aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src
diff options
context:
space:
mode:
authorPaul Eggert2019-04-14 16:31:24 -0700
committerPaul Eggert2019-04-14 17:06:09 -0700
commit5c2f94a182a1154766154040eb5b4b39275fd3b6 (patch)
tree04ae030b12f1e993173fe33b34ea1975ec9340c7 /lib-src
parent661f44946d2bba21d16d718cf86372345c929a39 (diff)
downloademacs-5c2f94a182a1154766154040eb5b4b39275fd3b6.tar.gz
emacs-5c2f94a182a1154766154040eb5b4b39275fd3b6.zip
Replace executable’s fingerprint in place
* admin/merge-gnulib (GNULIB_MODULES): Add memmem-simple. (AVOIDED_MODULES): Add memchr. * configure.ac (HAVE_PDUMPER): AC_SUBST it, too, for use in makefiles. * lib/Makefile.in (libgnu_a_OBJECTS): Add fingerprint.o. * lib/fingerprint.c: New file. * lib/memmem.c, lib/str-two-way.h, m4/memmem.m4: New files, copied from Gnulib. * lib/fingerprint.h: Rename from src/fingerprint.h. * lib-src/make-fingerprint.c: Include limits.h, sys/stat.h, fingerprint.h, intprops.h, min-max.h. (SSIZE_MAX): New macro, if not already defined. (main): Without -r, Replace the fingerprint in the input file instead of generating a fingerprint.c. * lib/Makefile.in (libgnu_a_OBJECTS): Add fingerprint.o. * lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate. * src/Makefile.in (HAVE_PDUMPER, MAKE_PDUMPER_FINGERPRINT): New macros. (temacs$(EXEEXT)): Use them to replace the fingerprint instead of precalculating it. (mostlyclean, ctagsfiles1): Do not worry about fingerprint.c.
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/make-fingerprint.c119
1 files changed, 88 insertions, 31 deletions
diff --git a/lib-src/make-fingerprint.c b/lib-src/make-fingerprint.c
index 35bb8b98a00..dc21fc2aa9a 100644
--- a/lib-src/make-fingerprint.c
+++ b/lib-src/make-fingerprint.c
@@ -25,14 +25,25 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
25 25
26#include <config.h> 26#include <config.h>
27 27
28#include <limits.h>
28#include <stdarg.h> 29#include <stdarg.h>
29#include <stdint.h> 30#include <stdint.h>
30#include <stdio.h> 31#include <stdio.h>
31#include <stdlib.h> 32#include <stdlib.h>
32#include <string.h> 33#include <string.h>
34#include <sys/stat.h>
35
33#include <sysstdio.h> 36#include <sysstdio.h>
34#include <sha256.h> 37
38#include <fingerprint.h>
35#include <getopt.h> 39#include <getopt.h>
40#include <intprops.h>
41#include <min-max.h>
42#include <sha256.h>
43
44#ifndef SSIZE_MAX
45# define SSIZE_MAX TYPE_MAXIMUM (ssize_t)
46#endif
36 47
37#ifdef WINDOWSNT 48#ifdef WINDOWSNT
38/* Defined to be sys_fopen in ms-w32.h, but only #ifdef emacs, so this 49/* Defined to be sys_fopen in ms-w32.h, but only #ifdef emacs, so this
@@ -54,41 +65,62 @@ main (int argc, char **argv)
54 raw = true; 65 raw = true;
55 break; 66 break;
56 case 'h': 67 case 'h':
57 printf ("make-fingerprint [-r] FILES...: compute a hash\n"); 68 printf ("make-fingerprint [-r] FILE: replace or compute a hash\n");
58 return 0; 69 return EXIT_SUCCESS;
59 default: 70 default:
60 return 1; 71 return EXIT_FAILURE;
61 } 72 }
62 } 73 }
63 74
64 struct sha256_ctx ctx; 75 struct sha256_ctx ctx;
65 sha256_init_ctx (&ctx); 76 sha256_init_ctx (&ctx);
66 77
67 for (int i = optind; i < argc; ++i) 78 if (argc - optind != 1)
68 { 79 {
69 FILE *f = fopen (argv[i], "r" FOPEN_BINARY); 80 fprintf (stderr, "%s: missing or extra file operand\n", argv[0]);
70 if (!f) 81 return EXIT_FAILURE;
71 { 82 }
72 fprintf (stderr, "%s: Error: could not open %s\n",
73 argv[0], argv[i]);
74 return 1;
75 }
76 83
77 char buf[128*1024]; 84 FILE *f = fopen (argv[1], raw ? "r" FOPEN_BINARY : "r+" FOPEN_BINARY);
78 do 85 struct stat st;
79 { 86 if (!f || fstat (fileno (f), &st) != 0)
80 size_t chunksz = fread (buf, 1, sizeof (buf), f); 87 {
81 if (ferror (f)) 88 perror (argv[1]);
82 { 89 return EXIT_FAILURE;
83 fprintf (stderr, "%s: Error: could not read %s\n",
84 argv[0], argv[i]);
85 return 1;
86 }
87 sha256_process_bytes (buf, chunksz, &ctx);
88 } while (!feof (f));
89 fclose (f);
90 } 90 }
91 91
92 if (!S_ISREG (st.st_mode))
93 {
94 fprintf (stderr, "%s: Error: %s is not a regular file\n",
95 argv[0], argv[1]);
96 return EXIT_FAILURE;
97 }
98
99 ptrdiff_t maxlen = min (min (TYPE_MAXIMUM (off_t), PTRDIFF_MAX),
100 min (SIZE_MAX, SSIZE_MAX));
101 if (maxlen <= st.st_size)
102 {
103 fprintf (stderr, "%s: %s: file too big\n", argv[0], argv[1]);
104 return EXIT_FAILURE;
105 }
106
107 char *buf = malloc (st.st_size + 1);
108 if (!buf)
109 {
110 perror ("malloc");
111 return EXIT_FAILURE;
112 }
113
114 size_t chunksz = fread (buf, 1, st.st_size + 1, f);
115 if (ferror (f) || chunksz != st.st_size)
116 {
117 fprintf (stderr, "%s: Error: could not read %s\n",
118 argv[0], argv[1]);
119 return EXIT_FAILURE;
120 }
121
122 sha256_process_bytes (buf, chunksz, &ctx);
123
92 unsigned char digest[32]; 124 unsigned char digest[32];
93 sha256_finish_ctx (&ctx, digest); 125 sha256_finish_ctx (&ctx, digest);
94 126
@@ -99,12 +131,37 @@ main (int argc, char **argv)
99 } 131 }
100 else 132 else
101 { 133 {
102 puts ("#include \"fingerprint.h\"\n" 134 char *finger = memmem (buf, chunksz, fingerprint, sizeof fingerprint);
103 "unsigned char const fingerprint[] =\n" 135 if (!finger)
104 "{"); 136 {
105 for (int i = 0; i < 32; ++i) 137 fprintf (stderr, "%s: %s: missing fingerprint\n", argv[0], argv[1]);
106 printf ("\t0x%02X,\n", digest[i]); 138 return EXIT_FAILURE;
107 puts ("};"); 139 }
140 else if (memmem (finger + 1, buf + chunksz - (finger + 1),
141 fingerprint, sizeof fingerprint))
142 {
143 fprintf (stderr, "%s: %s: two occurrences of fingerprint\n",
144 argv[0], argv[1]);
145 return EXIT_FAILURE;
146 }
147
148 if (fseeko (f, finger - buf, SEEK_SET) != 0)
149 {
150 perror (argv[1]);
151 return EXIT_FAILURE;
152 }
153
154 if (fwrite (digest, 1, sizeof digest, f) != sizeof digest)
155 {
156 perror (argv[1]);
157 return EXIT_FAILURE;
158 }
159 }
160
161 if (fclose (f) != 0)
162 {
163 perror (argv[1]);
164 return EXIT_FAILURE;
108 } 165 }
109 166
110 return EXIT_SUCCESS; 167 return EXIT_SUCCESS;