diff options
-rw-r--r-- | nt/mingw-cfg.site | 5 | ||||
-rw-r--r-- | src/comp.c | 19 | ||||
-rw-r--r-- | src/w32.c | 39 | ||||
-rw-r--r-- | src/w32.h | 1 |
4 files changed, 53 insertions, 11 deletions
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); |