r3153: pvfs now passes the first 9 of the BASE-DELETE tests
authorAndrew Tridgell <tridge@samba.org>
Sun, 24 Oct 2004 12:39:15 +0000 (12:39 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:02:26 +0000 (13:02 -0500)
(This used to be commit f8041feaebc9170763ce04d2dd90cfc1c7889c21)

source4/ntvfs/common/opendb.c
source4/ntvfs/posix/pvfs_open.c
source4/ntvfs/posix/pvfs_setfileinfo.c

index f074c31f6eb5bb3316387b8bf342305aa14e0fe6..3def23f1907d808a2f1f4df3a6e983f4e09f1c47 100644 (file)
@@ -169,6 +169,17 @@ static BOOL share_conflict(struct odb_entry *e1, struct odb_entry *e2)
                return True;
        }
 
                return True;
        }
 
+       if ((e1->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) ||
+           (e2->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) {
+               return True;
+       }
+
+       if ((e1->access_mask & STD_RIGHT_DELETE_ACCESS) &&
+           !(e2->share_access & NTCREATEX_SHARE_ACCESS_DELETE)) {
+               return True;
+       }
+           
+
        return False;
 }
 
        return False;
 }
 
@@ -256,7 +267,8 @@ NTSTATUS odb_close_file(struct odb_lock *lck, uint16_t fnum)
                    odb->server == elist[i].server &&
                    odb->tid == elist[i].tid) {
                        if (i < count-1) {
                    odb->server == elist[i].server &&
                    odb->tid == elist[i].tid) {
                        if (i < count-1) {
-                               memmove(elist+i, elist+i+1, count - (i+1));
+                               memmove(elist+i, elist+i+1, 
+                                       (count - (i+1)) * sizeof(struct odb_entry));
                        }
                        break;
                }
                        }
                        break;
                }
@@ -281,3 +293,45 @@ NTSTATUS odb_close_file(struct odb_lock *lck, uint16_t fnum)
 
        return status;
 }
 
        return status;
 }
+
+
+/*
+  update create options on an open file
+*/
+NTSTATUS odb_set_create_options(struct odb_lock *lck, 
+                               uint16_t fnum, uint32_t create_options)
+{
+       struct odb_context *odb = lck->odb;
+       TDB_DATA dbuf;
+       struct odb_entry *elist;
+       int i, count;
+       NTSTATUS status;
+
+       dbuf = tdb_fetch(odb->w->tdb, lck->key);
+       if (dbuf.dptr == NULL) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       elist = (struct odb_entry *)dbuf.dptr;
+       count = dbuf.dsize / sizeof(struct odb_entry);
+
+       /* find the entry, and modify it */
+       for (i=0;i<count;i++) {
+               if (fnum == elist[i].fnum &&
+                   odb->server == elist[i].server &&
+                   odb->tid == elist[i].tid) {
+                       elist[i].create_options = create_options;
+                       break;
+               }
+       }
+
+       if (tdb_store(odb->w->tdb, lck->key, dbuf, TDB_REPLACE) != 0) {
+               status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+       } else {
+               status = NT_STATUS_OK;
+       }
+
+       free(dbuf.dptr);
+
+       return status;
+}
index 90de303a9d9762ac23d16525c34a734b7a3586e7..7c1e1645759745d8844f4f09f990eba7aaccaa6d 100644 (file)
@@ -55,6 +55,14 @@ static int pvfs_dir_fd_destructor(void *p)
        struct pvfs_file *f = p;
        DLIST_REMOVE(f->pvfs->open_files, f);
        idr_remove(f->pvfs->idtree_fnum, f->fnum);
        struct pvfs_file *f = p;
        DLIST_REMOVE(f->pvfs->open_files, f);
        idr_remove(f->pvfs->idtree_fnum, f->fnum);
