=== modified file 'src/ChangeLog' --- src/ChangeLog 2013-01-19 00:40:07 +0000 +++ src/ChangeLog 2013-01-19 02:32:33 +0000 @@ -1,5 +1,18 @@ 2013-01-19 Paul Eggert + Work around bug in CIFS and vboxsf file systems (Bug#13149). + The bug was observed on Ubuntu operating inside a virtual machine, + editing files mounted via CIFS or vboxsf from the MS Windows 7 host. + The workaround introduces a race condition on non-buggy hosts, + but it's an unlikely race and anyway there's a nearly identical + nearby race that can't be fixed. + * fileio.c (valid_timestamp_file_system, timestamp_file_system): + New static vars. + (Fwrite_region): Test for file system time stamp bug. + (init_fileio): New function. + * lisp.h (init_fileio): Declare it. + * emacs.c (main): Call it. + * fileio.c (Finsert_file_contents): Simplify new diagnostic and make it more consistent with other stat-failure diagnostics. === modified file 'src/emacs.c' --- src/emacs.c 2013-01-13 20:03:01 +0000 +++ src/emacs.c 2013-01-19 02:32:33 +0000 @@ -1317,6 +1317,7 @@ } init_callproc (); /* Must follow init_cmdargs but not init_sys_modes. */ + init_fileio (); init_lread (); #ifdef WINDOWSNT /* Check to see if Emacs has been installed correctly. */ === modified file 'src/fileio.c' --- src/fileio.c 2013-01-19 00:40:07 +0000 +++ src/fileio.c 2013-01-19 02:32:33 +0000 @@ -103,6 +103,11 @@ /* Set by auto_save_1 if an error occurred during the last auto-save. */ static bool auto_save_error_occurred; +/* If VALID_TIMESTAMP_FILE_SYSTEM, then TIMESTAMP_FILE_SYSTEM is the device + number of a file system where time stamps were observed to to work. */ +static bool valid_timestamp_file_system; +static dev_t timestamp_file_system; + /* The symbol bound to coding-system-for-read when insert-file-contents is called for recovering a file. This is not an actual coding system name, but just an indicator to tell @@ -4971,6 +4976,48 @@ /* Discard the unwind protect for close_file_unwind. */ specpdl_ptr = specpdl + count1; + /* Some file systems have a bug where st_mtime is not updated + properly after a write. For example, CIFS might not see the + st_mtime change until after the file is opened again. + + Attempt to detect this file system bug, and update MODTIME to the + newer st_mtime if the bug appears to be present. This introduces + a race condition, so to avoid most instances of the race condition + on non-buggy file systems, skip this check if the most recently + encountered non-buggy file system was the current file system. + + A race condition can occur if some other process modifies the + file between the fstat above and the fstat below, but the race is + unlikely and a similar race between the last write and the fstat + above cannot possibly be closed anyway. */ + + if (EMACS_TIME_VALID_P (modtime) + && ! (valid_timestamp_file_system && st.st_dev == timestamp_file_system)) + { + int desc1 = emacs_open (fn, O_WRONLY, 0); + if (0 <= desc1) + { + struct stat st1; + if (fstat (desc1, &st1) == 0 + && st.st_dev == st1.st_dev && st.st_ino == st1.st_ino) + { + EMACS_TIME modtime1 = get_stat_mtime (&st1); + if (EMACS_TIME_EQ (modtime, modtime1) + && st.st_size == st1.st_size) + { + timestamp_file_system = st.st_dev; + valid_timestamp_file_system = 1; + } + else + { + st.st_size = st1.st_size; + modtime = modtime1; + } + } + emacs_close (desc1); + } + } + /* Call write-region-post-annotation-function. */ while (CONSP (Vwrite_region_annotation_buffers)) { @@ -5768,6 +5815,12 @@ void +init_fileio (void) +{ + valid_timestamp_file_system = 0; +} + +void syms_of_fileio (void) { DEFSYM (Qoperations, "operations"); === modified file 'src/lisp.h' --- src/lisp.h 2013-01-17 06:29:40 +0000 +++ src/lisp.h 2013-01-19 02:32:33 +0000 @@ -3299,6 +3299,7 @@ extern bool internal_delete_file (Lisp_Object); extern bool file_directory_p (const char *); extern bool file_accessible_directory_p (const char *); +extern void init_fileio (void); extern void syms_of_fileio (void); extern Lisp_Object make_temp_name (Lisp_Object, bool); extern Lisp_Object Qdelete_file;