Fix more POSIX path lstat calls. Fix bug where close can return
authorJeremy Allison <jra@samba.org>
Wed, 25 Feb 2009 22:57:16 +0000 (14:57 -0800)
committerJeremy Allison <jra@samba.org>
Wed, 25 Feb 2009 22:57:16 +0000 (14:57 -0800)
failure if we have a pending modtime and the containing directory
of the file has been renamed (there is no POSIX "update time by
fd" call). This can't happen on Windows as the rename will fail
if there are open files beneath it. Will add a torture test
for this.
Jeremy.

source3/smbd/close.c

index 78b8123680f050748dffaeefe743104d35c2f7ea..d23b509af2dd16d82cc7f2ca9c6c5eaa00c82049 100644 (file)
@@ -471,6 +471,7 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
        SMB_STRUCT_STAT sbuf;
        struct smb_file_time ft;
        NTSTATUS status;
+       int ret = -1;
 
        ZERO_STRUCT(sbuf);
        ZERO_STRUCT(ft);
@@ -485,15 +486,19 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
 
        /* Ensure we have a valid stat struct for the source. */
        if (fsp->fh->fd != -1) {
-               if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
-                       return map_nt_error_from_unix(errno);
-               }
+               ret = SMB_VFS_FSTAT(fsp, &sbuf);
        } else {
-               if (SMB_VFS_STAT(fsp->conn,fsp->fsp_name,&sbuf) == -1) {
-                       return map_nt_error_from_unix(errno);
+               if (fsp->posix_open) {
+                       ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name,&sbuf);
+               } else {
+                       ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name,&sbuf);
                }
        }
 
+       if (ret == -1) {
+               return map_nt_error_from_unix(errno);
+       }
+
        if (!VALID_STAT(sbuf)) {
                /* if it doesn't seem to be a real file */
                return NT_STATUS_OK;
@@ -581,6 +586,13 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
         */
 
        saved_status4 = update_write_time_on_close(fsp);
+       if (NT_STATUS_EQUAL(saved_status4, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+               /* Someone renamed the file or a parent directory containing
+                * this file. We can't do anything about this, we don't have
+                * an "update timestamp by fd" call in POSIX. Eat the error. */
+
+               saved_status4 = NT_STATUS_OK;
+       }
 
        if (NT_STATUS_IS_OK(status)) {
                if (!NT_STATUS_IS_OK(saved_status1)) {