From 9aa5203b542f0c9ea7d074c6cfde2a28b466f5d1 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 17 Apr 2021 16:49:16 +0300 Subject: [PATCH] Fix loading *.eln files when Emacs is installed via symlinks * src/emacs.c (real_filename, set_invocation_vars) (init_vars_for_load): Functions deleted; callers adjusted. (init_cmdargs): Put back all the code which was extracted into set_invocation_vars. (load_pdump_find_executable): Make sure the return value has any symlinks in it expanded. (load_pdump): Accept only 2 arguments, not 3. Determine both the file name of the Emacs executable and of the dump file in synchronized manner, so that if we decided to look for the dump file in its hardcoded installation directory, the directory of the Emacs executable will also be where we expect it to be installed. Pass only 2 arguments to pdumper_load. (Bug#47800) (Bug#44128) * src/pdumper.c (dump_do_dump_relocation): Use emacs_execdir instead of Vinvocation_directory to produce absolute file names of *.eln files that are recorded in the pdumper file. Pass the full .eln file name to fixup_eln_load_path. (pdumper_set_emacs_execdir) [HAVE_NATIVE_COMP]: New function. (pdumper_load) [HAVE_NATIVE_COMP]: Call pdumper_set_emacs_execdir. * src/comp.c (fixup_eln_load_path): Use Fsubstring_no_properties instead of Fsubstring. No need to cons a file name, as the caller already did that. Use explicit const string to avoid "magic" values. * lisp/startup.el (normal-top-level): Use expand-file-name instead of concat. Decode comp-eln-load-path and expand-file-name its members. --- lisp/startup.el | 13 ++- src/comp.c | 35 ++++---- src/comp.h | 6 +- src/emacs.c | 223 ++++++++++++++++++++---------------------------- src/lisp.h | 1 - src/pdumper.c | 93 +++++++++++++++----- src/pdumper.h | 3 +- 7 files changed, 200 insertions(+), 174 deletions(-) diff --git a/lisp/startup.el b/lisp/startup.el index 6e0faf3f68a..01d28141654 100644 --- a/lisp/startup.el +++ b/lisp/startup.el @@ -544,7 +544,8 @@ It is the default value of the variable `top-level'." (dolist (path (split-string path-env path-separator)) (unless (string= "" path) (push path comp-eln-load-path))))) - (push (concat user-emacs-directory "eln-cache/") comp-eln-load-path) + (push (expand-file-name "eln-cache/" user-emacs-directory) + comp-eln-load-path) ;; When $HOME is set to '/nonexistent' means we are running the ;; testsuite, add a temporary folder in front to produce there ;; new compilations. @@ -636,6 +637,16 @@ It is the default value of the variable `top-level'." (set pathsym (mapcar (lambda (dir) (decode-coding-string dir coding t)) path))))) + (when (featurep 'nativecomp) + (let ((npath (symbol-value 'comp-eln-load-path))) + (set 'comp-eln-load-path + (mapcar (lambda (dir) + ;; Call expand-file-name to remove all the + ;; pesky ".." from the directyory names in + ;; comp-eln-load-path. + (expand-file-name + (decode-coding-string dir coding t))) + npath)))) (dolist (filesym '(data-directory doc-directory exec-directory installation-directory invocation-directory invocation-name diff --git a/src/comp.c b/src/comp.c index c4b9b4b6c10..50947316df8 100644 --- a/src/comp.c +++ b/src/comp.c @@ -4749,29 +4749,30 @@ maybe_defer_native_compilation (Lisp_Object function_name, /* Functions used to load eln files. */ /**************************************/ -/* Fixup the system eln-cache dir. This is the last entry in - `comp-eln-load-path'. */ +/* Fixup the system eln-cache directory, which is the last entry in + `comp-eln-load-path'. Argument is a .eln file in that directory. */ void fixup_eln_load_path (Lisp_Object eln_filename) { Lisp_Object last_cell = Qnil; - Lisp_Object tmp = Vcomp_eln_load_path; - FOR_EACH_TAIL (tmp) - if (CONSP (tmp)) - last_cell = tmp; - - Lisp_Object eln_cache_sys = - Ffile_name_directory (concat2 (Vinvocation_directory, - eln_filename)); - bool preloaded = - !NILP (Fequal (Fsubstring (eln_cache_sys, make_fixnum (-10), - make_fixnum (-1)), - build_string ("preloaded"))); + Lisp_Object tem = Vcomp_eln_load_path; + FOR_EACH_TAIL (tem) + if (CONSP (tem)) + last_cell = tem; + + const char preloaded[] = "preloaded"; + ptrdiff_t preloaded_len = sizeof (preloaded) - 1; + Lisp_Object eln_cache_sys = Ffile_name_directory (eln_filename); + bool preloaded_p = + !NILP (Fequal (Fsubstring_no_properties (eln_cache_sys, + make_fixnum (-preloaded_len - 1), + make_fixnum (-1)), + build_string (preloaded))); /* One or two directories up... */ - for (int i = 0; i < (preloaded ? 2 : 1); i++) + for (int i = 0; i < (preloaded_p ? 2 : 1); i++) eln_cache_sys = - Ffile_name_directory (Fsubstring (eln_cache_sys, Qnil, - make_fixnum (-1))); + Ffile_name_directory (Fsubstring_no_properties (eln_cache_sys, Qnil, + make_fixnum (-1))); Fsetcar (last_cell, eln_cache_sys); } diff --git a/src/comp.h b/src/comp.h index e17b843d139..03d22dfaa0e 100644 --- a/src/comp.h +++ b/src/comp.h @@ -34,7 +34,11 @@ enum { struct Lisp_Native_Comp_Unit { union vectorlike_header header; - /* Original eln file loaded. */ + /* The original eln file loaded. In the pdumper file this is stored + as a cons cell of 2 alternative file names: the car is the + filename relative to the directory of an installed binary, the + cdr is the filename relative to the directory of an uninstalled + binary. This is arranged in loadup.el. */ Lisp_Object file; Lisp_Object optimize_qualities; /* Guard anonymous lambdas against Garbage Collection and serve diff --git a/src/emacs.c b/src/emacs.c index a2565645c6c..d27b1c1351d 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -440,53 +440,33 @@ terminate_due_to_signal (int sig, int backtrace_limit) exit (1); } -/* Return the real filename following symlinks in case. - The caller should deallocate the returned buffer. */ - -static char * -real_filename (char *filename) -{ - char *real_name; -#ifdef WINDOWSNT - /* w32_my_exename resolves symlinks internally, so no need to - call realpath. */ - real_name = xstrdup (filename); -#else - real_name = realpath (filename, NULL); - if (!real_name) - fatal ("could not resolve realpath of \"%s\": %s", - filename, strerror (errno)); -#endif - return real_name; -} - -/* Set `invocation-name' `invocation-directory'. */ - + +/* Code for dealing with Lisp access to the Unix command line. */ static void -set_invocation_vars (char *argv0, char const *original_pwd) +init_cmdargs (int argc, char **argv, int skip_args, char const *original_pwd) { - Lisp_Object raw_name, handler; + int i; + Lisp_Object name, dir, handler; + ptrdiff_t count = SPECPDL_INDEX (); + Lisp_Object raw_name; AUTO_STRING (slash_colon, "/:"); + initial_argv = argv; + initial_argc = argc; + #ifdef WINDOWSNT - /* Must use argv0 converted to UTF-8, as it begets many standard + /* Must use argv[0] converted to UTF-8, as it begets many standard file and directory names. */ { - char argv0_1[MAX_UTF8_PATH]; + char argv0[MAX_UTF8_PATH]; - /* Avoid calling 'openp' below, as we aren't ready for that yet: - emacs_dir is not yet defined in the environment, and therefore - emacs_root_dir, called by expand-file-name, will abort. */ - if (!IS_ABSOLUTE_FILE_NAME (argv0)) - argv0 = w32_my_exename (); - - if (filename_from_ansi (argv0, argv0_1) == 0) - raw_name = build_unibyte_string (argv0_1); - else + if (filename_from_ansi (argv[0], argv0) == 0) raw_name = build_unibyte_string (argv0); + else + raw_name = build_unibyte_string (argv[0]); } #else - raw_name = build_unibyte_string (argv0); + raw_name = build_unibyte_string (argv[0]); #endif /* Add /: to the front of the name @@ -495,26 +475,16 @@ set_invocation_vars (char *argv0, char const *original_pwd) if (! NILP (handler)) raw_name = concat2 (slash_colon, raw_name); - char *filename = real_filename (SSDATA (raw_name)); - raw_name = build_unibyte_string (filename); - xfree (filename); - Vinvocation_name = Ffile_name_nondirectory (raw_name); Vinvocation_directory = Ffile_name_directory (raw_name); -#ifdef WINDOWSNT - eassert (!NILP (Vinvocation_directory) - && !NILP (Ffile_name_absolute_p (Vinvocation_directory))); -#endif - - /* If we got no directory in argv0, search PATH to find where + /* If we got no directory in argv[0], search PATH to find where Emacs actually came from. */ if (NILP (Vinvocation_directory)) { Lisp_Object found; - int yes = - openp (Vexec_path, Vinvocation_name, Vexec_suffixes, &found, - make_fixnum (X_OK), false, false); + int yes = openp (Vexec_path, Vinvocation_name, Vexec_suffixes, + &found, make_fixnum (X_OK), false, false); if (yes == 1) { /* Add /: to the front of the name @@ -536,38 +506,6 @@ set_invocation_vars (char *argv0, char const *original_pwd) Vinvocation_directory = Fexpand_file_name (Vinvocation_directory, odir); } -} - -/* Initialize a number of variables (ultimately - 'Vinvocation_directory') needed by pdumper to complete native code - load. */ - -void -init_vars_for_load (char *argv0, char const *original_pwd) -{ - /* This function is called from within pdumper while loading (as - soon as we are able to allocate) or later during boot if pdumper - is not used. No need to run it twice. */ - static bool double_run_guard; - if (double_run_guard) - return; - double_run_guard = true; - - init_callproc_1 (); /* Must precede init_cmdargs and init_sys_modes. */ - set_invocation_vars (argv0, original_pwd); -} - - -/* Code for dealing with Lisp access to the Unix command line. */ -static void -init_cmdargs (int argc, char **argv, int skip_args, char const *original_pwd) -{ - int i; - Lisp_Object name, dir; - ptrdiff_t count = SPECPDL_INDEX (); - - initial_argv = argv; - initial_argc = argc; Vinstallation_directory = Qnil; @@ -801,6 +739,8 @@ load_pdump_find_executable (char const *argv0, ptrdiff_t *candidate_size) implementation of malloc, since the caller calls our free. */ #ifdef WINDOWSNT char *prog_fname = w32_my_exename (); + if (prog_fname) + *candidate_size = strlen (prog_fname) + 1; return prog_fname ? xstrdup (prog_fname) : NULL; #else /* !WINDOWSNT */ char *candidate = NULL; @@ -846,7 +786,19 @@ load_pdump_find_executable (char const *argv0, ptrdiff_t *candidate_size) struct stat st; if (file_access_p (candidate, X_OK) && stat (candidate, &st) == 0 && S_ISREG (st.st_mode)) - return candidate; + { + /* People put on PATH a symlink to the real Emacs + executable, with all the auxiliary files where the real + executable lives. Support that. */ + if (lstat (candidate, &st) == 0 && S_ISLNK (st.st_mode)) + { + char *real_name = realpath (candidate, NULL); + + if (real_name) + return real_name; + } + return candidate; + } *candidate = '\0'; } while (*path++ != '\0'); @@ -856,10 +808,11 @@ load_pdump_find_executable (char const *argv0, ptrdiff_t *candidate_size) } static void -load_pdump (int argc, char **argv, char const *original_pwd) +load_pdump (int argc, char **argv) { const char *const suffix = ".pdmp"; int result; + char *emacs_executable = argv[0]; const char *strip_suffix = #if defined DOS_NT || defined CYGWIN ".exe" @@ -889,9 +842,19 @@ load_pdump (int argc, char **argv, char const *original_pwd) skip_args++; } + /* Where's our executable? */ + ptrdiff_t bufsize, exec_bufsize; + emacs_executable = load_pdump_find_executable (argv[0], &bufsize); + exec_bufsize = bufsize; + + /* If we couldn't find our executable, go straight to looking for + the dump in the hardcoded location. */ + if (!(emacs_executable && *emacs_executable)) + goto hardcoded; + if (dump_file) { - result = pdumper_load (dump_file, argv[0], original_pwd); + result = pdumper_load (dump_file, emacs_executable); if (result != PDUMPER_LOAD_SUCCESS) fatal ("could not load dump file \"%s\": %s", @@ -905,42 +868,29 @@ load_pdump (int argc, char **argv, char const *original_pwd) 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. */ - 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 (dump_file && *dump_file) - { - char *real_exename = real_filename (dump_file); - xfree (dump_file); - dump_file = real_exename; - ptrdiff_t exenamelen = strlen (dump_file); -#ifndef WINDOWSNT - bufsize = exenamelen + 1; -#endif - if (strip_suffix) - { - 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; - } - 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, argv[0], original_pwd); - if (result == PDUMPER_LOAD_SUCCESS) - goto out; - - if (result != PDUMPER_LOAD_FILE_NOT_FOUND) - fatal ("could not load dump file \"%s\": %s", - dump_file, dump_error_to_string (result)); - } - + ptrdiff_t exenamelen = strlen (emacs_executable); + if (strip_suffix) + { + ptrdiff_t strip_suffix_length = strlen (strip_suffix); + ptrdiff_t prefix_length = exenamelen - strip_suffix_length; + if (0 <= prefix_length + && !memcmp (&emacs_executable[prefix_length], strip_suffix, + strip_suffix_length)) + exenamelen = prefix_length; + } + ptrdiff_t needed = exenamelen + strlen (suffix) + 1; + dump_file = xpalloc (NULL, &bufsize, needed - bufsize, -1, 1); + memcpy (dump_file, emacs_executable, exenamelen); + strcpy (dump_file + exenamelen, suffix); + result = pdumper_load (dump_file, emacs_executable); + if (result == PDUMPER_LOAD_SUCCESS) + goto out; + + if (result != PDUMPER_LOAD_FILE_NOT_FOUND) + fatal ("could not load dump file \"%s\": %s", + dump_file, dump_error_to_string (result)); + + hardcoded: #ifdef WINDOWSNT /* On MS-Windows, PATH_EXEC normally starts with a literal "%emacs_dir%", so it will never work without some tweaking. */ @@ -951,11 +901,11 @@ load_pdump (int argc, char **argv, char const *original_pwd) "emacs.pdmp" so that the Emacs binary still works if the user copies and renames it. */ const char *argv0_base = "emacs"; - ptrdiff_t needed = (strlen (path_exec) - + 1 - + strlen (argv0_base) - + strlen (suffix) - + 1); + needed = (strlen (path_exec) + + 1 + + strlen (argv0_base) + + strlen (suffix) + + 1); if (bufsize < needed) { xfree (dump_file); @@ -963,7 +913,19 @@ load_pdump (int argc, char **argv, char const *original_pwd) } sprintf (dump_file, "%s%c%s%s", path_exec, DIRECTORY_SEP, argv0_base, suffix); - result = pdumper_load (dump_file, argv[0], original_pwd); + /* Assume the Emacs binary lives in a sibling directory as set up by + the default installation configuration. */ + const char *go_up = "../../../../bin/"; + needed += strlen (strip_suffix) - strlen (suffix) + strlen (go_up); + if (exec_bufsize < needed) + { + xfree (emacs_executable); + emacs_executable = xpalloc (NULL, &exec_bufsize, needed - exec_bufsize, + -1, 1); + } + sprintf (emacs_executable, "%s%c%s%s%s", + path_exec, DIRECTORY_SEP, go_up, argv0_base, strip_suffix); + result = pdumper_load (dump_file, emacs_executable); if (result == PDUMPER_LOAD_FILE_NOT_FOUND) { @@ -998,7 +960,7 @@ load_pdump (int argc, char **argv, char const *original_pwd) #endif sprintf (dump_file, "%s%c%s%s", path_exec, DIRECTORY_SEP, argv0_base, suffix); - result = pdumper_load (dump_file, argv[0], original_pwd); + result = pdumper_load (dump_file, emacs_executable); } if (result != PDUMPER_LOAD_SUCCESS) @@ -1010,6 +972,7 @@ load_pdump (int argc, char **argv, char const *original_pwd) out: xfree (dump_file); + xfree (emacs_executable); } #endif /* HAVE_PDUMPER */ @@ -1320,10 +1283,9 @@ main (int argc, char **argv) w32_init_main_thread (); #endif - emacs_wd = emacs_get_current_dir_name (); #ifdef HAVE_PDUMPER if (attempt_load_pdump) - load_pdump (argc, argv, emacs_wd); + load_pdump (argc, argv); #endif argc = maybe_disable_address_randomization (argc, argv); @@ -1395,6 +1357,7 @@ main (int argc, char **argv) exit (0); } + emacs_wd = emacs_get_current_dir_name (); #ifdef HAVE_PDUMPER if (dumped_with_pdumper_p ()) pdumper_record_wd (emacs_wd); @@ -2038,8 +2001,6 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem /* Init buffer storage and default directory of main buffer. */ init_buffer (); - init_vars_for_load (argv[0], original_pwd); - /* Must precede init_lread. */ init_cmdargs (argc, argv, skip_args, original_pwd); diff --git a/src/lisp.h b/src/lisp.h index 474e49c8e1e..f83c55f827d 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4450,7 +4450,6 @@ extern bool display_arg; extern Lisp_Object decode_env_path (const char *, const char *, bool); extern Lisp_Object empty_unibyte_string, empty_multibyte_string; extern AVOID terminate_due_to_signal (int, int); -extern void init_vars_for_load (char *, char const *); #ifdef WINDOWSNT extern Lisp_Object Vlibrary_cache; #endif diff --git a/src/pdumper.c b/src/pdumper.c index dc893c59bfa..c9285ddbc78 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -4356,6 +4356,16 @@ pdumper_remember_lv_ptr_raw_impl (void *ptr, enum Lisp_Type type) } +#ifdef HAVE_NATIVE_COMP +/* This records the directory where the Emacs executable lives, to be + used for locating the native-lisp directory from which we need to + load the preloaded *.eln files. See pdumper_set_emacs_execdir + below. */ +static char *emacs_execdir; +static ptrdiff_t execdir_size; +static ptrdiff_t execdir_len; +#endif + /* Dump runtime */ enum dump_memory_protection { @@ -5269,35 +5279,54 @@ dump_do_dump_relocation (const uintptr_t dump_base, struct Lisp_Native_Comp_Unit *comp_u = dump_ptr (dump_base, reloc_offset); comp_u->lambda_gc_guard_h = CALLN (Fmake_hash_table, QCtest, Qeq); - if (!CONSP (comp_u->file)) + if (STRINGP (comp_u->file)) error ("Trying to load incoherent dumped eln file %s", SSDATA (comp_u->file)); + /* emacs_execdir is always unibyte, but the file names in + comp_u->file could be multibyte, so we need to encode + them. */ + Lisp_Object cu_file1 = ENCODE_FILE (XCAR (comp_u->file)); + Lisp_Object cu_file2 = ENCODE_FILE (XCDR (comp_u->file)); + ptrdiff_t fn1_len = SBYTES (cu_file1), fn2_len = SBYTES (cu_file2); + Lisp_Object eln_fname; + char *fndata; + /* Check just once if this is a local build or Emacs was installed. */ + /* Can't use expand-file-name here, because we are too early + in the startup, and we will crash at least on WINDOWSNT. */ if (installation_state == UNKNOWN) { - /* Can't use expand-file-name here, because we are too - early in the startup, and we will crash at least on - WINDOWSNT. */ - Lisp_Object fname = - concat2 (Vinvocation_directory, XCAR (comp_u->file)); - if (file_access_p (SSDATA (ENCODE_FILE (fname)), F_OK)) - { - installation_state = INSTALLED; - fixup_eln_load_path (XCAR (comp_u->file)); - } + eln_fname = make_uninit_string (execdir_len + fn1_len); + fndata = SSDATA (eln_fname); + memcpy (fndata, emacs_execdir, execdir_len); + memcpy (fndata + execdir_len, SSDATA (cu_file1), fn1_len); + if (file_access_p (fndata, F_OK)) + installation_state = INSTALLED; else { + eln_fname = make_uninit_string (execdir_len + fn2_len); + fndata = SSDATA (eln_fname); + memcpy (fndata, emacs_execdir, execdir_len); + memcpy (fndata + execdir_len, SSDATA (cu_file2), fn2_len); installation_state = LOCAL_BUILD; - fixup_eln_load_path (XCDR (comp_u->file)); } + fixup_eln_load_path (eln_fname); + } + else + { + ptrdiff_t fn_len = + installation_state == INSTALLED ? fn1_len : fn2_len; + Lisp_Object cu_file = + installation_state == INSTALLED ? cu_file1 : cu_file2; + eln_fname = make_uninit_string (execdir_len + fn_len); + fndata = SSDATA (eln_fname); + memcpy (fndata, emacs_execdir, execdir_len); + memcpy (fndata + execdir_len, SSDATA (cu_file), fn_len); } - comp_u->file = - concat2 (Vinvocation_directory, - installation_state == INSTALLED - ? XCAR (comp_u->file) : XCDR (comp_u->file)); - comp_u->handle = dynlib_open (SSDATA (ENCODE_FILE (comp_u->file))); + comp_u->file = eln_fname; + comp_u->handle = dynlib_open (SSDATA (eln_fname)); if (!comp_u->handle) error ("%s", dynlib_error ()); load_comp_unit (comp_u, true, false); @@ -5435,6 +5464,26 @@ dump_do_all_emacs_relocations (const struct dump_header *const header, dump_do_emacs_relocation (dump_base, r[i]); } +#ifdef HAVE_NATIVE_COMP +/* Compute and record the directory of the Emacs executable given the + file name of that executable. */ +static void +pdumper_set_emacs_execdir (char *emacs_executable) +{ + char *p = emacs_executable + strlen (emacs_executable); + + while (p > emacs_executable + && !IS_DIRECTORY_SEP (p[-1])) + --p; + eassert (p > emacs_executable); + emacs_execdir = xpalloc (emacs_execdir, &execdir_size, + p - emacs_executable + 1 - execdir_size, -1, 1); + memcpy (emacs_execdir, emacs_executable, p - emacs_executable); + execdir_len = p - emacs_executable; + emacs_execdir[execdir_len] = '\0'; +} +#endif + enum dump_section { DS_HOT, @@ -5451,7 +5500,7 @@ static Lisp_Object *pdumper_hashes = &zero_vector; N.B. We run very early in initialization, so we can't use lisp, unwinding, xmalloc, and so on. */ int -pdumper_load (const char *dump_filename, char *argv0, char const *original_pwd) +pdumper_load (const char *dump_filename, char *argv0) { intptr_t dump_size; struct stat stat; @@ -5607,9 +5656,11 @@ pdumper_load (const char *dump_filename, char *argv0, char const *original_pwd) for (int i = 0; i < nr_dump_hooks; ++i) dump_hooks[i] (); - /* Once we can allocate and before loading .eln files we must set - Vinvocation_directory (.eln paths are relative to it). */ - init_vars_for_load (argv0, original_pwd); +#ifdef HAVE_NATIVE_COMP + pdumper_set_emacs_execdir (argv0); +#else + (void) argv0; +#endif dump_do_all_dump_reloc_for_phase (header, dump_base, LATE_RELOCS); dump_do_all_dump_reloc_for_phase (header, dump_base, VERY_LATE_RELOCS); diff --git a/src/pdumper.h b/src/pdumper.h index 49e6739b0dc..deec9af046d 100644 --- a/src/pdumper.h +++ b/src/pdumper.h @@ -140,8 +140,7 @@ enum pdumper_load_result PDUMPER_LOAD_ERROR /* Must be last, as errno may be added. */ }; -int pdumper_load (const char *dump_filename, char *argv0, - char const *original_pwd); +int pdumper_load (const char *dump_filename, char *argv0); struct pdumper_loaded_dump { -- 2.39.2