Fix more POSIX path lstat calls. Fix bug where close can return
[jra/samba/.git] / source3 / smbd / close.c
index e484fa8e01153431bdc540a944bff0cda0c8c0ed..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;
@@ -553,6 +558,11 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
                return NT_STATUS_OK;
        }
 
+       /* Remove the oplock before potentially deleting the file. */
+       if(fsp->oplock_type) {
+               release_file_oplock(fsp);
+       }
+
        /* If this is an old DOS or FCB open and we have multiple opens on
           the same handle we only have one share mode. Ensure we only remove
           the share mode on the last close. */
@@ -562,10 +572,6 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
                saved_status3 = close_remove_share_mode(fsp, close_type);
        }
 
-       if(fsp->oplock_type) {
-               release_file_oplock(fsp);
-       }
-
        locking_close_file(smbd_messaging_context(), fsp);
 
        status = fd_close(fsp);
@@ -580,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)) {