aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2012-10-12 17:52:01 -0700
committerPaul Eggert2012-10-12 17:52:01 -0700
commitd6453ce49724b0a3bd24922ff0ad02f391d6e517 (patch)
tree655b2ca5f792dc2058ad731a4c1bb5af89163b28 /src
parent06485aa8215af39f9f5f999933aa39d349a2bdf9 (diff)
downloademacs-d6453ce49724b0a3bd24922ff0ad02f391d6e517.tar.gz
emacs-d6453ce49724b0a3bd24922ff0ad02f391d6e517.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog13
-rw-r--r--src/fileio.c16
-rw-r--r--src/image.c44
-rw-r--r--src/process.c17
4 files changed, 27 insertions, 63 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index d753221b996..6c03ef0ba0a 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,16 @@
12012-10-13 Paul Eggert <eggert@cs.ucla.edu>
2
3 Fix some stat-related races.
4 * fileio.c (Fwrite_region): Avoid race condition if a file is
5 removed or renamed by some other process immediately after Emacs
6 writes it but before Emacs stats it. Do not assume that stat (or
7 fstat) succeeds.
8 * image.c (slurp_file): Resolve the file name with fopen + fstat
9 rather than stat + fopen.
10 (pbm_read_file) [0]: Remove unused code with stat race.
11 * process.c (allocate_pty) [HAVE_PTYS && !PTY_ITERATION && !PTY_OPEN]:
12 Remove ineffective code with stat race.
13
12012-10-12 Stefan Monnier <monnier@iro.umontreal.ca> 142012-10-12 Stefan Monnier <monnier@iro.umontreal.ca>
2 15
3 * doc.c (get_doc_string): Don't signal an error if the file is missing. 16 * doc.c (get_doc_string): Don't signal an error if the file is missing.
diff --git a/src/fileio.c b/src/fileio.c
index 5de5bc2b021..460eaf1e0b0 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -4545,6 +4545,7 @@ This calls `write-region-annotate-functions' at the start, and
4545 int save_errno = 0; 4545 int save_errno = 0;
4546 const char *fn; 4546 const char *fn;
4547 struct stat st; 4547 struct stat st;
4548 EMACS_TIME modtime;
4548 ptrdiff_t count = SPECPDL_INDEX (); 4549 ptrdiff_t count = SPECPDL_INDEX ();
4549 int count1; 4550 int count1;
4550 Lisp_Object handler; 4551 Lisp_Object handler;
@@ -4757,12 +4758,19 @@ This calls `write-region-annotate-functions' at the start, and
4757 } 4758 }
4758#endif 4759#endif
4759 4760
4761 modtime = invalid_emacs_time ();
4762 if (visiting)
4763 {
4764 if (fstat (desc, &st) == 0)
4765 modtime = get_stat_mtime (&st);
4766 else
4767 ok = 0, save_errno = errno;
4768 }
4769
4760 /* NFS can report a write failure now. */ 4770 /* NFS can report a write failure now. */
4761 if (emacs_close (desc) < 0) 4771 if (emacs_close (desc) < 0)
4762 ok = 0, save_errno = errno; 4772 ok = 0, save_errno = errno;
4763 4773
4764 stat (fn, &st);
4765
4766 /* Discard the unwind protect for close_file_unwind. */ 4774 /* Discard the unwind protect for close_file_unwind. */
4767 specpdl_ptr = specpdl + count1; 4775 specpdl_ptr = specpdl + count1;
4768 4776
@@ -4790,9 +4798,9 @@ This calls `write-region-annotate-functions' at the start, and
4790 /* Do this before reporting IO error 4798 /* Do this before reporting IO error
4791 to avoid a "file has changed on disk" warning on 4799 to avoid a "file has changed on disk" warning on
4792 next attempt to save. */ 4800 next attempt to save. */
4793 if (visiting) 4801 if (EMACS_TIME_VALID_P (modtime))
4794 { 4802 {
4795 current_buffer->modtime = get_stat_mtime (&st); 4803 current_buffer->modtime = modtime;
4796 current_buffer->modtime_size = st.st_size; 4804 current_buffer->modtime_size = st.st_size;
4797 } 4805 }
4798 4806
diff --git a/src/image.c b/src/image.c
index 9b41cf74993..d52c3a29a27 100644
--- a/src/image.c
+++ b/src/image.c
@@ -2140,12 +2140,11 @@ x_find_image_file (Lisp_Object file)
2140static unsigned char * 2140static unsigned char *
2141slurp_file (char *file, ptrdiff_t *size) 2141slurp_file (char *file, ptrdiff_t *size)
2142{ 2142{
2143 FILE *fp = NULL; 2143 FILE *fp = fopen (file, "rb");
2144 unsigned char *buf = NULL; 2144 unsigned char *buf = NULL;
2145 struct stat st; 2145 struct stat st;
2146 2146
2147 if (stat (file, &st) == 0 2147 if (fp && fstat (fileno (fp), &st) == 0
2148 && (fp = fopen (file, "rb")) != NULL
2149 && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX) 2148 && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
2150 && (buf = xmalloc (st.st_size), 2149 && (buf = xmalloc (st.st_size),
2151 fread (buf, 1, st.st_size, fp) == st.st_size)) 2150 fread (buf, 1, st.st_size, fp) == st.st_size))
@@ -5004,45 +5003,6 @@ pbm_scan_number (unsigned char **s, unsigned char *end)
5004} 5003}
5005 5004
5006 5005
5007#ifdef HAVE_NTGUI
5008#if 0 /* Unused. ++kfs */
5009
5010/* Read FILE into memory. Value is a pointer to a buffer allocated
5011 with xmalloc holding FILE's contents. Value is null if an error
5012 occurred. *SIZE is set to the size of the file. */
5013
5014static char *
5015pbm_read_file (Lisp_Object file, int *size)
5016{
5017 FILE *fp = NULL;
5018 char *buf = NULL;
5019 struct stat st;
5020
5021 if (stat (SDATA (file), &st) == 0
5022 && (fp = fopen (SDATA (file), "rb")) != NULL
5023 && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
5024 && (buf = xmalloc (st.st_size),
5025 fread (buf, 1, st.st_size, fp) == st.st_size))
5026 {
5027 *size = st.st_size;
5028 fclose (fp);
5029 }
5030 else
5031 {
5032 if (fp)
5033 fclose (fp);
5034 if (buf)
5035 {
5036 xfree (buf);
5037 buf = NULL;
5038 }
5039 }
5040
5041 return buf;
5042}
5043#endif
5044#endif /* HAVE_NTGUI */
5045
5046/* Load PBM image IMG for use on frame F. */ 5006/* Load PBM image IMG for use on frame F. */
5047 5007
5048static bool 5008static bool
diff --git a/src/process.c b/src/process.c
index 2cbce9d28ea..d45a2c6e8e0 100644
--- a/src/process.c
+++ b/src/process.c
@@ -646,23 +646,6 @@ allocate_pty (void)
646 PTY_OPEN; 646 PTY_OPEN;
647#else /* no PTY_OPEN */ 647#else /* no PTY_OPEN */
648 { 648 {
649 { /* Some systems name their pseudoterminals so that there are gaps in
650 the usual sequence - for example, on HP9000/S700 systems, there
651 are no pseudoterminals with names ending in 'f'. So we wait for
652 three failures in a row before deciding that we've reached the
653 end of the ptys. */
654 int failed_count = 0;
655 struct stat stb;
656
657 if (stat (pty_name, &stb) < 0)
658 {
659 failed_count++;
660 if (failed_count >= 3)
661 return -1;
662 }
663 else
664 failed_count = 0;
665 }
666# ifdef O_NONBLOCK 649# ifdef O_NONBLOCK
667 fd = emacs_open (pty_name, O_RDWR | O_NONBLOCK, 0); 650 fd = emacs_open (pty_name, O_RDWR | O_NONBLOCK, 0);
668# else 651# else