From: Eli Zaretskii Date: Thu, 27 May 2021 13:31:14 +0000 (+0300) Subject: Fix resolution of symlinks during dumping X-Git-Tag: emacs-28.0.90~2310 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=d3817ad6ce7b719c89d4049bdd12b168e3053a76;p=emacs.git Fix resolution of symlinks during dumping * src/comp.c (Fcomp_el_to_eln_rel_filename): Don't use 'file-truename', as it is only available once files.el is loaded, which doesn't work during dumping, until loadup loads files.el. Instead, use 'realpath'. (Bug#48578) * src/w32.c (realpath): New function. * src/w32.h (realpath): Add prototype. * nt/mingw-cfg.site (ac_cv_func_realpath) (gl_cv_func_realpath_works): Define to "yes", as this function is now implemented in w32.c. --- diff --git a/nt/mingw-cfg.site b/nt/mingw-cfg.site index 431fdab51bb..6ab81e943f1 100644 --- a/nt/mingw-cfg.site +++ b/nt/mingw-cfg.site @@ -90,8 +90,9 @@ ac_cv_func_readlinkat=yes ac_cv_func_faccessat=yes # Avoid compiling Gnulib's canonicalize-lgpl.c, which fails ac_cv_func_canonicalize_file_name=yes -ac_cv_func_realpath="not-needed" -gl_cv_func_realpath_works="no-but-not-needed-so-yes" +# Implemented in w32.c +ac_cv_func_realpath=yes +gl_cv_func_realpath_works=yes # Implemented in w32.c ac_cv_func_fcntl=yes gl_cv_func_fcntl_f_dupfd_cloexec=yes diff --git a/src/comp.c b/src/comp.c index 340ed850387..056d0860d8a 100644 --- a/src/comp.c +++ b/src/comp.c @@ -4008,15 +4008,16 @@ DEFUN ("comp-el-to-eln-rel-filename", Fcomp_el_to_eln_rel_filename, { CHECK_STRING (filename); - /* Use `file-truename' or fall back to `expand-file-name' when the - first is not available (bug#44701). - - `file-truename' is not available only for a short phases of the - bootstrap before file.el is loaded, given we do not symlink - inside the build directory this should work. */ - filename = NILP (Ffboundp (intern_c_string ("file-truename"))) - ? Fexpand_file_name (filename, Qnil) - : CALL1I (file-truename, filename); + /* Resolve possible symlinks in FILENAME, so that path_hash below + always compares equal. (Bug#44701). */ + filename = Fexpand_file_name (filename, Qnil); + char *file_normalized = realpath (SSDATA (ENCODE_FILE (filename)), NULL); + if (file_normalized) + { + filename = DECODE_FILE (make_unibyte_string (file_normalized, + strlen (file_normalized))); + xfree (file_normalized); + } if (NILP (Ffile_exists_p (filename))) xsignal1 (Qfile_missing, filename); diff --git a/src/w32.c b/src/w32.c index 26cc28f877c..968b4bbe489 100644 --- a/src/w32.c +++ b/src/w32.c @@ -10587,6 +10587,45 @@ w32_my_exename (void) return exename; } +/* Emulate Posix 'realpath'. This is needed in + comp-el-to-eln-rel-filename. */ +char * +realpath (const char *file_name, char *resolved_name) +{ + char *tgt = chase_symlinks (file_name); + char target[MAX_UTF8_PATH]; + + if (tgt == file_name) + { + /* If FILE_NAME is not a symlink, chase_symlinks returns its + argument, possibly not in canonical absolute form. Make sure + we return a canonical file name. */ + if (w32_unicode_filenames) + { + wchar_t file_w[MAX_PATH], tgt_w[MAX_PATH]; + + filename_to_utf16 (file_name, file_w); + if (GetFullPathNameW (file_w, MAX_PATH, tgt_w, NULL) == 0) + return NULL; + filename_from_utf16 (tgt_w, target); + } + else + { + char file_a[MAX_PATH], tgt_a[MAX_PATH]; + + filename_to_ansi (file_name, file_a); + if (GetFullPathNameA (file_a, MAX_PATH, tgt_a, NULL) == 0) + return NULL; + filename_from_ansi (tgt_a, target); + } + tgt = target; + } + + if (resolved_name) + return strcpy (resolved_name, tgt); + return xstrdup (tgt); +} + /* globals_of_w32 is used to initialize those global variables that must always be initialized on startup even when the global variable diff --git a/src/w32.h b/src/w32.h index a382dbe791a..ffa145b1484 100644 --- a/src/w32.h +++ b/src/w32.h @@ -187,6 +187,7 @@ extern DWORD multiByteToWideCharFlags; extern char *w32_my_exename (void); extern const char *w32_relocate (const char *); +extern char *realpath (const char *, char *); extern void init_environment (char **); extern void check_windows_init_file (void);