Mercurial > ~dholland > hg > ag > index.cgi
comparison insertsums/insertsums.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 * insertsums - patch checksum data block into binary | |
9 * usage: insertsums sums.dat sums.ctl | |
10 * | |
11 * The patch area is a region of size TARGETSIZE that the | |
12 * checksum program finds for us. We check to make sure it | |
13 * contains the right magic string before patching over it, | |
14 * just in case. | |
15 * | |
16 * Everything is XOR'd with PADBYTE as something of a paranoia | |
17 * measure against viruses. | |
18 * | |
19 * XXX the definitions of TARGETSIZE and TARGETLABEL should | |
20 * be shared with the AG code. PADBYTE too. | |
21 * | |
22 * This module is new code as of June 2006 and should be much more | |
23 * portable than the old stuff. | |
24 */ | |
25 | |
26 #include <assert.h> | |
27 #include <ctype.h> | |
28 #include <errno.h> | |
29 #include <fcntl.h> | |
30 #include <stdarg.h> | |
31 #include <stdio.h> | |
32 #include <stdlib.h> | |
33 #include <string.h> | |
34 #include <unistd.h> | |
35 | |
36 #ifndef O_BINARY | |
37 #define O_BINARY 0 | |
38 #define O_TEXT 0 | |
39 #endif | |
40 | |
41 #define TARGETSIZE 512 | |
42 #define TARGETLABEL "Checksum data:\n" | |
43 #define PADBYTE 0xae | |
44 | |
45 | |
46 static char info[TARGETSIZE]; | |
47 static const char *me; | |
48 | |
49 static const char label[] = TARGETLABEL; | |
50 | |
51 //////////////////////////////////////////////////////////// | |
52 | |
53 static void setme(const char *av0) { | |
54 me = strrchr(av0, '/'); | |
55 if (me) { | |
56 me++; | |
57 } | |
58 else { | |
59 me = av0; | |
60 } | |
61 } | |
62 | |
63 static void die(const char *fmt, ...) { | |
64 va_list ap; | |
65 fprintf(stderr, "%s: ", me); | |
66 va_start(ap, fmt); | |
67 vfprintf(stderr, fmt, ap); | |
68 fputc('\n', stderr); | |
69 exit(EXIT_FAILURE); | |
70 } | |
71 | |
72 //////////////////////////////////////////////////////////// | |
73 | |
74 static int isnumber(const char *s) { | |
75 size_t i; | |
76 for (i=0; s[i]; i++) { | |
77 if (!isdigit((unsigned char) s[i])) { | |
78 return 0; | |
79 } | |
80 } | |
81 // protect against possible overflow, just in case | |
82 return i<10; | |
83 } | |
84 | |
85 //////////////////////////////////////////////////////////// | |
86 | |
87 static void putsums(const char *file, long offset) { | |
88 char buf[TARGETSIZE]; | |
89 ssize_t len; | |
90 int fd; | |
91 | |
92 fd = open(file, O_RDWR); | |
93 if (fd<0) { | |
94 die("%s: %s", file, strerror(errno)); | |
95 } | |
96 if (lseek(fd, offset, SEEK_SET)<0) { | |
97 die("%s: lseek: %s", file, strerror(errno)); | |
98 } | |
99 len = read(fd, buf, sizeof(buf)); | |
100 if (len < 0) { | |
101 die("%s: read: %s", file, strerror(errno)); | |
102 } | |
103 if ((size_t)len != TARGETSIZE) { | |
104 die("%s: read: short count (past EOF?)", file); | |
105 } | |
106 | |
107 if (memcmp(buf, label, strlen(label))!=0) { | |
108 die("%s: patch area label is missing", file); | |
109 } | |
110 | |
111 if (lseek(fd, offset, SEEK_SET)<0) { | |
112 die("%s: lseek: %s", file, strerror(errno)); | |
113 } | |
114 len = write(fd, info, sizeof(info)); | |
115 if (len < 0) { | |
116 die("%s: write: %s", file, strerror(errno)); | |
117 } | |
118 if ((size_t)len != TARGETSIZE) { | |
119 die("%s: write: short count", file); | |
120 } | |
121 if (close(fd)<0) { | |
122 die("%s: close: %s", file, strerror(errno)); | |
123 } | |
124 //printf("%s: patched %s\n", me, file); | |
125 } | |
126 | |
127 static void storesums(const char *ctlfile) { | |
128 char buf[128]; | |
129 FILE *f; | |
130 int lineno = 0; | |
131 | |
132 f = fopen(ctlfile, "rt"); | |
133 if (!f) { | |
134 die("%s: fopen failed", ctlfile); | |
135 } | |
136 | |
137 while (fgets(buf, sizeof(buf), f)) { | |
138 /* format is: pathname offset */ | |
139 char *words[3], *s; | |
140 int nwords = 0; | |
141 lineno++; | |
142 if (*buf=='#') { | |
143 continue; | |
144 } | |
145 for (s = strtok(buf, " \t\r\n"); s; s = strtok(NULL, " \t\r\n")) { | |
146 if (nwords >= 3) { | |
147 break; | |
148 } | |
149 words[nwords++] = s; | |
150 } | |
151 if (nwords != 2 || !isnumber(words[1])) { | |
152 die("%s: Invalid line %d", ctlfile, lineno); | |
153 } | |
154 putsums(words[0], atol(words[1])); | |
155 } | |
156 if (ferror(f)) { | |
157 die("%s: read error", ctlfile); | |
158 } | |
159 fclose(f); | |
160 } | |
161 | |
162 //////////////////////////////////////////////////////////// | |
163 | |
164 static void hidesums(void) { | |
165 size_t i; | |
166 for (i=strlen(label); i<sizeof(info); i++) { | |
167 info[i] = (char) (PADBYTE ^ (unsigned char)info[i]); | |
168 } | |
169 } | |
170 | |
171 //////////////////////////////////////////////////////////// | |
172 | |
173 static void loadsums(const char *sumpath) { | |
174 ssize_t readlen; | |
175 size_t loadpos, maxlen, infolen; | |
176 int fd; | |
177 | |
178 assert(strlen(label) < TARGETSIZE); | |
179 strcpy(info, label); | |
180 loadpos = strlen(info); | |
181 maxlen = sizeof(info) - loadpos; | |
182 | |
183 fd = open(sumpath, O_TEXT|O_RDONLY); | |
184 if (fd < 0) { | |
185 die("%s: %s", sumpath, strerror(errno)); | |
186 } | |
187 | |
188 readlen = read(fd, info+loadpos, maxlen); | |
189 if (readlen < 0) { | |
190 die("%s: read: %s", sumpath, strerror(errno)); | |
191 } | |
192 if (readlen == 0) { | |
193 die("%s: read: empty file?", sumpath); | |
194 } | |
195 close(fd); | |
196 | |
197 infolen = loadpos+readlen; | |
198 if (infolen >= sizeof(info)) { | |
199 die("%s: Too much information!", sumpath); /* :-) */ | |
200 } | |
201 | |
202 //printf("%s: %lu bytes prepared\n", me, (unsigned long) infolen); | |
203 | |
204 while (infolen < sizeof(info)) { | |
205 info[infolen++] = 0; | |
206 } | |
207 } | |
208 | |
209 //////////////////////////////////////////////////////////// | |
210 | |
211 static void usage(void) { | |
212 die("Usage: %s sums.dat sums.ctl", me); | |
213 } | |
214 | |
215 int main(int argc, char *argv[]) { | |
216 setme(argv[0]); | |
217 if (argc != 3) { | |
218 usage(); | |
219 } | |
220 | |
221 loadsums(argv[1]); | |
222 hidesums(); | |
223 storesums(argv[2]); | |
224 | |
225 return EXIT_SUCCESS; | |
226 } |