Mercurial > ~dholland > hg > ag > index.cgi
comparison anagram/agcore/checksum.cpp @ 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 1993-1999 Parsifal Software. All Rights Reserved. | |
4 * Copyright 2006 David A. Holland. All Rights Reserved. | |
5 * See the file COPYING for license and usage terms. | |
6 * | |
7 * checksum.cpp - self-checksum module | |
8 */ | |
9 | |
10 #include <sys/types.h> | |
11 #include <sys/stat.h> | |
12 #include <fcntl.h> | |
13 #include <limits.h> | |
14 #include <stdio.h> | |
15 #include <stdlib.h> | |
16 #include <string.h> | |
17 #include "port.h" | |
18 | |
19 #ifdef AG_ON_WINDOWS | |
20 #include <windows.h> | |
21 #endif | |
22 | |
23 #include "agstring.h" | |
24 #include "assert.h" | |
25 #include "checksum.h" | |
26 #include "file.h" | |
27 | |
28 //#define INCLUDE_LOGGING | |
29 #include "log.h" | |
30 | |
31 | |
32 /* | |
33 * Fletcher's check-sum routines for AnaGram | |
34 * | |
35 * Freely adapted from routines published in Dr. Dobbs Journal | |
36 * May 1992, p. 64 | |
37 */ | |
38 | |
39 #define BLOCK_SIZE 0X4000U | |
40 | |
41 static AgString basedir; | |
42 | |
43 static void checkSum(int fh, int offset, u_long *res_sum, u_long *res_len) { | |
44 LOGSECTION("checkSum"); | |
45 char *buf; | |
46 unsigned short k1, k2; | |
47 | |
48 *res_sum = 0; | |
49 *res_len = 0; | |
50 | |
51 //LOGV(fh); | |
52 | |
53 if (fh < 0) { | |
54 return; | |
55 } | |
56 lseek(fh, 0, 2); | |
57 int length = tell(fh); | |
58 *res_len = length; | |
59 //LOGV(length); | |
60 //buf = ALLOCATE(BLOCK_SIZE + 1, char); | |
61 buf = new char[BLOCK_SIZE + 1]; | |
62 | |
63 k1 = (unsigned short) (length >> 16); | |
64 k2 = (unsigned short) length; | |
65 | |
66 if (offset) { | |
67 lseek(fh, offset+512, 0); | |
68 length -= offset+512; | |
69 //LOGV(length); | |
70 } | |
71 else { | |
72 lseek(fh,0,0); | |
73 } | |
74 | |
75 if (k1 == 0) k1++; | |
76 if (k2 == 0) k2++; | |
77 | |
78 while (length > 0) { | |
79 unsigned n; | |
80 unsigned ni; | |
81 unsigned i; | |
82 unsigned short *b; | |
83 | |
84 n = BLOCK_SIZE; | |
85 if ((long) n > length) { | |
86 n = (unsigned short) length; | |
87 } | |
88 n = read(fh, buf, n); | |
89 if (n == 0) { | |
90 break; | |
91 } | |
92 ni = (n+1)/2; | |
93 i = 0; | |
94 b = (unsigned short *) buf; | |
95 buf[n] = 0; | |
96 while (i< ni) { | |
97 k1 += b[i]; | |
98 if (k1 < b[i]) { | |
99 k1++; | |
100 } | |
101 k2 += k1; | |
102 if (k2 < k1) { | |
103 k2++; | |
104 } | |
105 i++; | |
106 } | |
107 length -= n; | |
108 if (length <= 0 && offset!=0) { | |
109 //LOGV(k1) LCV(k2); | |
110 length = offset; | |
111 offset = 0; | |
112 lseek(fh, 0, 0); | |
113 } | |
114 } | |
115 k1 ^= (unsigned short) -1; | |
116 k2 ^= (unsigned short) -1; | |
117 *res_sum = 65535L*k2 + k1; | |
118 | |
119 LOGV(*res_sum); | |
120 //DEALLOCATE(buf); | |
121 delete [] buf; | |
122 } | |
123 | |
124 #ifdef AG_ON_WINDOWS | |
125 static int open_binary(summable what) { | |
126 char buf[_MAX_PATH]; | |
127 HMODULE module; | |
128 | |
129 switch (what) { | |
130 case SUM_AG1: module = GetModuleHandle("ag1"); break; | |
131 case SUM_AG: module = 0; break; | |
132 case SUM_AGCL: module = 0; break; | |
133 } | |
134 | |
135 GetModuleFileName(module, buf, sizeof(buf)-2); | |
136 | |
137 if (what != SUM_AG1) { | |
138 size_t len = strlen(buf); | |
139 if (len >= 6 && !stricmp(buf+len-6, "ag.exe") && what == SUM_AGCL) { | |
140 strcpy(buf+len-6, "agcl.exe"); | |
141 } | |
142 else if (len >= 8 && !stricmp(buf+len-8, "agcl.exe") && what == SUM_AG) { | |
143 strcpy(buf+len-8, "ag.exe"); | |
144 } | |
145 } | |
146 | |
147 return open_shared_denywrite(buf, O_BINARY|O_RDONLY); | |
148 } | |
149 #endif | |
150 | |
151 #ifdef AG_ON_UNIX | |
152 static int open_binary(summable what) { | |
153 char buf[PATH_MAX]; | |
154 const char *name = NULL; | |
155 switch (what) { | |
156 case SUM_AG1: name = "ag1.so"; break; | |
157 case SUM_AG: name = "ag"; break; | |
158 case SUM_AGCL: name = "agcl"; break; | |
159 } | |
160 | |
161 snprintf(buf, sizeof(buf), "%s/%s", basedir.pointer(), name); | |
162 return open(buf, O_RDONLY); | |
163 } | |
164 #endif | |
165 | |
166 static int open_summable(summable what) { | |
167 switch (what) { | |
168 case SUM_AG1: | |
169 case SUM_AG: | |
170 case SUM_AGCL: | |
171 return open_binary(what); | |
172 } | |
173 return -1; | |
174 } | |
175 | |
176 static void close_summable(summable what, int fd) { | |
177 switch (what) { | |
178 case SUM_AG1: | |
179 case SUM_AG: | |
180 case SUM_AGCL: | |
181 close(fd); | |
182 break; | |
183 } | |
184 } | |
185 | |
186 void observeSum(sumentry *s) { | |
187 LOGSECTION("observeSum"); | |
188 | |
189 int fd = open_summable(s->what); | |
190 if (fd >= 0) { | |
191 LOGV(fd); | |
192 checkSum(fd, s->offset, &s->observed.sum, &s->observed.length); | |
193 close_summable(s->what, fd); | |
194 } | |
195 else { | |
196 s->observed.sum = 0; | |
197 s->observed.length = 0; | |
198 } | |
199 } | |
200 | |
201 void sum_remember_argv0(const char *argv0) { | |
202 LOGSECTION("sum_remember_argv0"); | |
203 LOGV(argv0); | |
204 AgString av0(argv0); | |
205 | |
206 #ifdef AG_ON_WINDOWS | |
207 basedir = av0.lastCut("\\/:").leftX(); | |
208 LOGV(basedir); | |
209 #endif | |
210 | |
211 #ifdef AG_ON_UNIX | |
212 /* | |
213 * Not as simple on Unix - we get whatever the parent process sends | |
214 * us, which is typically what the user typed into the shell to | |
215 * invoke the program. That is, it might be an absolute path, a | |
216 * relative path, or no path at all, and in the latter case we need | |
217 * to search $PATH. Blah. | |
218 * | |
219 * Note that since both argv[0] and $PATH are under the user's | |
220 * control, if the user is adversarial we can't count on finding the | |
221 * same file that we're actually executing from. Fortunately we | |
222 * don't care about that now AG is open source. | |
223 */ | |
224 | |
225 if (argv0[0]=='/') { | |
226 /* absolute path */ | |
227 basedir = av0.lastCut("\\/:").leftX(); | |
228 LOGV(basedir); | |
229 } | |
230 else if (strrchr(argv0, '/')!=NULL) { | |
231 /* relative path - good enough; we don't chdir before summing is done */ | |
232 basedir = av0.lastCut("\\/:").leftX(); | |
233 LOGV(basedir); | |
234 } | |
235 else { | |
236 /* nothing */ | |
237 struct stat sb; | |
238 const char *p = getenv("PATH"); | |
239 LOGV(p); | |
240 if (p) { | |
241 AgString path(p); // copy it | |
242 for (char *s = strtok(path.pointer(), ":"); s; s = strtok(NULL, ":")) { | |
243 char tmp[PATH_MAX]; | |
244 snprintf(tmp, sizeof(tmp), "%s/%s", s, argv0); | |
245 LOGV(tmp); | |
246 if (stat(tmp, &sb)==0) { | |
247 basedir = s; // copy it | |
248 LOGV(basedir); | |
249 return; | |
250 } | |
251 } | |
252 } | |
253 | |
254 /* oh well - let's make a guess */ | |
255 basedir = "/usr/local/lib/anagram"; | |
256 LOGV(basedir); | |
257 } | |
258 #endif | |
259 } |