diff options
| author | Paul Eggert | 2019-09-11 11:26:07 -0700 |
|---|---|---|
| committer | Paul Eggert | 2019-09-11 11:27:14 -0700 |
| commit | 5fafa40d076ee24baf880e97d4290b6196cf838a (patch) | |
| tree | 03452b023e9777409d979932b53f9ef347601b76 /src | |
| parent | a6daae7b3df3a964b3dcde85987c02fd0af66a89 (diff) | |
| download | emacs-5fafa40d076ee24baf880e97d4290b6196cf838a.tar.gz emacs-5fafa40d076ee24baf880e97d4290b6196cf838a.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/alloc.c | 3 | ||||
| -rw-r--r-- | src/emacs.c | 182 | ||||
| -rw-r--r-- | src/fileio.c | 2 | ||||
| -rw-r--r-- | src/lisp.h | 1 | ||||
| -rw-r--r-- | src/pdumper.c | 11 | ||||
| -rw-r--r-- | src/pdumper.h | 4 |
6 files changed, 91 insertions, 112 deletions
diff --git a/src/alloc.c b/src/alloc.c index be98cfd5f53..2d490f3bb75 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -3844,6 +3844,9 @@ set_interval_marked (INTERVAL i) | |||
| 3844 | void | 3844 | void |
| 3845 | memory_full (size_t nbytes) | 3845 | memory_full (size_t nbytes) |
| 3846 | { | 3846 | { |
| 3847 | if (!initialized) | ||
| 3848 | fatal ("memory exhausted"); | ||
| 3849 | |||
| 3847 | /* Do not go into hysterics merely because a large request failed. */ | 3850 | /* Do not go into hysterics merely because a large request failed. */ |
| 3848 | bool enough_free_memory = false; | 3851 | bool enough_free_memory = false; |
| 3849 | if (SPARE_MEMORY < nbytes) | 3852 | if (SPARE_MEMORY < nbytes) |
diff --git a/src/emacs.c b/src/emacs.c index 53572d7f0c8..5a526687b14 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -662,7 +662,7 @@ argmatch (char **argv, int argc, const char *sstr, const char *lstr, | |||
| 662 | #ifdef HAVE_PDUMPER | 662 | #ifdef HAVE_PDUMPER |
| 663 | 663 | ||
| 664 | static const char * | 664 | static const char * |
| 665 | dump_error_to_string (enum pdumper_load_result result) | 665 | dump_error_to_string (int result) |
| 666 | { | 666 | { |
| 667 | switch (result) | 667 | switch (result) |
| 668 | { | 668 | { |
| @@ -681,37 +681,29 @@ dump_error_to_string (enum pdumper_load_result result) | |||
| 681 | case PDUMPER_LOAD_VERSION_MISMATCH: | 681 | case PDUMPER_LOAD_VERSION_MISMATCH: |
| 682 | return "not built for this Emacs executable"; | 682 | return "not built for this Emacs executable"; |
| 683 | default: | 683 | default: |
| 684 | return "generic error"; | 684 | return (result <= PDUMPER_LOAD_ERROR |
| 685 | ? "generic error" | ||
| 686 | : strerror (result - PDUMPER_LOAD_ERROR)); | ||
| 685 | } | 687 | } |
| 686 | } | 688 | } |
| 687 | 689 | ||
| 688 | /* Find a path (absolute or relative) to the Emacs executable. | 690 | /* Find a name (absolute or relative) of the Emacs executable whose |
| 689 | Called early in initialization by portable dumper loading code, so we | 691 | name (as passed into this program) is ARGV0. Called early in |
| 690 | can't use lisp and associated machinery. On success, *EXENAME is | 692 | initialization by portable dumper loading code, so avoid Lisp and |
| 691 | set to a heap-allocated string giving a path to the Emacs | 693 | associated machinery. Return a heap-allocated string giving a name |
| 692 | executable or to NULL if we can't determine the path immediately. | 694 | of the Emacs executable, or an empty heap-allocated string or NULL |
| 693 | */ | 695 | if not found. Store into *CANDIDATE_SIZE a lower bound on the size |
| 694 | static enum pdumper_load_result | 696 | of any heap allocation. */ |
| 695 | load_pdump_find_executable (const char* argv0, char **exename) | 697 | static char * |
| 698 | load_pdump_find_executable (char const *argv0, ptrdiff_t *candidate_size) | ||
| 696 | { | 699 | { |
| 697 | enum pdumper_load_result result; | 700 | *candidate_size = 0; |
| 701 | |||
| 702 | /* Use xstrdup etc. to allocate storage, so as to call our private | ||
| 703 | implementation of malloc, since the caller calls our free. */ | ||
| 698 | #ifdef WINDOWSNT | 704 | #ifdef WINDOWSNT |
| 699 | result = PDUMPER_LOAD_ERROR; | ||
| 700 | *exename = NULL; | ||
| 701 | char *prog_fname = w32_my_exename (); | 705 | char *prog_fname = w32_my_exename (); |
| 702 | if (prog_fname) | 706 | return prog_fname ? xstrdup (prog_fname) : NULL; |
| 703 | { | ||
| 704 | result = PDUMPER_LOAD_OOM; | ||
| 705 | /* Use xstrdup, so as to call our private implementation of | ||
| 706 | malloc, since the caller calls our free. */ | ||
| 707 | char *ret = xstrdup (prog_fname); | ||
| 708 | if (ret) | ||
| 709 | { | ||
| 710 | *exename = ret; | ||
| 711 | result = PDUMPER_LOAD_SUCCESS; | ||
| 712 | } | ||
| 713 | } | ||
| 714 | return result; | ||
| 715 | #else /* !WINDOWSNT */ | 707 | #else /* !WINDOWSNT */ |
| 716 | char *candidate = NULL; | 708 | char *candidate = NULL; |
| 717 | 709 | ||
| @@ -719,33 +711,23 @@ load_pdump_find_executable (const char* argv0, char **exename) | |||
| 719 | path already, so just copy it. */ | 711 | path already, so just copy it. */ |
| 720 | eassert (argv0); | 712 | eassert (argv0); |
| 721 | if (strchr (argv0, DIRECTORY_SEP)) | 713 | if (strchr (argv0, DIRECTORY_SEP)) |
| 722 | { | 714 | return xstrdup (argv0); |
| 723 | result = PDUMPER_LOAD_OOM; | 715 | ptrdiff_t argv0_length = strlen (argv0); |
| 724 | char *ret = strdup (argv0); | ||
| 725 | if (!ret) | ||
| 726 | goto out; | ||
| 727 | result = PDUMPER_LOAD_SUCCESS; | ||
| 728 | *exename = ret; | ||
| 729 | goto out; | ||
| 730 | } | ||
| 731 | size_t argv0_length = strlen (argv0); | ||
| 732 | 716 | ||
| 733 | const char *path = getenv ("PATH"); | 717 | const char *path = getenv ("PATH"); |
| 734 | if (!path) | 718 | if (!path) |
| 735 | { | 719 | { |
| 736 | /* Default PATH is implementation-defined, so we don't know how | 720 | /* Default PATH is implementation-defined, so we don't know how |
| 737 | to conduct the search. */ | 721 | to conduct the search. */ |
| 738 | result = PDUMPER_LOAD_SUCCESS; | 722 | return NULL; |
| 739 | *exename = NULL; | ||
| 740 | goto out; | ||
| 741 | } | 723 | } |
| 742 | 724 | ||
| 743 | /* Actually try each concatenation of a path element and the | 725 | /* Actually try each concatenation of a path element and the |
| 744 | executable basename. */ | 726 | executable basename. */ |
| 745 | const char path_sep[] = { SEPCHAR, '\0' }; | ||
| 746 | do | 727 | do |
| 747 | { | 728 | { |
| 748 | size_t path_part_length = strcspn (path, path_sep); | 729 | static char const path_sep[] = { SEPCHAR, '\0' }; |
| 730 | ptrdiff_t path_part_length = strcspn (path, path_sep); | ||
| 749 | const char *path_part = path; | 731 | const char *path_part = path; |
| 750 | path += path_part_length; | 732 | path += path_part_length; |
| 751 | if (path_part_length == 0) | 733 | if (path_part_length == 0) |
| @@ -753,46 +735,34 @@ load_pdump_find_executable (const char* argv0, char **exename) | |||
| 753 | path_part = "."; | 735 | path_part = "."; |
| 754 | path_part_length = 1; | 736 | path_part_length = 1; |
| 755 | } | 737 | } |
| 756 | size_t candidate_length = path_part_length + 1 + argv0_length; | 738 | ptrdiff_t needed = path_part_length + 1 + argv0_length + 1; |
| 757 | { | 739 | if (*candidate_size <= needed) |
| 758 | char *new_candidate = realloc (candidate, candidate_length + 1); | 740 | { |
| 759 | if (!new_candidate) | 741 | xfree (candidate); |
| 760 | { | 742 | candidate = xpalloc (NULL, candidate_size, |
| 761 | result = PDUMPER_LOAD_OOM; | 743 | needed - *candidate_size + 1, -1, 1); |
| 762 | goto out; | 744 | } |
| 763 | } | ||
| 764 | candidate = new_candidate; | ||
| 765 | } | ||
| 766 | memcpy (candidate + 0, path_part, path_part_length); | 745 | memcpy (candidate + 0, path_part, path_part_length); |
| 767 | candidate[path_part_length] = DIRECTORY_SEP; | 746 | candidate[path_part_length] = DIRECTORY_SEP; |
| 768 | memcpy (candidate + path_part_length + 1, argv0, argv0_length + 1); | 747 | memcpy (candidate + path_part_length + 1, argv0, argv0_length + 1); |
| 769 | struct stat st; | 748 | struct stat st; |
| 770 | if (!access (candidate, X_OK) && | 749 | if (check_executable (candidate) |
| 771 | !stat (candidate, &st) && | 750 | && stat (candidate, &st) == 0 && S_ISREG (st.st_mode)) |
| 772 | S_ISREG (st.st_mode)) | 751 | return candidate; |
| 773 | { | 752 | *candidate = '\0'; |
| 774 | *exename = candidate; | 753 | } |
| 775 | candidate = NULL; | 754 | while (*path++ != '\0'); |
| 776 | break; | ||
| 777 | } | ||
| 778 | } while ((path++)[0] != '\0'); | ||
| 779 | |||
| 780 | result = PDUMPER_LOAD_SUCCESS; | ||
| 781 | 755 | ||
| 782 | out: | 756 | return candidate; |
| 783 | free (candidate); | ||
| 784 | return result; | ||
| 785 | #endif /* !WINDOWSNT */ | 757 | #endif /* !WINDOWSNT */ |
| 786 | } | 758 | } |
| 787 | 759 | ||
| 788 | static enum pdumper_load_result | 760 | static void |
| 789 | load_pdump (int argc, char **argv) | 761 | load_pdump (int argc, char **argv) |
| 790 | { | 762 | { |
| 791 | const char *const suffix = ".pdmp"; | 763 | const char *const suffix = ".pdmp"; |
| 792 | enum pdumper_load_result result; | 764 | int result; |
| 793 | char *exename = NULL; | 765 | const char *strip_suffix = |
| 794 | char *real_exename = NULL; | ||
| 795 | const char* strip_suffix = | ||
| 796 | #if defined DOS_NT || defined CYGWIN | 766 | #if defined DOS_NT || defined CYGWIN |
| 797 | ".exe" | 767 | ".exe" |
| 798 | #else | 768 | #else |
| @@ -821,7 +791,6 @@ load_pdump (int argc, char **argv) | |||
| 821 | skip_args++; | 791 | skip_args++; |
| 822 | } | 792 | } |
| 823 | 793 | ||
| 824 | result = PDUMPER_NOT_LOADED; | ||
| 825 | if (dump_file) | 794 | if (dump_file) |
| 826 | { | 795 | { |
| 827 | result = pdumper_load (dump_file); | 796 | result = pdumper_load (dump_file); |
| @@ -829,8 +798,7 @@ load_pdump (int argc, char **argv) | |||
| 829 | if (result != PDUMPER_LOAD_SUCCESS) | 798 | if (result != PDUMPER_LOAD_SUCCESS) |
| 830 | fatal ("could not load dump file \"%s\": %s", | 799 | fatal ("could not load dump file \"%s\": %s", |
| 831 | dump_file, dump_error_to_string (result)); | 800 | dump_file, dump_error_to_string (result)); |
| 832 | else | 801 | return; |
| 833 | goto out; | ||
| 834 | } | 802 | } |
| 835 | 803 | ||
| 836 | /* Look for a dump file in the same directory as the executable; it | 804 | /* Look for a dump file in the same directory as the executable; it |
| @@ -839,44 +807,41 @@ load_pdump (int argc, char **argv) | |||
| 839 | so we can't use decode_env_path. We're working in whatever | 807 | so we can't use decode_env_path. We're working in whatever |
| 840 | encoding the system natively uses for filesystem access, so | 808 | encoding the system natively uses for filesystem access, so |
| 841 | there's no need for character set conversion. */ | 809 | there's no need for character set conversion. */ |
| 842 | result = load_pdump_find_executable (argv[0], &exename); | 810 | ptrdiff_t bufsize; |
| 843 | if (result != PDUMPER_LOAD_SUCCESS) | 811 | dump_file = load_pdump_find_executable (argv[0], &bufsize); |
| 844 | goto out; | ||
| 845 | 812 | ||
| 846 | /* If we couldn't find our executable, go straight to looking for | 813 | /* If we couldn't find our executable, go straight to looking for |
| 847 | the dump in the hardcoded location. */ | 814 | the dump in the hardcoded location. */ |
| 848 | if (exename) | 815 | if (dump_file && *dump_file) |
| 849 | { | 816 | { |
| 850 | #ifdef WINDOWSNT | 817 | #ifdef WINDOWSNT |
| 851 | /* w32_my_exename resolves symlinks internally, so no need to | 818 | /* w32_my_exename resolves symlinks internally, so no need to |
| 852 | call realpath. */ | 819 | call realpath. */ |
| 853 | real_exename = exename; | ||
| 854 | exename = NULL; | ||
| 855 | #else | 820 | #else |
| 856 | real_exename = realpath (exename, NULL); | 821 | char *real_exename = realpath (dump_file, NULL); |
| 857 | if (!real_exename) | 822 | if (!real_exename) |
| 858 | fatal ("could not resolve realpath of \"%s\": %s", | 823 | fatal ("could not resolve realpath of \"%s\": %s", |
| 859 | exename, strerror (errno)); | 824 | dump_file, strerror (errno)); |
| 825 | xfree (dump_file); | ||
| 826 | dump_file = real_exename; | ||
| 827 | #endif | ||
| 828 | ptrdiff_t exenamelen = strlen (dump_file); | ||
| 829 | #ifndef WINDOWSNT | ||
| 830 | bufsize = exenamelen + 1; | ||
| 860 | #endif | 831 | #endif |
| 861 | size_t real_exename_length = strlen (real_exename); | ||
| 862 | if (strip_suffix) | 832 | if (strip_suffix) |
| 863 | { | 833 | { |
| 864 | size_t strip_suffix_length = strlen (strip_suffix); | 834 | ptrdiff_t strip_suffix_length = strlen (strip_suffix); |
| 865 | if (real_exename_length >= strip_suffix_length) | 835 | ptrdiff_t prefix_length = exenamelen - strip_suffix_length; |
| 866 | { | 836 | if (0 <= prefix_length |
| 867 | size_t prefix_length = | 837 | && !memcmp (&dump_file[prefix_length], strip_suffix, |
| 868 | real_exename_length - strip_suffix_length; | 838 | strip_suffix_length)) |
| 869 | if (!memcmp (&real_exename[prefix_length], | 839 | exenamelen = prefix_length; |
| 870 | strip_suffix, | ||
| 871 | strip_suffix_length)) | ||
| 872 | real_exename_length = prefix_length; | ||
| 873 | } | ||
| 874 | } | 840 | } |
| 875 | dump_file = alloca (real_exename_length + strlen (suffix) + 1); | 841 | ptrdiff_t needed = exenamelen + strlen (suffix) + 1; |
| 876 | memcpy (dump_file, real_exename, real_exename_length); | 842 | if (bufsize < needed) |
| 877 | memcpy (dump_file + real_exename_length, | 843 | dump_file = xpalloc (dump_file, &bufsize, needed - bufsize, -1, 1); |
| 878 | suffix, | 844 | strcpy (dump_file + exenamelen, suffix); |
| 879 | strlen (suffix) + 1); | ||
| 880 | result = pdumper_load (dump_file); | 845 | result = pdumper_load (dump_file); |
| 881 | if (result == PDUMPER_LOAD_SUCCESS) | 846 | if (result == PDUMPER_LOAD_SUCCESS) |
| 882 | goto out; | 847 | goto out; |
| @@ -896,16 +861,19 @@ load_pdump (int argc, char **argv) | |||
| 896 | "emacs.pdmp" so that the Emacs binary still works if the user | 861 | "emacs.pdmp" so that the Emacs binary still works if the user |
| 897 | copies and renames it. */ | 862 | copies and renames it. */ |
| 898 | const char *argv0_base = "emacs"; | 863 | const char *argv0_base = "emacs"; |
| 899 | dump_file = alloca (strlen (path_exec) | 864 | ptrdiff_t needed = (strlen (path_exec) |
| 900 | + 1 | 865 | + 1 |
| 901 | + strlen (argv0_base) | 866 | + strlen (argv0_base) |
| 902 | + strlen (suffix) | 867 | + strlen (suffix) |
| 903 | + 1); | 868 | + 1); |
| 869 | if (bufsize < needed) | ||
| 870 | { | ||
| 871 | xfree (dump_file); | ||
| 872 | dump_file = xpalloc (NULL, &bufsize, needed - bufsize, -1, 1); | ||
| 873 | } | ||
| 904 | sprintf (dump_file, "%s%c%s%s", | 874 | sprintf (dump_file, "%s%c%s%s", |
| 905 | path_exec, DIRECTORY_SEP, argv0_base, suffix); | 875 | path_exec, DIRECTORY_SEP, argv0_base, suffix); |
| 906 | result = pdumper_load (dump_file); | 876 | result = pdumper_load (dump_file); |
| 907 | if (result == PDUMPER_LOAD_SUCCESS) | ||
| 908 | goto out; | ||
| 909 | 877 | ||
| 910 | if (result == PDUMPER_LOAD_FILE_NOT_FOUND) | 878 | if (result == PDUMPER_LOAD_FILE_NOT_FOUND) |
| 911 | { | 879 | { |
| @@ -920,13 +888,18 @@ load_pdump (int argc, char **argv) | |||
| 920 | last_sep = p; | 888 | last_sep = p; |
| 921 | } | 889 | } |
| 922 | argv0_base = last_sep ? last_sep + 1 : argv[0]; | 890 | argv0_base = last_sep ? last_sep + 1 : argv[0]; |
| 923 | dump_file = alloca (strlen (path_exec) | 891 | ptrdiff_t needed = (strlen (path_exec) |
| 924 | + 1 | 892 | + 1 |
| 925 | + strlen (argv0_base) | 893 | + strlen (argv0_base) |
| 926 | + strlen (suffix) | 894 | + strlen (suffix) |
| 927 | + 1); | 895 | + 1); |
| 896 | if (bufsize < needed) | ||
| 897 | { | ||
| 898 | xfree (dump_file); | ||
| 899 | dump_file = xmalloc (needed); | ||
| 900 | } | ||
| 928 | #ifdef DOS_NT | 901 | #ifdef DOS_NT |
| 929 | size_t argv0_len = strlen (argv0_base); | 902 | ptrdiff_t argv0_len = strlen (argv0_base); |
| 930 | if (argv0_len >= 4 | 903 | if (argv0_len >= 4 |
| 931 | && c_strcasecmp (argv0_base + argv0_len - 4, ".exe") == 0) | 904 | && c_strcasecmp (argv0_base + argv0_len - 4, ".exe") == 0) |
| 932 | sprintf (dump_file, "%s%c%.*s%s", path_exec, DIRECTORY_SEP, | 905 | sprintf (dump_file, "%s%c%.*s%s", path_exec, DIRECTORY_SEP, |
| @@ -943,13 +916,10 @@ load_pdump (int argc, char **argv) | |||
| 943 | if (result != PDUMPER_LOAD_FILE_NOT_FOUND) | 916 | if (result != PDUMPER_LOAD_FILE_NOT_FOUND) |
| 944 | fatal ("could not load dump file \"%s\": %s", | 917 | fatal ("could not load dump file \"%s\": %s", |
| 945 | dump_file, dump_error_to_string (result)); | 918 | dump_file, dump_error_to_string (result)); |
| 946 | dump_file = NULL; | ||
| 947 | } | 919 | } |
| 948 | 920 | ||
| 949 | out: | 921 | out: |
| 950 | free (exename); | 922 | xfree (dump_file); |
| 951 | free (real_exename); | ||
| 952 | return result; | ||
| 953 | } | 923 | } |
| 954 | #endif /* HAVE_PDUMPER */ | 924 | #endif /* HAVE_PDUMPER */ |
| 955 | 925 | ||
diff --git a/src/fileio.c b/src/fileio.c index 968a55e5956..cbc0c89cf3e 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -150,7 +150,7 @@ check_existing (const char *filename) | |||
| 150 | 150 | ||
| 151 | /* Return true if file FILENAME exists and can be executed. */ | 151 | /* Return true if file FILENAME exists and can be executed. */ |
| 152 | 152 | ||
| 153 | static bool | 153 | bool |
| 154 | check_executable (char *filename) | 154 | check_executable (char *filename) |
| 155 | { | 155 | { |
| 156 | return faccessat (AT_FDCWD, filename, X_OK, AT_EACCESS) == 0; | 156 | return faccessat (AT_FDCWD, filename, X_OK, AT_EACCESS) == 0; |
diff --git a/src/lisp.h b/src/lisp.h index a7b19ab576e..024e5edb26e 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -4298,6 +4298,7 @@ extern void syms_of_marker (void); | |||
| 4298 | 4298 | ||
| 4299 | /* Defined in fileio.c. */ | 4299 | /* Defined in fileio.c. */ |
| 4300 | 4300 | ||
| 4301 | extern bool check_executable (char *); | ||
| 4301 | extern char *splice_dir_file (char *, char const *, char const *); | 4302 | extern char *splice_dir_file (char *, char const *, char const *); |
| 4302 | extern bool file_name_absolute_p (const char *); | 4303 | extern bool file_name_absolute_p (const char *); |
| 4303 | extern char const *get_homedir (void); | 4304 | extern char const *get_homedir (void); |
diff --git a/src/pdumper.c b/src/pdumper.c index 98090238b1a..2e382145be2 100644 --- a/src/pdumper.c +++ b/src/pdumper.c | |||
| @@ -5303,7 +5303,7 @@ enum dump_section | |||
| 5303 | 5303 | ||
| 5304 | N.B. We run very early in initialization, so we can't use lisp, | 5304 | N.B. We run very early in initialization, so we can't use lisp, |
| 5305 | unwinding, xmalloc, and so on. */ | 5305 | unwinding, xmalloc, and so on. */ |
| 5306 | enum pdumper_load_result | 5306 | int |
| 5307 | pdumper_load (const char *dump_filename) | 5307 | pdumper_load (const char *dump_filename) |
| 5308 | { | 5308 | { |
| 5309 | intptr_t dump_size; | 5309 | intptr_t dump_size; |
| @@ -5328,10 +5328,15 @@ pdumper_load (const char *dump_filename) | |||
| 5328 | /* We can load only one dump. */ | 5328 | /* We can load only one dump. */ |
| 5329 | eassert (!dump_loaded_p ()); | 5329 | eassert (!dump_loaded_p ()); |
| 5330 | 5330 | ||
| 5331 | enum pdumper_load_result err = PDUMPER_LOAD_FILE_NOT_FOUND; | 5331 | int err; |
| 5332 | int dump_fd = emacs_open (dump_filename, O_RDONLY, 0); | 5332 | int dump_fd = emacs_open (dump_filename, O_RDONLY, 0); |
| 5333 | if (dump_fd < 0) | 5333 | if (dump_fd < 0) |
| 5334 | goto out; | 5334 | { |
| 5335 | err = (errno == ENOENT || errno == ENOTDIR | ||
| 5336 | ? PDUMPER_LOAD_FILE_NOT_FOUND | ||
| 5337 | : PDUMPER_LOAD_ERROR + errno); | ||
| 5338 | goto out; | ||
| 5339 | } | ||
| 5335 | 5340 | ||
| 5336 | err = PDUMPER_LOAD_FILE_NOT_FOUND; | 5341 | err = PDUMPER_LOAD_FILE_NOT_FOUND; |
| 5337 | if (fstat (dump_fd, &stat) < 0) | 5342 | if (fstat (dump_fd, &stat) < 0) |
diff --git a/src/pdumper.h b/src/pdumper.h index 83c094f3caa..31b0d53b073 100644 --- a/src/pdumper.h +++ b/src/pdumper.h | |||
| @@ -124,10 +124,10 @@ enum pdumper_load_result | |||
| 124 | PDUMPER_LOAD_FAILED_DUMP, | 124 | PDUMPER_LOAD_FAILED_DUMP, |
| 125 | PDUMPER_LOAD_OOM, | 125 | PDUMPER_LOAD_OOM, |
| 126 | PDUMPER_LOAD_VERSION_MISMATCH, | 126 | PDUMPER_LOAD_VERSION_MISMATCH, |
| 127 | PDUMPER_LOAD_ERROR, | 127 | PDUMPER_LOAD_ERROR /* Must be last, as errno may be added. */ |
| 128 | }; | 128 | }; |
| 129 | 129 | ||
| 130 | enum pdumper_load_result pdumper_load (const char *dump_filename); | 130 | int pdumper_load (const char *dump_filename); |
| 131 | 131 | ||
| 132 | struct pdumper_loaded_dump | 132 | struct pdumper_loaded_dump |
| 133 | { | 133 | { |