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 }