+
+       if (f->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
+               if (rmdir(f->name->full_name) != 0) {
+                       DEBUG(0,("pvfs_close: failed to rmdir '%s'\n", 
+                                f->name->full_name));
+               }
+       }
+
        return 0;
 }
 
        return 0;
 }
 
@@ -106,6 +114,12 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
                return NT_STATUS_NO_MEMORY;
        }
 
                return NT_STATUS_NO_MEMORY;
        }
 
+       fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX);
+       if (fnum == -1) {
+               talloc_free(f);
+               return NT_STATUS_TOO_MANY_OPENED_FILES;
+       }
+
        f->fnum = fnum;
        f->fd = -1;
        f->name = talloc_steal(f, name);
        f->fnum = fnum;
        f->fd = -1;
        f->name = talloc_steal(f, name);
@@ -118,12 +132,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
        f->create_options = io->generic.in.create_options;
        f->share_access = io->generic.in.share_access;
 
        f->create_options = io->generic.in.create_options;
        f->share_access = io->generic.in.share_access;
 
-       fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX);
-       if (fnum == -1) {
-               talloc_free(f);
-               return NT_STATUS_TOO_MANY_OPENED_FILES;
-       }
-
        DLIST_ADD(pvfs->open_files, f);
 
        /* TODO: should we check in the opendb? Do directory opens 
        DLIST_ADD(pvfs->open_files, f);
 
        /* TODO: should we check in the opendb? Do directory opens 
@@ -196,16 +204,23 @@ static int pvfs_fd_destructor(void *p)
 
        lck = odb_lock(f, f->pvfs->odb_context, &f->locking_key);
        if (lck == NULL) {
 
        lck = odb_lock(f, f->pvfs->odb_context, &f->locking_key);
        if (lck == NULL) {
-               DEBUG(0,("Unabled to lock opendb for close\n"));
+               DEBUG(0,("Unable to lock opendb for close\n"));
                return 0;
        }
 
        status = odb_close_file(lck, f->fnum);
        if (!NT_STATUS_IS_OK(status)) {
                return 0;
        }
 
        status = odb_close_file(lck, f->fnum);
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0,("Unabled to remove opendb entry for '%s' - %s\n", 
+               DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n", 
                         f->name->full_name, nt_errstr(status)));
        }
 
                         f->name->full_name, nt_errstr(status)));
        }
 
+       if (f->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
+               if (unlink(f->name->full_name) != 0) {
+                       DEBUG(0,("pvfs_close: failed to delete '%s'\n", 
+                                f->name->full_name));
+               }
+       }
+
        return 0;
 }
 
        return 0;
 }
 
@@ -386,6 +401,15 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
                return pvfs_open_directory(pvfs, req, name, io);
        }
 
                return pvfs_open_directory(pvfs, req, name, io);
        }
 
+       create_options = io->generic.in.create_options;
+       share_access   = io->generic.in.share_access;
+       access_mask    = io->generic.in.access_mask;
+
+       /* certain create options are not allowed */
+       if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) &&
+           !(share_access & NTCREATEX_SHARE_ACCESS_DELETE)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
        switch (io->generic.in.open_disposition) {
        case NTCREATEX_DISP_SUPERSEDE:
 
        switch (io->generic.in.open_disposition) {
        case NTCREATEX_DISP_SUPERSEDE:
@@ -481,10 +505,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
 
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
 
-       create_options = io->generic.in.create_options;
-       share_access   = io->generic.in.share_access;
-       access_mask    = io->generic.in.access_mask;
-
        /* see if we are allowed to open at the same time as existing opens */
        status = odb_open_file(lck, fnum, share_access, create_options, access_mask);
        if (!NT_STATUS_IS_OK(status)) {
        /* see if we are allowed to open at the same time as existing opens */
        status = odb_open_file(lck, fnum, share_access, create_options, access_mask);
        if (!NT_STATUS_IS_OK(status)) {
@@ -492,22 +512,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
                return status;
        }
 
                return status;
        }
 
-       /* do the actual open */
-       fd = open(name->full_name, flags);
-       if (fd == -1) {
-               return pvfs_map_errno(pvfs, errno);
-       }
-
-       /* re-resolve the open fd */
-       status = pvfs_resolve_name_fd(pvfs, fd, name);
-       if (!NT_STATUS_IS_OK(status)) {
-               close(fd);
-               idr_remove(pvfs->idtree_fnum, fnum);
-               return status;
-       }
-
        f->fnum = fnum;
        f->fnum = fnum;
-       f->fd = fd;
+       f->fd = -1;
        f->name = talloc_steal(f, name);
        f->session = req->session;
        f->smbpid = req->smbpid;
        f->name = talloc_steal(f, name);
        f->session = req->session;
        f->smbpid = req->smbpid;
@@ -524,6 +530,20 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
           abnormal termination */
        talloc_set_destructor(f, pvfs_fd_destructor);
 
           abnormal termination */
        talloc_set_destructor(f, pvfs_fd_destructor);
 
+       /* do the actual open */
+       fd = open(name->full_name, flags);
+       if (fd == -1) {
+               return pvfs_map_errno(pvfs, errno);
+       }
+
+       f->fd = fd;
+
+       /* re-resolve the open fd */
+       status = pvfs_resolve_name_fd(pvfs, fd, name);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
        io->generic.out.oplock_level  = NO_OPLOCK;
        io->generic.out.fnum          = f->fnum;
        io->generic.out.create_action = NTCREATEX_ACTION_EXISTED;
        io->generic.out.oplock_level  = NO_OPLOCK;
        io->generic.out.fnum          = f->fnum;
        io->generic.out.create_action = NTCREATEX_ACTION_EXISTED;
@@ -619,3 +639,31 @@ NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs,
 
        return NT_STATUS_OK;
 }
 
        return NT_STATUS_OK;
 }
