Mercurial > ~dholland > hg > ag > index.cgi
comparison checksum/checksum.c @ 0:13d2b8934445
Import AnaGram (near-)release tree into Mercurial.
author | David A. Holland |
---|---|
date | Sat, 22 Dec 2007 17:52:45 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:13d2b8934445 |
---|---|
1 /* | |
2 * AnaGram, A System for Syntax Directed Programming | |
3 * Copyright 2006 David A. Holland. All Rights Reserved. | |
4 * See the file COPYING for license and usage terms. | |
5 */ | |
6 | |
7 /* | |
8 * checksum - compute checksums of key files. | |
9 * usage: checksum outputprefix symbolic-name filename | |
10 * | |
11 * Outputs to two files, one with the checksum info and one | |
12 * the control file for insertsums. | |
13 * | |
14 * In each binary searches for a sums patch area, which is a | |
15 * region of size TARGETSIZE beginning with the string TARGETLABEL. | |
16 * This region is excluded from the sum and reported to insertsums. | |
17 * | |
18 * XXX the definitions of TARGETSIZE and TARGETLABEL should be shared | |
19 * with the ag code. | |
20 * | |
21 * This module is new code as of June 2006 and should be much more | |
22 * portable than the old stuff. | |
23 */ | |
24 | |
25 #include <sys/types.h> | |
26 #include <sys/stat.h> | |
27 #include <stdio.h> | |
28 #include <stdarg.h> | |
29 #include <stdint.h> | |
30 #include <stdlib.h> | |
31 #include <string.h> | |
32 #include <assert.h> | |
33 #include <unistd.h> | |
34 #include <fcntl.h> | |
35 #include <getopt.h> | |
36 #include <errno.h> | |
37 | |
38 #include "bits.h" | |
39 | |
40 #ifndef O_BINARY | |
41 #define O_BINARY 0 | |
42 #define O_TEXT 0 | |
43 #endif | |
44 | |
45 #define TARGETSIZE 512 | |
46 #define TARGETLABEL "Checksum data:\n" | |
47 | |
48 static FILE *datfile, *ctlfile; | |
49 | |
50 #if 0 | |
51 /* The file extensions depend on the platform we're building for. */ | |
52 typedef enum { | |
53 EXEEXT, | |
54 SHLIBEXT, | |
55 HLPEXT, | |
56 } whichext; | |
57 | |
58 /* Information about files we checksum. */ | |
59 struct fileinfo { | |
60 const char *basename; | |
61 whichext ext; | |
62 int istarget; | |
63 const char *tag; | |
64 }; | |
65 | |
66 /* These are the files. */ | |
67 static const struct fileinfo files[] = { | |
68 { "ag", EXEEXT, 0, "ag" }, | |
69 { "agcl", EXEEXT, 0, "agcl" }, | |
70 { "ag1", SHLIBEXT, 1, "ag1" }, | |
71 { "AnaGram", HLPEXT, 0, "hlp" }, | |
72 }; | |
73 static const unsigned numfiles = sizeof(files) / sizeof(files[0]); | |
74 #endif | |
75 | |
76 /* The name of this program, from argv[0]. */ | |
77 static const char *me; | |
78 | |
79 //////////////////////////////////////////////////////////// | |
80 | |
81 static off_t filelength(int fd) { | |
82 struct stat statbuf; | |
83 fstat(fd, &statbuf); | |
84 return statbuf.st_size; | |
85 } | |
86 | |
87 static void setme(const char *av0) { | |
88 me = strrchr(av0, '/'); | |
89 if (me) { | |
90 me++; | |
91 } | |
92 else { | |
93 me = av0; | |
94 } | |
95 } | |
96 | |
97 static void die(const char *fmt, ...) { | |
98 va_list ap; | |
99 fprintf(stderr, "%s: ", me); | |
100 va_start(ap, fmt); | |
101 vfprintf(stderr, fmt, ap); | |
102 fputc('\n', stderr); | |
103 exit(EXIT_FAILURE); | |
104 } | |
105 | |
106 //////////////////////////////////////////////////////////// | |
107 | |
108 static void openoutput(const char *prefix) { | |
109 char buf[128]; | |
110 | |
111 snprintf(buf, sizeof(buf), "%s.dat", prefix); | |
112 datfile = fopen(buf, "at"); | |
113 if (!datfile) { | |
114 die("%s: fopen failed", buf); | |
115 } | |
116 | |
117 snprintf(buf, sizeof(buf), "%s.ctl", prefix); | |
118 ctlfile = fopen(buf, "at"); | |
119 if (!ctlfile) { | |
120 die("%s: fopen failed", buf); | |
121 } | |
122 } | |
123 | |
124 static void closeoutput(void) { | |
125 fclose(datfile); | |
126 fclose(ctlfile); | |
127 } | |
128 | |
129 //////////////////////////////////////////////////////////// | |
130 | |
131 /* | |
132 * Note: allocates a zero byte after the end of the file | |
133 * (the checksum code demands this) | |
134 */ | |
135 static char *loadfile(const char *path, size_t *len_ret) { | |
136 int fd; | |
137 char *buf; | |
138 off_t length; | |
139 ssize_t nread; | |
140 | |
141 fd = open(path, O_BINARY|O_RDONLY); | |
142 if (fd < 0) { | |
143 die("%s: %s", path, strerror(errno)); | |
144 } | |
145 | |
146 length = filelength(fd); | |
147 if (length > 1000000000L) { | |
148 // paranoia is good | |
149 die("Unreasonably large file"); | |
150 } | |
151 | |
152 buf = malloc(length+1); | |
153 if (!buf) { | |
154 die("malloc failed"); | |
155 } | |
156 | |
157 nread = read(fd, buf, length); | |
158 if (nread < 0) { | |
159 die("%s: read: %s", path, strerror(errno)); | |
160 } | |
161 if (nread != length) { | |
162 die("%s: read: short count", path); | |
163 } | |
164 | |
165 close(fd); | |
166 | |
167 buf[length] = 0; | |
168 | |
169 *len_ret = length; | |
170 return buf; | |
171 } | |
172 | |
173 static void unloadfile(char *buf) { | |
174 free(buf); | |
175 } | |
176 | |
177 //////////////////////////////////////////////////////////// | |
178 | |
179 static int search(const char *data, size_t len, size_t *pos_ret) { | |
180 static const char tag[] = TARGETLABEL; | |
181 static unsigned expected = 0; | |
182 static size_t start = 0; | |
183 | |
184 size_t pos = 0; | |
185 | |
186 for (pos=0; pos<len; pos++) { | |
187 int ch = data[pos]; | |
188 | |
189 if (ch == tag[expected]) { | |
190 if (expected==0) { | |
191 start = pos; | |
192 } | |
193 expected++; | |
194 if (tag[expected]==0) { | |
195 /* found */ | |
196 *pos_ret = start; | |
197 return 1; | |
198 } | |
199 } | |
200 else { | |
201 expected = 0; | |
202 } | |
203 } | |
204 | |
205 return 0; | |
206 } | |
207 | |
208 //////////////////////////////////////////////////////////// | |
209 | |
210 static void sumfile(const char *sym, const char *path) { | |
211 char *data; | |
212 uint32_t sum; | |
213 size_t length, patchpos; | |
214 int haspatcharea; | |
215 | |
216 data = loadfile(path, &length); | |
217 haspatcharea = search(data, length, &patchpos); | |
218 sum = dosum(data, length, haspatcharea ? patchpos : 0, TARGETSIZE); | |
219 unloadfile(data); | |
220 | |
221 if (haspatcharea && patchpos==0) { | |
222 die("%s: patch area is at file offset 0", path); | |
223 } | |
224 | |
225 fprintf(datfile, "%s=%lu,%lu", | |
226 sym, (unsigned long) length, (unsigned long) sum); | |
227 if (haspatcharea) { | |
228 fprintf(datfile, "@%lu", (unsigned long) patchpos); | |
229 fprintf(ctlfile, "%s %lu\n", path, (unsigned long) patchpos); | |
230 } | |
231 else { | |
232 fprintf(ctlfile, "# %s no-patch-area\n", path); | |
233 } | |
234 fprintf(datfile, "\n"); | |
235 } | |
236 | |
237 //////////////////////////////////////////////////////////// | |
238 | |
239 static void usage(void) { | |
240 die("Usage: %s outputprefix symbolic-name pathname", me); | |
241 } | |
242 | |
243 int main(int argc, char *argv[]) { | |
244 const char *out, *sym, *path; | |
245 | |
246 setme(argv[0]); | |
247 if (argc != 4) { | |
248 usage(); | |
249 } | |
250 | |
251 out = argv[1]; | |
252 sym = argv[2]; | |
253 path = argv[3]; | |
254 | |
255 openoutput(out); | |
256 sumfile(sym, path); | |
257 closeoutput(); | |
258 | |
259 return EXIT_SUCCESS; | |
260 } |