Commit d6453ce4 authored by Paul Eggert's avatar 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.
parent 06485aa8
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.
......
......@@ -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;
}
......
......@@ -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
......
......@@ -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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment