]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix some stat-related races.
authorPaul Eggert <eggert@cs.ucla.edu>
Sat, 13 Oct 2012 00:52:01 +0000 (17:52 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sat, 13 Oct 2012 00:52:01 +0000 (17:52 -0700)
* fileio.c (Fwrite_region): Avoid race condition if a file is
removed or renamed by some other process immediately after Emacs
writes it but before Emacs stats it.  Do not assume that stat (or
fstat) succeeds.
* image.c (slurp_file): Resolve the file name with fopen + fstat
rather than stat + fopen.
(pbm_read_file) [0]: Remove unused code with stat race.
* process.c (allocate_pty) [HAVE_PTYS && !PTY_ITERATION && !PTY_OPEN]:
Remove ineffective code with stat race.

src/ChangeLog
src/fileio.c
src/image.c
src/process.c

index d753221b99640d143be13e146c2799f7edb46720..6c03ef0ba0a7f9a4461cd4a93a9f8d6552e3cdd8 100644 (file)
@@ -1,3 +1,16 @@
+2012-10-13  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Fix some stat-related races.
+       * fileio.c (Fwrite_region): Avoid race condition if a file is
+       removed or renamed by some other process immediately after Emacs
+       writes it but before Emacs stats it.  Do not assume that stat (or
+       fstat) succeeds.
+       * image.c (slurp_file): Resolve the file name with fopen + fstat
+       rather than stat + fopen.
+       (pbm_read_file) [0]: Remove unused code with stat race.
+       * process.c (allocate_pty) [HAVE_PTYS && !PTY_ITERATION && !PTY_OPEN]:
+       Remove ineffective code with stat race.
+
 2012-10-12  Stefan Monnier  <monnier@iro.umontreal.ca>
 
        * doc.c (get_doc_string): Don't signal an error if the file is missing.
index 5de5bc2b021483bb1cfaff29a097bb45aaedd22d..460eaf1e0b01f749276894ff0839b9ab256e1d03 100644 (file)
@@ -4545,6 +4545,7 @@ This calls `write-region-annotate-functions' at the start, and
   int save_errno = 0;
   const char *fn;
   struct stat st;
+  EMACS_TIME modtime;
   ptrdiff_t count = SPECPDL_INDEX ();
   int count1;
   Lisp_Object handler;
@@ -4757,12 +4758,19 @@ This calls `write-region-annotate-functions' at the start, and
     }
 #endif
 
+  modtime = invalid_emacs_time ();
+  if (visiting)
+    {
+      if (fstat (desc, &st) == 0)
+       modtime = get_stat_mtime (&st);
+      else
+       ok = 0, save_errno = errno;
+    }
+
   /* NFS can report a write failure now.  */
   if (emacs_close (desc) < 0)
     ok = 0, save_errno = errno;
 
-  stat (fn, &st);
-
   /* Discard the unwind protect for close_file_unwind.  */
   specpdl_ptr = specpdl + count1;
 
@@ -4790,9 +4798,9 @@ This calls `write-region-annotate-functions' at the start, and
   /* Do this before reporting IO error
      to avoid a "file has changed on disk" warning on
      next attempt to save.  */
-  if (visiting)
+  if (EMACS_TIME_VALID_P (modtime))
     {
-      current_buffer->modtime = get_stat_mtime (&st);
+      current_buffer->modtime = modtime;
       current_buffer->modtime_size = st.st_size;
     }
 
index 9b41cf7499307d27ea34e30138cabe01f5c3a23c..d52c3a29a27f53034cae4f4b5b6a9ee381c10d30 100644 (file)
@@ -2140,12 +2140,11 @@ x_find_image_file (Lisp_Object file)
 static unsigned char *
 slurp_file (char *file, ptrdiff_t *size)
 {
-  FILE *fp = NULL;
+  FILE *fp = fopen (file, "rb");
   unsigned char *buf = NULL;
   struct stat st;
 
-  if (stat (file, &st) == 0
-      && (fp = fopen (file, "rb")) != NULL
+  if (fp && fstat (fileno (fp), &st) == 0
       && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
       && (buf = xmalloc (st.st_size),
          fread (buf, 1, st.st_size, fp) == st.st_size))
@@ -5004,45 +5003,6 @@ pbm_scan_number (unsigned char **s, unsigned char *end)
 }
 
 
-#ifdef HAVE_NTGUI
-#if 0  /* Unused. ++kfs  */
-
-/* Read FILE into memory.  Value is a pointer to a buffer allocated
-   with xmalloc holding FILE's contents.  Value is null if an error
-   occurred.  *SIZE is set to the size of the file.  */
-
-static char *
-pbm_read_file (Lisp_Object file, int *size)
-{
-  FILE *fp = NULL;
-  char *buf = NULL;
-  struct stat st;
-
-  if (stat (SDATA (file), &st) == 0
-      && (fp = fopen (SDATA (file), "rb")) != NULL
-      && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
-      && (buf = xmalloc (st.st_size),
-         fread (buf, 1, st.st_size, fp) == st.st_size))
-    {
-      *size = st.st_size;
-      fclose (fp);
-    }
-  else
-    {
-      if (fp)
-       fclose (fp);
-      if (buf)
-       {
-         xfree (buf);
-         buf = NULL;
-       }
-    }
-
-  return buf;
-}
-#endif
-#endif /* HAVE_NTGUI */
-
 /* Load PBM image IMG for use on frame F.  */
 
 static bool
index 2cbce9d28ea94f54e3bfbe1036388ab1e067b6e5..d45a2c6e8e008f8808035ae1498f529f00c4b559 100644 (file)
@@ -646,23 +646,6 @@ allocate_pty (void)
        PTY_OPEN;
 #else /* no PTY_OPEN */
        {
-         { /* Some systems name their pseudoterminals so that there are gaps in
-              the usual sequence - for example, on HP9000/S700 systems, there
-              are no pseudoterminals with names ending in 'f'.  So we wait for
-              three failures in a row before deciding that we've reached the
-              end of the ptys.  */
-           int failed_count = 0;
-           struct stat stb;
-
-           if (stat (pty_name, &stb) < 0)
-             {
-               failed_count++;
-               if (failed_count >= 3)
-                 return -1;
-             }
-           else
-             failed_count = 0;
-         }
 #  ifdef O_NONBLOCK
          fd = emacs_open (pty_name, O_RDWR | O_NONBLOCK, 0);
 #  else