commit c19f5dcd474bfc883fc7555eef7d8f50a0df3157 (HEAD, refs/remotes/origin/master) Author: Paul Eggert Date: Thu Sep 12 00:25:47 2019 -0700 Fix file name encoding when open_directory signals * src/dired.c (open_directory): New arg ENCODED_DIRNAME. All callers changed. Signal error with original name, not encoded name. diff --git a/src/dired.c b/src/dired.c index 58fa848e2e..cec79ab46b 100644 --- a/src/dired.c +++ b/src/dired.c @@ -79,9 +79,9 @@ dirent_type (struct dirent *dp) } static DIR * -open_directory (Lisp_Object dirname, int *fdp) +open_directory (Lisp_Object dirname, Lisp_Object encoded_dirname, int *fdp) { - char *name = SSDATA (dirname); + char *name = SSDATA (encoded_dirname); DIR *d; int fd, opendir_errno; @@ -187,11 +187,11 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full, /* Note: ENCODE_FILE and DECODE_FILE can GC because they can run run_pre_post_conversion_on_str which calls Lisp directly and indirectly. */ - dirfilename = ENCODE_FILE (dirfilename); + Lisp_Object encoded_dirfilename = ENCODE_FILE (dirfilename); encoded_directory = ENCODE_FILE (directory); int fd; - DIR *d = open_directory (dirfilename, &fd); + DIR *d = open_directory (dirfilename, encoded_dirfilename, &fd); /* Unfortunately, we can now invoke expand-file-name and file-attributes on filenames, both of which can throw, so we must @@ -210,7 +210,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full, { /* w32.c:stat will notice these bindings and avoid calling GetDriveType for each file. */ - if (is_slow_fs (SSDATA (dirfilename))) + if (is_slow_fs (SSDATA (encoded_dirfilename))) Vw32_get_true_file_attributes = Qnil; else Vw32_get_true_file_attributes = Qt; @@ -509,7 +509,7 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag, } } int fd; - DIR *d = open_directory (encoded_dir, &fd); + DIR *d = open_directory (dirname, encoded_dir, &fd); record_unwind_protect_ptr (directory_files_internal_unwind, d); /* Loop reading directory entries. */ commit ffa870fc806451b9bd4504bebbf9085f4b4c0be8 Author: Paul Eggert Date: Wed Sep 11 23:45:32 2019 -0700 Improve error reporting for DOC file problems * src/doc.c (get_doc_string): Report all serious errors when DOC cannot be opened, not just fd-exhaustion errors. diff --git a/src/doc.c b/src/doc.c index 247be79ada..b06b87c611 100644 --- a/src/doc.c +++ b/src/doc.c @@ -136,7 +136,7 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition) } if (fd < 0) { - if (errno == EMFILE || errno == ENFILE) + if (errno != ENOENT && errno != ENOTDIR) report_file_error ("Read error on documentation file", file); SAFE_FREE (); commit f7228a6479cc8c88a23138980d958c4c431dd6a5 Author: Paul Eggert Date: Wed Sep 11 23:22:46 2019 -0700 Fix directory-files-and-attributes race * src/dired.c (directory_files_internal): Fix race condition: when some other process removed a file between the readdir and the ensuing lstat, directory-files-and-attributes would return a list containing nil. diff --git a/src/dired.c b/src/dired.c index 7bc4b83fd7..58fa848e2e 100644 --- a/src/dired.c +++ b/src/dired.c @@ -295,7 +295,8 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full, { Lisp_Object fileattrs = file_attributes (fd, dp->d_name, directory, name, id_format); - list = Fcons (Fcons (finalname, fileattrs), list); + if (!NILP (fileattrs)) + list = Fcons (Fcons (finalname, fileattrs), list); } else list = Fcons (finalname, list); commit ef926ce3b6a078039303ae210e599dc4d3faa13b Author: Paul Eggert Date: Wed Sep 11 14:24:03 2019 -0700 Omit duplicate test of current directory * src/callproc.c (encode_current_directory): Remove redundant call to Ffile_accessible_directory_p. The code checks the encoded name with file_accessible_directory_p anyway. diff --git a/src/callproc.c b/src/callproc.c index b296bdb088..4473b19a29 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -108,11 +108,8 @@ static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int, ptrdiff_t); Lisp_Object encode_current_directory (void) { - Lisp_Object dir; - - dir = BVAR (current_buffer, directory); - - dir = Funhandled_file_name_directory (dir); + Lisp_Object curdir = BVAR (current_buffer, directory); + Lisp_Object dir = Funhandled_file_name_directory (curdir); /* If the file name handler says that dir is unreachable, use a sensible default. */ @@ -120,17 +117,10 @@ encode_current_directory (void) dir = build_string ("~"); dir = expand_and_dir_to_file (dir); - - if (NILP (Ffile_accessible_directory_p (dir))) - report_file_error ("Setting current directory", - BVAR (current_buffer, directory)); - - /* Remove "/:" from DIR and encode it. */ dir = ENCODE_FILE (remove_slash_colon (dir)); if (! file_accessible_directory_p (dir)) - report_file_error ("Setting current directory", - BVAR (current_buffer, directory)); + report_file_error ("Setting current directory", curdir); return dir; } commit 5fafa40d076ee24baf880e97d4290b6196cf838a Author: Paul Eggert Date: Wed Sep 11 11:26:07 2019 -0700 Improve checking of pdump load failures * src/alloc.c (memory_full): Just report "memory exhausted" if failure occurs during initialization, since fancier recovery schemes are not likely to work when not initialized. * src/emacs.c (dump_error_to_string): Accept int, not enum pdumper_load_result, since the result might not fit in the enum. Use strerror if it was derived from errno. This is for better diagnostics of pdump load failures. (load_pdump_find_executable): Return char *, not enum. 2nd arg is now pointer to buffer size, rather than pointer to pointer to buffer. All callers changed. Use Emacs allocator since they should now be OK even during early startup. Use check_executable instead access, to use effective rather than real permissions. (load_pdump): Return void since callers ignore result. Use int where enum could be too narrow. Use heap rather than stack for possibly-long string. Prefer ptrdiff_t to size_t. * src/fileio.c (check_executable): Now extern. * src/pdumper.c (pdumper_load): Return int that may have errno added to it, for better diagnostics when loads fail. diff --git a/src/alloc.c b/src/alloc.c index be98cfd5f5..2d490f3bb7 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -3844,6 +3844,9 @@ set_interval_marked (INTERVAL i) void memory_full (size_t nbytes) { + if (!initialized) + fatal ("memory exhausted"); + /* Do not go into hysterics merely because a large request failed. */ bool enough_free_memory = false; if (SPARE_MEMORY < nbytes) diff --git a/src/emacs.c b/src/emacs.c index 53572d7f0c..5a526687b1 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -662,7 +662,7 @@ argmatch (char **argv, int argc, const char *sstr, const char *lstr, #ifdef HAVE_PDUMPER static const char * -dump_error_to_string (enum pdumper_load_result result) +dump_error_to_string (int result) { switch (result) { @@ -681,37 +681,29 @@ dump_error_to_string (enum pdumper_load_result result) case PDUMPER_LOAD_VERSION_MISMATCH: return "not built for this Emacs executable"; default: - return "generic error"; + return (result <= PDUMPER_LOAD_ERROR + ? "generic error" + : strerror (result - PDUMPER_LOAD_ERROR)); } } -/* Find a path (absolute or relative) to the Emacs executable. - Called early in initialization by portable dumper loading code, so we - can't use lisp and associated machinery. On success, *EXENAME is - set to a heap-allocated string giving a path to the Emacs - executable or to NULL if we can't determine the path immediately. - */ -static enum pdumper_load_result -load_pdump_find_executable (const char* argv0, char **exename) +/* Find a name (absolute or relative) of the Emacs executable whose + name (as passed into this program) is ARGV0. Called early in + initialization by portable dumper loading code, so avoid Lisp and + associated machinery. Return a heap-allocated string giving a name + of the Emacs executable, or an empty heap-allocated string or NULL + if not found. Store into *CANDIDATE_SIZE a lower bound on the size + of any heap allocation. */ +static char * +load_pdump_find_executable (char const *argv0, ptrdiff_t *candidate_size) { - enum pdumper_load_result result; + *candidate_size = 0; + + /* Use xstrdup etc. to allocate storage, so as to call our private + implementation of malloc, since the caller calls our free. */ #ifdef WINDOWSNT - result = PDUMPER_LOAD_ERROR; - *exename = NULL; char *prog_fname = w32_my_exename (); - if (prog_fname) - { - result = PDUMPER_LOAD_OOM; - /* Use xstrdup, so as to call our private implementation of - malloc, since the caller calls our free. */ - char *ret = xstrdup (prog_fname); - if (ret) - { - *exename = ret; - result = PDUMPER_LOAD_SUCCESS; - } - } - return result; + return prog_fname ? xstrdup (prog_fname) : NULL; #else /* !WINDOWSNT */ char *candidate = NULL; @@ -719,33 +711,23 @@ load_pdump_find_executable (const char* argv0, char **exename) path already, so just copy it. */ eassert (argv0); if (strchr (argv0, DIRECTORY_SEP)) - { - result = PDUMPER_LOAD_OOM; - char *ret = strdup (argv0); - if (!ret) - goto out; - result = PDUMPER_LOAD_SUCCESS; - *exename = ret; - goto out; - } - size_t argv0_length = strlen (argv0); + return xstrdup (argv0); + ptrdiff_t argv0_length = strlen (argv0); const char *path = getenv ("PATH"); if (!path) { /* Default PATH is implementation-defined, so we don't know how to conduct the search. */ - result = PDUMPER_LOAD_SUCCESS; - *exename = NULL; - goto out; + return NULL; } /* Actually try each concatenation of a path element and the executable basename. */ - const char path_sep[] = { SEPCHAR, '\0' }; do { - size_t path_part_length = strcspn (path, path_sep); + static char const path_sep[] = { SEPCHAR, '\0' }; + ptrdiff_t path_part_length = strcspn (path, path_sep); const char *path_part = path; path += path_part_length; if (path_part_length == 0) @@ -753,46 +735,34 @@ load_pdump_find_executable (const char* argv0, char **exename) path_part = "."; path_part_length = 1; } - size_t candidate_length = path_part_length + 1 + argv0_length; - { - char *new_candidate = realloc (candidate, candidate_length + 1); - if (!new_candidate) - { - result = PDUMPER_LOAD_OOM; - goto out; - } - candidate = new_candidate; - } + ptrdiff_t needed = path_part_length + 1 + argv0_length + 1; + if (*candidate_size <= needed) + { + xfree (candidate); + candidate = xpalloc (NULL, candidate_size, + needed - *candidate_size + 1, -1, 1); + } memcpy (candidate + 0, path_part, path_part_length); candidate[path_part_length] = DIRECTORY_SEP; memcpy (candidate + path_part_length + 1, argv0, argv0_length + 1); struct stat st; - if (!access (candidate, X_OK) && - !stat (candidate, &st) && - S_ISREG (st.st_mode)) - { - *exename = candidate; - candidate = NULL; - break; - } - } while ((path++)[0] != '\0'); - - result = PDUMPER_LOAD_SUCCESS; + if (check_executable (candidate) + && stat (candidate, &st) == 0 && S_ISREG (st.st_mode)) + return candidate; + *candidate = '\0'; + } + while (*path++ != '\0'); - out: - free (candidate); - return result; + return candidate; #endif /* !WINDOWSNT */ } -static enum pdumper_load_result +static void load_pdump (int argc, char **argv) { const char *const suffix = ".pdmp"; - enum pdumper_load_result result; - char *exename = NULL; - char *real_exename = NULL; - const char* strip_suffix = + int result; + const char *strip_suffix = #if defined DOS_NT || defined CYGWIN ".exe" #else @@ -821,7 +791,6 @@ load_pdump (int argc, char **argv) skip_args++; } - result = PDUMPER_NOT_LOADED; if (dump_file) { result = pdumper_load (dump_file); @@ -829,8 +798,7 @@ load_pdump (int argc, char **argv) if (result != PDUMPER_LOAD_SUCCESS) fatal ("could not load dump file \"%s\": %s", dump_file, dump_error_to_string (result)); - else - goto out; + return; } /* Look for a dump file in the same directory as the executable; it @@ -839,44 +807,41 @@ load_pdump (int argc, char **argv) so we can't use decode_env_path. We're working in whatever encoding the system natively uses for filesystem access, so there's no need for character set conversion. */ - result = load_pdump_find_executable (argv[0], &exename); - if (result != PDUMPER_LOAD_SUCCESS) - goto out; + ptrdiff_t bufsize; + dump_file = load_pdump_find_executable (argv[0], &bufsize); /* If we couldn't find our executable, go straight to looking for the dump in the hardcoded location. */ - if (exename) + if (dump_file && *dump_file) { #ifdef WINDOWSNT /* w32_my_exename resolves symlinks internally, so no need to call realpath. */ - real_exename = exename; - exename = NULL; #else - real_exename = realpath (exename, NULL); + char *real_exename = realpath (dump_file, NULL); if (!real_exename) fatal ("could not resolve realpath of \"%s\": %s", - exename, strerror (errno)); + dump_file, strerror (errno)); + xfree (dump_file); + dump_file = real_exename; +#endif + ptrdiff_t exenamelen = strlen (dump_file); +#ifndef WINDOWSNT + bufsize = exenamelen + 1; #endif - size_t real_exename_length = strlen (real_exename); if (strip_suffix) { - size_t strip_suffix_length = strlen (strip_suffix); - if (real_exename_length >= strip_suffix_length) - { - size_t prefix_length = - real_exename_length - strip_suffix_length; - if (!memcmp (&real_exename[prefix_length], - strip_suffix, - strip_suffix_length)) - real_exename_length = prefix_length; - } + ptrdiff_t strip_suffix_length = strlen (strip_suffix); + ptrdiff_t prefix_length = exenamelen - strip_suffix_length; + if (0 <= prefix_length + && !memcmp (&dump_file[prefix_length], strip_suffix, + strip_suffix_length)) + exenamelen = prefix_length; } - dump_file = alloca (real_exename_length + strlen (suffix) + 1); - memcpy (dump_file, real_exename, real_exename_length); - memcpy (dump_file + real_exename_length, - suffix, - strlen (suffix) + 1); + ptrdiff_t needed = exenamelen + strlen (suffix) + 1; + if (bufsize < needed) + dump_file = xpalloc (dump_file, &bufsize, needed - bufsize, -1, 1); + strcpy (dump_file + exenamelen, suffix); result = pdumper_load (dump_file); if (result == PDUMPER_LOAD_SUCCESS) goto out; @@ -896,16 +861,19 @@ load_pdump (int argc, char **argv) "emacs.pdmp" so that the Emacs binary still works if the user copies and renames it. */ const char *argv0_base = "emacs"; - dump_file = alloca (strlen (path_exec) + ptrdiff_t needed = (strlen (path_exec) + 1 + strlen (argv0_base) + strlen (suffix) + 1); + if (bufsize < needed) + { + xfree (dump_file); + dump_file = xpalloc (NULL, &bufsize, needed - bufsize, -1, 1); + } sprintf (dump_file, "%s%c%s%s", path_exec, DIRECTORY_SEP, argv0_base, suffix); result = pdumper_load (dump_file); - if (result == PDUMPER_LOAD_SUCCESS) - goto out; if (result == PDUMPER_LOAD_FILE_NOT_FOUND) { @@ -920,13 +888,18 @@ load_pdump (int argc, char **argv) last_sep = p; } argv0_base = last_sep ? last_sep + 1 : argv[0]; - dump_file = alloca (strlen (path_exec) + ptrdiff_t needed = (strlen (path_exec) + 1 + strlen (argv0_base) + strlen (suffix) + 1); + if (bufsize < needed) + { + xfree (dump_file); + dump_file = xmalloc (needed); + } #ifdef DOS_NT - size_t argv0_len = strlen (argv0_base); + ptrdiff_t argv0_len = strlen (argv0_base); if (argv0_len >= 4 && c_strcasecmp (argv0_base + argv0_len - 4, ".exe") == 0) sprintf (dump_file, "%s%c%.*s%s", path_exec, DIRECTORY_SEP, @@ -943,13 +916,10 @@ load_pdump (int argc, char **argv) if (result != PDUMPER_LOAD_FILE_NOT_FOUND) fatal ("could not load dump file \"%s\": %s", dump_file, dump_error_to_string (result)); - dump_file = NULL; } out: - free (exename); - free (real_exename); - return result; + xfree (dump_file); } #endif /* HAVE_PDUMPER */ diff --git a/src/fileio.c b/src/fileio.c index 968a55e595..cbc0c89cf3 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -150,7 +150,7 @@ check_existing (const char *filename) /* Return true if file FILENAME exists and can be executed. */ -static bool +bool check_executable (char *filename) { return faccessat (AT_FDCWD, filename, X_OK, AT_EACCESS) == 0; diff --git a/src/lisp.h b/src/lisp.h index a7b19ab576..024e5edb26 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4298,6 +4298,7 @@ extern void syms_of_marker (void); /* Defined in fileio.c. */ +extern bool check_executable (char *); extern char *splice_dir_file (char *, char const *, char const *); extern bool file_name_absolute_p (const char *); extern char const *get_homedir (void); diff --git a/src/pdumper.c b/src/pdumper.c index 98090238b1..2e382145be 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -5303,7 +5303,7 @@ enum dump_section N.B. We run very early in initialization, so we can't use lisp, unwinding, xmalloc, and so on. */ -enum pdumper_load_result +int pdumper_load (const char *dump_filename) { intptr_t dump_size; @@ -5328,10 +5328,15 @@ pdumper_load (const char *dump_filename) /* We can load only one dump. */ eassert (!dump_loaded_p ()); - enum pdumper_load_result err = PDUMPER_LOAD_FILE_NOT_FOUND; + int err; int dump_fd = emacs_open (dump_filename, O_RDONLY, 0); if (dump_fd < 0) - goto out; + { + err = (errno == ENOENT || errno == ENOTDIR + ? PDUMPER_LOAD_FILE_NOT_FOUND + : PDUMPER_LOAD_ERROR + errno); + goto out; + } err = PDUMPER_LOAD_FILE_NOT_FOUND; if (fstat (dump_fd, &stat) < 0) diff --git a/src/pdumper.h b/src/pdumper.h index 83c094f3ca..31b0d53b07 100644 --- a/src/pdumper.h +++ b/src/pdumper.h @@ -124,10 +124,10 @@ enum pdumper_load_result PDUMPER_LOAD_FAILED_DUMP, PDUMPER_LOAD_OOM, PDUMPER_LOAD_VERSION_MISMATCH, - PDUMPER_LOAD_ERROR, + PDUMPER_LOAD_ERROR /* Must be last, as errno may be added. */ }; -enum pdumper_load_result pdumper_load (const char *dump_filename); +int pdumper_load (const char *dump_filename); struct pdumper_loaded_dump { commit a6daae7b3df3a964b3dcde85987c02fd0af66a89 Author: Paul Eggert Date: Wed Sep 11 10:19:07 2019 -0700 Reset dbus registered buses on dump load Problem reported by Leonard Lausen (Bug#37331). * src/dbusbind.c: Include pdumper.h. (syms_of_dbusbind_for_pdumper): New function, to reset the registered buses. (syms_of_dbusbind): Use it, fixing a TODO. diff --git a/src/dbusbind.c b/src/dbusbind.c index 7f4c8717f4..de67dc94f9 100644 --- a/src/dbusbind.c +++ b/src/dbusbind.c @@ -26,6 +26,7 @@ along with GNU Emacs. If not, see . */ #include "lisp.h" #include "termhooks.h" #include "keyboard.h" +#include "pdumper.h" #include "process.h" #ifndef DBUS_NUM_MESSAGE_TYPES @@ -1681,6 +1682,12 @@ init_dbusbind (void) xputenv ("DBUS_FATAL_WARNINGS=0"); } +static void +syms_of_dbusbind_for_pdumper (void) +{ + xd_registered_buses = Qnil; +} + void syms_of_dbusbind (void) { @@ -1829,13 +1836,10 @@ be called when the D-Bus reply message arrives. */); #endif /* Initialize internal objects. */ - xd_registered_buses = Qnil; + pdumper_do_now_and_after_load (syms_of_dbusbind_for_pdumper); staticpro (&xd_registered_buses); - // TODO: reset buses on dump load - Fprovide (intern_c_string ("dbusbind"), Qnil); - } #endif /* HAVE_DBUS */ commit 636856faa4de78912bf41eeaf0e639664a323424 Author: Paul Eggert Date: Wed Sep 11 08:50:02 2019 -0700 Fix auto-save with user-emacs-directory * lisp/startup.el (auto-save-list-file-prefix): Delay initialization, since the value depends on user-emacs-directory (Bug#37354). diff --git a/lisp/startup.el b/lisp/startup.el index a16db242da..ef6234128a 100644 --- a/lisp/startup.el +++ b/lisp/startup.el @@ -406,6 +406,7 @@ if you have not already set `auto-save-list-file-name' yourself. Directories in the prefix will be created if necessary. Set this to nil if you want to prevent `auto-save-list-file-name' from being initialized." + :initialize #'custom-initialize-delay :type '(choice (const :tag "Don't record a session's auto save list" nil) string) :group 'auto-save) commit 4d90fadf27ccbb98e0e174304cb4e3008bf364fc Author: Mattias EngdegÄrd Date: Wed Sep 11 11:18:38 2019 +0200 * lisp/emacs-lisp/elint.el (elint-directory-skip-re): Fix doc typo. diff --git a/lisp/emacs-lisp/elint.el b/lisp/emacs-lisp/elint.el index b7ef6eeb2a..187d619f1b 100644 --- a/lisp/emacs-lisp/elint.el +++ b/lisp/emacs-lisp/elint.el @@ -106,7 +106,7 @@ are as follows, and suppress messages about the indicated features: :group 'elint) (defcustom elint-directory-skip-re "\\(ldefs-boot\\|loaddefs\\)\\.el\\'" - "If nil, a regexp matching files to skip when linting a directory." + "If non-nil, a regexp matching files to skip when linting a directory." :type '(choice (const :tag "Lint all files" nil) (regexp :tag "Regexp to skip")) :safe 'string-or-null-p