+
+
+/*
+  change the create options on an already open file
+*/
+NTSTATUS pvfs_change_create_options(struct pvfs_state *pvfs,
+                                   struct smbsrv_request *req, 
+                                   struct pvfs_file *f, uint32_t create_options)
+{
+       struct odb_lock *lck;
+       NTSTATUS status;
+
+       if (f->create_options == create_options) {
+               return NT_STATUS_OK;
+       }
+
+       lck = odb_lock(req, pvfs->odb_context, &f->locking_key);
+       if (lck == NULL) {
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+
+       status = odb_set_create_options(lck, f->fnum, create_options);
+       if (NT_STATUS_IS_OK(status)) {
+               f->create_options = create_options;
+       }
+
+       return status;
+}
index 8892c92c3ce5c1b9126c2c7ed2be59df5d000401..0de87b858416fd6d686263eac4937679d19a5483 100644 (file)
@@ -33,6 +33,7 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
        struct pvfs_state *pvfs = ntvfs->private_data;
        struct utimbuf unix_times;
        struct pvfs_file *f;
        struct pvfs_state *pvfs = ntvfs->private_data;
        struct utimbuf unix_times;
        struct pvfs_file *f;
+       uint32_t create_options;
 
        f = pvfs_find_fd(pvfs, req, info->generic.file.fnum);
        if (!f) {
 
        f = pvfs_find_fd(pvfs, req, info->generic.file.fnum);
        if (!f) {
@@ -65,6 +66,18 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
                        return NT_STATUS_ACCESS_DENIED;
                }
                break;
                        return NT_STATUS_ACCESS_DENIED;
                }
                break;
+       case RAW_SFILEINFO_DISPOSITION_INFO:
+               if (!(f->access_mask & STD_RIGHT_DELETE_ACCESS)) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+               create_options = f->create_options;
+               if (info->disposition_info.in.delete_on_close) {
+                       create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
+               } else {
+                       create_options &= ~NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
+               }
+               return pvfs_change_create_options(pvfs, req, f, create_options);
        }
        }
+
        return NT_STATUS_OK;
 }
        return NT_STATUS_OK;
 }