+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.
int save_errno = 0;
const char *fn;
struct stat st;
+ EMACS_TIME modtime;
ptrdiff_t count = SPECPDL_INDEX ();
int count1;
Lisp_Object handler;
}
#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;
/* 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;
}
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))
}
-#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
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