From: Paul Eggert Date: Sat, 13 Oct 2012 00:52:01 +0000 (-0700) Subject: Fix some stat-related races. X-Git-Tag: emacs-24.2.90~235^2~7^2~6 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=d6453ce49724b0a3bd24922ff0ad02f391d6e517;p=emacs.git 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. --- diff --git a/src/ChangeLog b/src/ChangeLog index d753221b996..6c03ef0ba0a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,16 @@ +2012-10-13 Paul Eggert + + 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 * 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 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; } 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) 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 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) 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