Now on revision 113444. ------------------------------------------------------------ revno: 113444 committer: Paul Eggert branch nick: trunk timestamp: Wed 2013-07-17 19:12:59 -0700 message: * charset.c: Fix file descriptor leaks and errno issues. Include . (load_charset_map_from_file): Don't leak file descriptor on error. Use plain record_xmalloc since the allocation is larger than MAX_ALLOCA; that's simpler here. Simplify test for exhaustion of entries. * eval.c (record_unwind_protect_nothing): * fileio.c (fclose_unwind): New functions. * lread.c (load_unwind): Remove. All uses replaced by fclose_unwind. The replacement doesn't block input, but that no longer seems necessary. diff: === modified file 'src/ChangeLog' --- src/ChangeLog 2013-07-17 17:24:54 +0000 +++ src/ChangeLog 2013-07-18 02:12:59 +0000 @@ -1,3 +1,18 @@ +2013-07-18 Paul Eggert + + * charset.c: Fix file descriptor leaks and errno issues. + Include . + (load_charset_map_from_file): Don't leak file descriptor on error. + Use plain record_xmalloc since the allocation is larger than + MAX_ALLOCA; that's simpler here. Simplify test for exhaustion + of entries. + * eval.c (record_unwind_protect_nothing): + * fileio.c (fclose_unwind): + New functions. + * lread.c (load_unwind): Remove. All uses replaced by fclose_unwind. + The replacement doesn't block input, but that no longer seems + necessary. + 2013-07-17 Paul Eggert * lread.c: Fix file descriptor leaks and errno issues. === modified file 'src/charset.c' --- src/charset.c 2013-07-16 06:39:49 +0000 +++ src/charset.c 2013-07-18 02:12:59 +0000 @@ -28,6 +28,7 @@ #define CHARSET_INLINE EXTERN_INLINE +#include #include #include #include @@ -477,7 +478,8 @@ `file-name-handler-alist' to avoid running any Lisp code. */ static void -load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, int control_flag) +load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, + int control_flag) { unsigned min_code = CHARSET_MIN_CODE (charset); unsigned max_code = CHARSET_MAX_CODE (charset); @@ -487,21 +489,26 @@ struct charset_map_entries *head, *entries; int n_entries; ptrdiff_t count; - USE_SAFE_ALLOCA; suffixes = list2 (build_string (".map"), build_string (".TXT")); count = SPECPDL_INDEX (); + record_unwind_protect_nothing (); specbind (Qfile_name_handler_alist, Qnil); fd = openp (Vcharset_map_path, mapfile, suffixes, NULL, Qnil); - unbind_to (count, Qnil); - if (fd < 0 - || ! (fp = fdopen (fd, "r"))) - error ("Failure in loading charset map: %s", SDATA (mapfile)); + fp = fd < 0 ? 0 : fdopen (fd, "r"); + if (!fp) + { + int open_errno = errno; + emacs_close (fd); + report_file_errno ("Loading charset map", mapfile, open_errno); + } + set_unwind_protect_ptr (count, fclose_unwind, fp); + unbind_to (count + 1, Qnil); - /* Use SAFE_ALLOCA instead of alloca, as `charset_map_entries' is + /* Use record_xmalloc, as `charset_map_entries' is large (larger than MAX_ALLOCA). */ - head = SAFE_ALLOCA (sizeof *head); + head = record_xmalloc (sizeof *head); entries = head; memset (entries, 0, sizeof (struct charset_map_entries)); @@ -530,9 +537,9 @@ if (from < min_code || to > max_code || from > to || c > MAX_CHAR) continue; - if (n_entries > 0 && (n_entries % 0x10000) == 0) + if (n_entries == 0x10000) { - entries->next = SAFE_ALLOCA (sizeof *entries->next); + entries->next = record_xmalloc (sizeof *entries->next); entries = entries->next; memset (entries, 0, sizeof (struct charset_map_entries)); n_entries = 0; @@ -544,9 +551,10 @@ n_entries++; } fclose (fp); + clear_unwind_protect (count); load_charset_map (charset, head, n_entries, control_flag); - SAFE_FREE (); + unbind_to (count, Qnil); } static void === modified file 'src/eval.c' --- src/eval.c 2013-07-17 17:24:54 +0000 +++ src/eval.c 2013-07-18 02:12:59 +0000 @@ -3190,6 +3190,8 @@ } } +/* Push unwind-protect entries of various types. */ + void record_unwind_protect (void (*function) (Lisp_Object), Lisp_Object arg) { @@ -3229,6 +3231,18 @@ do_nothing (void) {} +/* Push an unwind-protect entry that does nothing, so that + set_unwind_protect_ptr can overwrite it later. */ + +void +record_unwind_protect_nothing (void) +{ + record_unwind_protect_void (do_nothing); +} + +/* Clear the unwind-protect entry COUNT, so that it does nothing. + It need not be at the top of the stack. */ + void clear_unwind_protect (ptrdiff_t count) { @@ -3237,6 +3251,10 @@ p->unwind_void.func = do_nothing; } +/* Set the unwind-protect entry COUNT so that it invokes FUNC (ARG). + It need not be at the top of the stack. Discard the entry's + previous value without invoking it. */ + void set_unwind_protect_ptr (ptrdiff_t count, void (*func) (void *), void *arg) { @@ -3246,6 +3264,9 @@ p->unwind_ptr.arg = arg; } +/* Pop and execute entries from the unwind-protect stack until the + depth COUNT is reached. Return VALUE. */ + Lisp_Object unbind_to (ptrdiff_t count, Lisp_Object value) { === modified file 'src/fileio.c' --- src/fileio.c 2013-07-17 17:24:54 +0000 +++ src/fileio.c 2013-07-18 02:12:59 +0000 @@ -220,6 +220,13 @@ emacs_close (fd); } +void +fclose_unwind (void *arg) +{ + FILE *stream = arg; + fclose (stream); +} + /* Restore point, having saved it as a marker. */ void === modified file 'src/lisp.h' --- src/lisp.h 2013-07-17 17:24:54 +0000 +++ src/lisp.h 2013-07-18 02:12:59 +0000 @@ -3743,6 +3743,7 @@ extern void record_unwind_protect_int (void (*) (int), int); extern void record_unwind_protect_ptr (void (*) (void *), void *); extern void record_unwind_protect_void (void (*) (void)); +extern void record_unwind_protect_nothing (void); extern void clear_unwind_protect (ptrdiff_t); extern void set_unwind_protect_ptr (ptrdiff_t, void (*) (void *), void *); extern Lisp_Object unbind_to (ptrdiff_t, Lisp_Object); @@ -3827,6 +3828,7 @@ extern Lisp_Object expand_and_dir_to_file (Lisp_Object, Lisp_Object); EXFUN (Fread_file_name, 6); /* Not a normal DEFUN. */ extern void close_file_unwind (int); +extern void fclose_unwind (void *); extern void restore_point_unwind (Lisp_Object); extern _Noreturn void report_file_errno (const char *, Lisp_Object, int); extern _Noreturn void report_file_error (const char *, Lisp_Object); === modified file 'src/lread.c' --- src/lread.c 2013-07-17 17:24:54 +0000 +++ src/lread.c 2013-07-18 02:12:59 +0000 @@ -145,7 +145,6 @@ static void readevalloop (Lisp_Object, FILE *, Lisp_Object, bool, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); -static void load_unwind (void *); /* Functions that read one byte from the current source READCHARFUN or unreads one byte. If the integer argument C is -1, it returns @@ -1317,7 +1316,7 @@ } if (! stream) report_file_error ("Opening stdio stream", file); - set_unwind_protect_ptr (fd_index, load_unwind, stream); + set_unwind_protect_ptr (fd_index, fclose_unwind, stream); if (! NILP (Vpurify_flag)) Vpreloaded_file_list = Fcons (Fpurecopy (file), Vpreloaded_file_list); @@ -1387,18 +1386,6 @@ return Qt; } - -static void -load_unwind (void *arg) -{ - FILE *stream = arg; - if (stream != NULL) - { - block_input (); - fclose (stream); - unblock_input (); - } -} static bool complete_filename_p (Lisp_Object pathname) ------------------------------------------------------------ revno: 113443 committer: Paul Eggert branch nick: trunk timestamp: Wed 2013-07-17 10:24:54 -0700 message: * lread.c: Fix file descriptor leaks and errno issues. (Fload): Close some races that leaked fds or streams when 'load' was interrupted. (Fload, openp): Report error number of last nontrivial failure to open. ENOENT counts as trivial. * eval.c (do_nothing, clear_unwind_protect, set_unwind_protect_ptr): New functions. * fileio.c (close_file_unwind): No need to test whether FD is nonnegative, now that the function is always called with a nonnegative arg. * lisp.h (set_unwind_protect_ptr, set_unwind_protect_int): Remove. All uses replaced with ... (clear_unwind_protect, set_unwind_protect_ptr): New decls. diff: === modified file 'src/ChangeLog' --- src/ChangeLog 2013-07-17 04:37:27 +0000 +++ src/ChangeLog 2013-07-17 17:24:54 +0000 @@ -1,5 +1,18 @@ 2013-07-17 Paul Eggert + * lread.c: Fix file descriptor leaks and errno issues. + (Fload): Close some races that leaked fds or streams when 'load' + was interrupted. + (Fload, openp): Report error number of last nontrivial failure to open. + ENOENT counts as trivial. + * eval.c (do_nothing, clear_unwind_protect, set_unwind_protect_ptr): + New functions. + * fileio.c (close_file_unwind): No need to test whether FD is nonnegative, + now that the function is always called with a nonnegative arg. + * lisp.h (set_unwind_protect_ptr, set_unwind_protect_int): Remove. + All uses replaced with ... + (clear_unwind_protect, set_unwind_protect_ptr): New decls. + A few more minor file errno-reporting bugs. * callproc.c (Fcall_process): * doc.c (Fsnarf_documentation): === modified file 'src/editfns.c' --- src/editfns.c 2013-07-16 21:35:45 +0000 +++ src/editfns.c 2013-07-17 17:24:54 +0000 @@ -4238,7 +4238,7 @@ else { buf = xrealloc (buf, bufsize); - set_unwind_protect_ptr (buf_save_value_index, buf); + set_unwind_protect_ptr (buf_save_value_index, xfree, buf); } p = buf + used; === modified file 'src/eval.c' --- src/eval.c 2013-07-16 21:35:45 +0000 +++ src/eval.c 2013-07-17 17:24:54 +0000 @@ -3225,6 +3225,27 @@ grow_specpdl (); } +static void +do_nothing (void) +{} + +void +clear_unwind_protect (ptrdiff_t count) +{ + union specbinding *p = specpdl + count; + p->unwind_void.kind = SPECPDL_UNWIND_VOID; + p->unwind_void.func = do_nothing; +} + +void +set_unwind_protect_ptr (ptrdiff_t count, void (*func) (void *), void *arg) +{ + union specbinding *p = specpdl + count; + p->unwind_ptr.kind = SPECPDL_UNWIND_PTR; + p->unwind_ptr.func = func; + p->unwind_ptr.arg = arg; +} + Lisp_Object unbind_to (ptrdiff_t count, Lisp_Object value) { === modified file 'src/fileio.c' --- src/fileio.c 2013-07-17 04:37:27 +0000 +++ src/fileio.c 2013-07-17 17:24:54 +0000 @@ -217,8 +217,7 @@ void close_file_unwind (int fd) { - if (0 <= fd) - emacs_close (fd); + emacs_close (fd); } /* Restore point, having saved it as a marker. */ @@ -4029,7 +4028,7 @@ if (this < 0) report_file_error ("Read error", orig_filename); emacs_close (fd); - set_unwind_protect_int (fd_index, -1); + clear_unwind_protect (fd_index); if (unprocessed > 0) { @@ -4270,7 +4269,7 @@ Vdeactivate_mark = Qt; emacs_close (fd); - set_unwind_protect_int (fd_index, -1); + clear_unwind_protect (fd_index); if (how_much < 0) report_file_error ("Read error", orig_filename); === modified file 'src/lisp.h' --- src/lisp.h 2013-07-16 21:49:32 +0000 +++ src/lisp.h 2013-07-17 17:24:54 +0000 @@ -2744,18 +2744,6 @@ return specpdl_ptr - specpdl; } -LISP_INLINE void -set_unwind_protect_ptr (ptrdiff_t count, void *arg) -{ - specpdl[count].unwind_ptr.arg = arg; -} - -LISP_INLINE void -set_unwind_protect_int (ptrdiff_t count, int arg) -{ - specpdl[count].unwind_int.arg = arg; -} - /* Everything needed to describe an active condition case. Members are volatile if their values need to survive _longjmp when @@ -3755,6 +3743,8 @@ extern void record_unwind_protect_int (void (*) (int), int); extern void record_unwind_protect_ptr (void (*) (void *), void *); extern void record_unwind_protect_void (void (*) (void)); +extern void clear_unwind_protect (ptrdiff_t); +extern void set_unwind_protect_ptr (ptrdiff_t, void (*) (void *), void *); extern Lisp_Object unbind_to (ptrdiff_t, Lisp_Object); extern _Noreturn void error (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2); extern _Noreturn void verror (const char *, va_list) === modified file 'src/lread.c' --- src/lread.c 2013-07-16 21:35:45 +0000 +++ src/lread.c 2013-07-17 17:24:54 +0000 @@ -1040,10 +1040,12 @@ is bound to the file's name. Return t if the file exists and loads successfully. */) - (Lisp_Object file, Lisp_Object noerror, Lisp_Object nomessage, Lisp_Object nosuffix, Lisp_Object must_suffix) + (Lisp_Object file, Lisp_Object noerror, Lisp_Object nomessage, + Lisp_Object nosuffix, Lisp_Object must_suffix) { - register FILE *stream; - register int fd = -1; + FILE *stream; + int fd; + int fd_index; ptrdiff_t count = SPECPDL_INDEX (); struct gcpro gcpro1, gcpro2, gcpro3; Lisp_Object found, efound, hist_file_name; @@ -1054,7 +1056,6 @@ Lisp_Object handler; bool safe_p = 1; const char *fmode = "r"; - Lisp_Object tmp[2]; int version; #ifdef DOS_NT @@ -1087,19 +1088,23 @@ else file = Fsubstitute_in_file_name (file); - /* Avoid weird lossage with null string as arg, since it would try to load a directory as a Lisp file. */ - if (SBYTES (file) > 0) - { - ptrdiff_t size = SBYTES (file); - + if (SCHARS (file) == 0) + { + fd = -1; + errno = ENOENT; + } + else + { + Lisp_Object suffixes; found = Qnil; GCPRO2 (file, found); if (! NILP (must_suffix)) { /* Don't insist on adding a suffix if FILE already ends with one. */ + ptrdiff_t size = SBYTES (file); if (size > 3 && !strcmp (SSDATA (file) + size - 3, ".el")) must_suffix = Qnil; @@ -1112,20 +1117,28 @@ must_suffix = Qnil; } - fd = openp (Vload_path, file, - (!NILP (nosuffix) ? Qnil - : !NILP (must_suffix) ? Fget_load_suffixes () - : Fappend (2, (tmp[0] = Fget_load_suffixes (), - tmp[1] = Vload_file_rep_suffixes, - tmp))), - &found, Qnil); + if (!NILP (nosuffix)) + suffixes = Qnil; + else + { + suffixes = Fget_load_suffixes (); + if (NILP (must_suffix)) + { + Lisp_Object arg[2]; + arg[0] = suffixes; + arg[1] = Vload_file_rep_suffixes; + suffixes = Fappend (2, arg); + } + } + + fd = openp (Vload_path, file, suffixes, &found, Qnil); UNGCPRO; } if (fd == -1) { if (NILP (noerror)) - xsignal2 (Qfile_error, build_string ("Cannot open load file"), file); + report_file_error ("Cannot open load file", file); return Qnil; } @@ -1163,6 +1176,12 @@ #endif } + if (0 <= fd) + { + fd_index = SPECPDL_INDEX (); + record_unwind_protect_int (close_file_unwind, fd); + } + /* Check if we're stuck in a recursive load cycle. 2000-09-21: It's not possible to just check for the file loaded @@ -1178,11 +1197,7 @@ Lisp_Object tem; for (tem = Vloads_in_progress; CONSP (tem); tem = XCDR (tem)) if (!NILP (Fequal (found, XCAR (tem))) && (++load_count > 3)) - { - if (fd >= 0) - emacs_close (fd); - signal_error ("Recursive load", Fcons (found, Vloads_in_progress)); - } + signal_error ("Recursive load", Fcons (found, Vloads_in_progress)); record_unwind_protect (record_load_unwind, Vloads_in_progress); Vloads_in_progress = Fcons (found, Vloads_in_progress); } @@ -1195,9 +1210,8 @@ /* Get the name for load-history. */ hist_file_name = (! NILP (Vpurify_flag) - ? Fconcat (2, (tmp[0] = Ffile_name_directory (file), - tmp[1] = Ffile_name_nondirectory (found), - tmp)) + ? concat2 (Ffile_name_directory (file), + Ffile_name_nondirectory (found)) : found) ; version = -1; @@ -1223,12 +1237,7 @@ { safe_p = 0; if (!load_dangerous_libraries) - { - if (fd >= 0) - emacs_close (fd); - error ("File `%s' was not compiled in Emacs", - SDATA (found)); - } + error ("File `%s' was not compiled in Emacs", SDATA (found)); else if (!NILP (nomessage) && !force_load_messages) message_with_string ("File `%s' not compiled in Emacs", found, 1); } @@ -1274,7 +1283,10 @@ Lisp_Object val; if (fd >= 0) - emacs_close (fd); + { + emacs_close (fd); + clear_unwind_protect (fd_index); + } val = call4 (Vload_source_file_function, found, hist_file_name, NILP (noerror) ? Qnil : Qt, (NILP (nomessage) || force_load_messages) ? Qnil : Qt); @@ -1284,26 +1296,28 @@ GCPRO3 (file, found, hist_file_name); + if (fd < 0) + { + /* We somehow got here with fd == -2, meaning the file is deemed + to be remote. Don't even try to reopen the file locally; + just force a failure. */ + stream = NULL; + errno = EINVAL; + } + else + { #ifdef WINDOWSNT - efound = ENCODE_FILE (found); - /* If we somehow got here with fd == -2, meaning the file is deemed - to be remote, don't even try to reopen the file locally; just - force a failure instead. */ - if (fd >= 0) - { emacs_close (fd); + clear_unwind_protect (fd_index); + efound = ENCODE_FILE (found); stream = emacs_fopen (SSDATA (efound), fmode); - } - else - stream = NULL; -#else /* not WINDOWSNT */ - stream = fdopen (fd, fmode); -#endif /* not WINDOWSNT */ - if (stream == 0) - { - emacs_close (fd); - error ("Failure to create stdio stream for %s", SDATA (file)); - } +#else + stream = fdopen (fd, fmode); +#endif + } + if (! stream) + report_file_error ("Opening stdio stream", file); + set_unwind_protect_ptr (fd_index, load_unwind, stream); if (! NILP (Vpurify_flag)) Vpreloaded_file_list = Fcons (Fpurecopy (file), Vpreloaded_file_list); @@ -1322,7 +1336,6 @@ message_with_string ("Loading %s...", file, 1); } - record_unwind_protect_ptr (load_unwind, stream); specbind (Qload_file_name, found); specbind (Qinhibit_file_name_operation, Qnil); specbind (Qload_in_progress, Qt); @@ -1521,7 +1534,6 @@ if ((!NILP (handler) || !NILP (predicate)) && !NATNUMP (predicate)) { bool exists; - last_errno = ENOENT; if (NILP (predicate)) exists = !NILP (Ffile_readable_p (string)); else @@ -1576,7 +1588,10 @@ { fd = emacs_open (pfn, O_RDONLY, 0); if (fd < 0) - last_errno = errno; + { + if (errno != ENOENT) + last_errno = errno; + } else { struct stat st; ------------------------------------------------------------ revno: 113442 fixes bug: http://debbugs.gnu.org/14881 committer: Eli Zaretskii branch nick: trunk timestamp: Wed 2013-07-17 19:47:49 +0300 message: Fix bug #14881 with scrolling images smaller than the window height. lisp/simple.el (line-move-partial, line-move): Don't start vscroll or scroll-up if the current line is not taller than the window. diff: === modified file 'lisp/ChangeLog' --- lisp/ChangeLog 2013-07-16 19:16:51 +0000 +++ lisp/ChangeLog 2013-07-17 16:47:49 +0000 @@ -1,3 +1,9 @@ +2013-07-17 Eli Zaretskii + + * simple.el (line-move-partial, line-move): Don't start vscroll or + scroll-up if the current line is not taller than the window. + (Bug#14881) + 2013-07-16 Dmitry Gutov * progmodes/ruby-mode.el (ruby-font-lock-keywords): Do not === modified file 'lisp/simple.el' --- lisp/simple.el 2013-07-15 00:49:22 +0000 +++ lisp/simple.el 2013-07-17 16:47:49 +0000 @@ -4800,6 +4800,8 @@ (this-ypos (nth 2 this-lh)) (dlh (default-line-height)) (wslines (window-screen-lines)) + (edges (window-inside-pixel-edges)) + (winh (- (nth 3 edges) (nth 1 edges) 1)) py vs last-line) (if (> (mod wslines 1.0) 0.0) (setq wslines (round (+ wslines 0.5)))) @@ -4848,7 +4850,7 @@ nil) ;; If cursor is not in the bottom scroll margin, and the ;; current line is is not too tall, move forward. - ((and (or (null this-height) (<= this-height dlh)) + ((and (or (null this-height) (<= this-height winh)) vpos (> vpos 0) (< py last-line)) @@ -4865,7 +4867,7 @@ (> vpos 0) (= py last-line)) ;; Don't vscroll if the partially-visible line at window - ;; bottom has the default height (a.k.a. "just one more text + ;; bottom is not too tall (a.k.a. "just one more text ;; line"): in that case, we do want redisplay to behave ;; normally, i.e. recenter or whatever. ;; @@ -4874,7 +4876,7 @@ ;; partially-visible glyph row at the end of the window. As ;; we are dealing with floats, we disregard sub-pixel ;; discrepancies between that and DLH. - (if (and rowh rbot (>= (- (+ rowh rbot) dlh) 1)) + (if (and rowh rbot (>= (- (+ rowh rbot) winh) 1)) (set-window-vscroll nil dlh t)) (line-move-1 arg noerror to-end) t) @@ -4918,10 +4920,13 @@ ;; If we moved into a tall line, set vscroll to make ;; scrolling through tall images more smooth. (let ((lh (line-pixel-height)) - (dlh (default-line-height))) + (edges (window-inside-pixel-edges)) + (dlh (default-line-height)) + winh) + (setq winh (- (nth 3 edges) (nth 1 edges) 1)) (if (and (< arg 0) (< (point) (window-start)) - (> lh dlh)) + (> lh winh)) (set-window-vscroll nil (- lh dlh) t)))) ------------------------------------------------------------ revno: 113441 committer: Paul Eggert branch nick: trunk timestamp: Tue 2013-07-16 21:37:27 -0700 message: A few more minor file errno-reporting bugs. * callproc.c (Fcall_process): * doc.c (Fsnarf_documentation): * fileio.c (Frename_file, Fadd_name_to_file, Fmake_symbolic_link): * process.c (set_socket_option): Don't let a constructor trash errno. * doc.c: Include . diff: === modified file 'src/ChangeLog' --- src/ChangeLog 2013-07-16 23:29:05 +0000 +++ src/ChangeLog 2013-07-17 04:37:27 +0000 @@ -1,3 +1,13 @@ +2013-07-17 Paul Eggert + + A few more minor file errno-reporting bugs. + * callproc.c (Fcall_process): + * doc.c (Fsnarf_documentation): + * fileio.c (Frename_file, Fadd_name_to_file, Fmake_symbolic_link): + * process.c (set_socket_option): + Don't let a constructor trash errno. + * doc.c: Include . + 2013-07-16 Juanma Barranquero * w32fns.c (unwind_create_tip_frame): Fix declaration. === modified file 'src/callproc.c' --- src/callproc.c 2013-07-16 22:40:17 +0000 +++ src/callproc.c 2013-07-17 04:37:27 +0000 @@ -405,7 +405,11 @@ filefd = emacs_open (SSDATA (infile), O_RDONLY, 0); if (filefd < 0) - report_file_error ("Opening process input file", DECODE_FILE (infile)); + { + int open_errno = errno; + report_file_errno ("Opening process input file", DECODE_FILE (infile), + open_errno); + } if (STRINGP (output_file)) { === modified file 'src/doc.c' --- src/doc.c 2013-07-16 16:39:42 +0000 +++ src/doc.c 2013-07-17 04:37:27 +0000 @@ -21,6 +21,7 @@ #include +#include #include #include /* Must be after sys/types.h for USG. */ #include @@ -609,7 +610,11 @@ fd = emacs_open (name, O_RDONLY, 0); if (fd < 0) - report_file_error ("Opening doc string file", build_string (name)); + { + int open_errno = errno; + report_file_errno ("Opening doc string file", build_string (name), + open_errno); + } Vdoc_file_name = filename; filled = 0; pos = 0; === modified file 'src/fileio.c' --- src/fileio.c 2013-07-16 21:49:32 +0000 +++ src/fileio.c 2013-07-17 04:37:27 +0000 @@ -204,7 +204,9 @@ } /* Signal a file-access failure that set errno. STRING describes the - failure, NAME the file involved. */ + failure, NAME the file involved. When invoking this function, take + care to not use arguments such as build_string ("foo") that involve + side effects that may set errno. */ void report_file_error (char const *string, Lisp_Object name) @@ -2371,7 +2373,8 @@ INTEGERP (ok_if_already_exists), 0, 0); if (rename (SSDATA (encoded_file), SSDATA (encoded_newname)) < 0) { - if (errno == EXDEV) + int rename_errno = errno; + if (rename_errno == EXDEV) { ptrdiff_t count; symlink_target = Ffile_symlink_p (file); @@ -2397,7 +2400,7 @@ unbind_to (count, Qnil); } else - report_file_error ("Renaming", list2 (file, newname)); + report_file_errno ("Renaming", list2 (file, newname), rename_errno); } UNGCPRO; return Qnil; @@ -2451,7 +2454,10 @@ unlink (SSDATA (newname)); if (link (SSDATA (encoded_file), SSDATA (encoded_newname)) < 0) - report_file_error ("Adding new name", list2 (file, newname)); + { + int link_errno = errno; + report_file_errno ("Adding new name", list2 (file, newname), link_errno); + } UNGCPRO; return Qnil; @@ -2510,6 +2516,7 @@ if (symlink (SSDATA (encoded_filename), SSDATA (encoded_linkname)) < 0) { /* If we didn't complain already, silently delete existing file. */ + int symlink_errno; if (errno == EEXIST) { unlink (SSDATA (encoded_linkname)); @@ -2527,7 +2534,9 @@ build_string ("Symbolic links are not supported")); } - report_file_error ("Making symbolic link", list2 (filename, linkname)); + symlink_errno = errno; + report_file_errno ("Making symbolic link", list2 (filename, linkname), + symlink_errno); } UNGCPRO; return Qnil; === modified file 'src/process.c' --- src/process.c 2013-07-16 21:35:45 +0000 +++ src/process.c 2013-07-17 04:37:27 +0000 @@ -2321,7 +2321,12 @@ } if (ret < 0) - report_file_error ("Cannot set network option", list2 (opt, val)); + { + int setsockopt_errno = errno; + report_file_errno ("Cannot set network option", list2 (opt, val), + setsockopt_errno); + } + return (1 << sopt->optbit); }