Fix bug #6520 time stamps - e.g. last mod time is not preserved when "unix extensions...
authorJeremy Allison <jra@samba.org>
Wed, 1 Jul 2009 23:58:14 +0000 (16:58 -0700)
committerKarolin Seeger <kseeger@samba.org>
Thu, 2 Jul 2009 06:30:03 +0000 (08:30 +0200)
Cancel out any pending "sticky" writes or "last write" changes when
doing a UNIX info level set.
Jeremy.
(cherry picked from commit b971860e01a3e616b0dd21990c054c8f8356f513)

source3/smbd/trans2.c

index 40b470125d5764175926462433fca43c2b48e648..cae13dfd94c852e8992756078a64a31de1b792b2 100644 (file)
@@ -4943,7 +4943,7 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
 
        if (setting_write_time) {
                /*
-                * This was a setfileinfo on an open file.
+                * This was a Windows setfileinfo on an open file.
                 * NT does this a lot. We also need to 
                 * set the time here, as it can be read by 
                 * FindFirst/FindNext and with the patch for bug #2045
@@ -6044,6 +6044,9 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
        NTSTATUS status = NT_STATUS_OK;
        bool delete_on_fail = False;
        enum perm_type ptype;
+       files_struct *all_fsps = NULL;
+       bool modify_mtime = true;
+       struct file_id id;
 
        ZERO_STRUCT(ft);
 
@@ -6192,13 +6195,38 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
        }
 
        /* Deal with any time changes. */
+       id = vfs_file_id_from_sbuf(conn, psbuf);
+       for(all_fsps = file_find_di_first(id); all_fsps;
+                       all_fsps = file_find_di_next(all_fsps)) {
+               /*
+                * We're setting the time explicitly for UNIX.
+                * Cancel any pending changes over all handles.
+                */
+               all_fsps->update_write_time_on_close = false;
+               TALLOC_FREE(all_fsps->update_write_time_event);
+       }
 
-       return smb_set_file_time(conn,
+       /*
+        * Override the "setting_write_time"
+        * parameter here as it almost does what
+        * we need. Just remember if we modified
+        * mtime and send the notify ourselves.
+        */
+       if (null_timespec(ft.mtime)) {
+               modify_mtime = false;
+       }
+
+       status = smb_set_file_time(conn,
                                fsp,
                                fname,
                                psbuf,
                                &ft,
-                               true);
+                               false);
+       if (modify_mtime) {
+               notify_fname(conn, NOTIFY_ACTION_MODIFIED,
+                       FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
+       }
+       return status;
 }
 
 /****************************************************************************