1 | /* Copyright (C) 1988 Tim Shepard All rights reserved. */ |
---|
2 | |
---|
3 | #include "synctree.h" |
---|
4 | #include <string.h> |
---|
5 | #include <stdio.h> |
---|
6 | |
---|
7 | extern char *date_db_name; |
---|
8 | extern rule rules[]; |
---|
9 | extern unsigned int lastrule; |
---|
10 | extern unsigned int rflag; |
---|
11 | |
---|
12 | extern bool nosrcrules; |
---|
13 | extern bool nodstrules; |
---|
14 | |
---|
15 | extern char *src_rule_file; |
---|
16 | extern char *dst_rule_file; |
---|
17 | |
---|
18 | extern int verbosef; |
---|
19 | |
---|
20 | char srcpath; |
---|
21 | char dstpath; |
---|
22 | |
---|
23 | void compute_ifs(); |
---|
24 | |
---|
25 | int findrule(pathname,rtype,ftype,srcpath) |
---|
26 | enum rule_type rtype; |
---|
27 | char *pathname, *srcpath; |
---|
28 | { |
---|
29 | int i; |
---|
30 | char *p; |
---|
31 | |
---|
32 | if (verbosef>2) { |
---|
33 | printf("findrule of |%s| rtype = %d\n", pathname, rtype); |
---|
34 | } |
---|
35 | |
---|
36 | /* First we catch the special file names which we never want to be |
---|
37 | * updated. They are "." and "..". If pathname refers to one of |
---|
38 | * these files, we return rule 0 which should always be a "map *". |
---|
39 | * We also map ".reconcile_dates*" files (date_db_name) to nowhere |
---|
40 | * (by using rule 0). |
---|
41 | */ |
---|
42 | |
---|
43 | if (p = strrchr(pathname,'/')) |
---|
44 | p++; |
---|
45 | else |
---|
46 | p = pathname; |
---|
47 | |
---|
48 | if ((strcmp(p,".") == 0) || (strcmp(p,"..") == 0) || |
---|
49 | (strncmp(p,date_db_name,strlen(date_db_name)) == 0)) |
---|
50 | return |
---|
51 | (rtype == R_MAP)? 0 : |
---|
52 | (rtype == R_ACTION)? 1 : |
---|
53 | panic("findrule: rtype is unexpected rule type for special case"); |
---|
54 | |
---|
55 | /* now search the normal rules */ |
---|
56 | for (i = lastrule ; i >= 0 ; i--) { |
---|
57 | switch (rules[i].type) { |
---|
58 | case R_MAP: |
---|
59 | if ((rtype == R_MAP) && |
---|
60 | hastype(rules[i].u.u_map.file_types,ftype) && |
---|
61 | glob_match(rules[i].u.u_map.globexp,pathname)) |
---|
62 | return i; |
---|
63 | break; |
---|
64 | case R_CHASE: |
---|
65 | if ((rtype == R_CHASE) && |
---|
66 | (ftype == TYPE_L) && |
---|
67 | glob_match(rules[i].u.u_chase.globexp,pathname)) |
---|
68 | return i; |
---|
69 | break; |
---|
70 | case R_ACTION: |
---|
71 | if (verbosef > 2) { |
---|
72 | printf("Checking for a match with rule %d:\n",i); |
---|
73 | printf("\tFile types: 0x%02.2x\t(source type: 0x%02.2x)\n", |
---|
74 | rules[i].u.u_action.file_types, ftype); |
---|
75 | printf("\tAction type: %d\n", |
---|
76 | rules[i].u.u_action.type); |
---|
77 | } |
---|
78 | if ((rtype == R_ACTION) && |
---|
79 | glob_match(rules[i].u.u_action.globexp,pathname)) |
---|
80 | { |
---|
81 | if (verbosef > 2) { |
---|
82 | printf("Rule %d - regexp passed\n", i); |
---|
83 | } |
---|
84 | |
---|
85 | /* |
---|
86 | * A "virtual" file (one that exists only in the target) |
---|
87 | * can only have one of a couple actions performed on it: |
---|
88 | * "delete" and "ignore" |
---|
89 | */ |
---|
90 | if (hastype(ftype,TYPE_V) && |
---|
91 | rules[i].u.u_action.type != ACTION_DELETE && |
---|
92 | rules[i].u.u_action.type != ACTION_IGNORE) |
---|
93 | break; |
---|
94 | |
---|
95 | /* |
---|
96 | * Don't waste time checking for executables if there is |
---|
97 | * already a match... |
---|
98 | */ |
---|
99 | if (hastype(rules[i].u.u_action.file_types,ftype)) { |
---|
100 | if (verbosef>2) { |
---|
101 | printf("findrule %s - matches general mask; rule %d\n", pathname, i); |
---|
102 | } |
---|
103 | return i; |
---|
104 | } |
---|
105 | |
---|
106 | /* |
---|
107 | * We have been unable to establish a match; check if this |
---|
108 | * rule applies to executables and if the file in question |
---|
109 | * is an executable. |
---|
110 | */ |
---|
111 | if (hastype(rules[i].u.u_action.file_types,TYPE_X) && |
---|
112 | !hastype(rules[i].u.u_action.file_types,TYPE_R) && |
---|
113 | (ftype == TYPE_R)) |
---|
114 | { |
---|
115 | /* |
---|
116 | * At this point, we know: |
---|
117 | * 1. The pathname matches the pattern supplied. |
---|
118 | * 2. The pathname should be an executable. |
---|
119 | */ |
---|
120 | |
---|
121 | int fd, nbytes; |
---|
122 | unsigned long magic; |
---|
123 | unsigned short *smagic = |
---|
124 | (unsigned short *)&magic; |
---|
125 | |
---|
126 | #define swabs(a) (((a&0xff00) >> 8) | ((a&0xff) << 8)) |
---|
127 | #define swabl(a) ((a>>24)&0xff | (((a>>16)&0xff)<<8) | \ |
---|
128 | (((a>>8)&0xff)<<16) | ((a&0xff)<<24)) |
---|
129 | |
---|
130 | if ((fd=open(srcpath,0,0)) < 0) |
---|
131 | break; |
---|
132 | nbytes = read(fd,&magic,sizeof(magic)); |
---|
133 | close(fd); |
---|
134 | |
---|
135 | if (nbytes != sizeof(magic)) |
---|
136 | break; |
---|
137 | |
---|
138 | #ifdef ZMAGIC |
---|
139 | #define xxx(a) case(a): case(swabl(a)): |
---|
140 | switch(magic) { |
---|
141 | xxx(ZMAGIC); |
---|
142 | xxx(NMAGIC); |
---|
143 | xxx(OMAGIC); |
---|
144 | #ifdef Z0MAGIC |
---|
145 | xxx(Z0MAGIC); |
---|
146 | #endif |
---|
147 | if (verbosef>2) { |
---|
148 | printf("findrule %s - matches (COFF executable); rule %d\n", pathname, i); |
---|
149 | } |
---|
150 | return i; |
---|
151 | |
---|
152 | default: |
---|
153 | break; /* Not an a.out executable */ |
---|
154 | } |
---|
155 | #undef xxx |
---|
156 | #endif /* ZMAGIC */ |
---|
157 | |
---|
158 | #ifdef F_EXEC |
---|
159 | #define xxx(a) \ |
---|
160 | if (*smagic == (a) || *smagic == (swabs(a))) { \ |
---|
161 | if (verbosef>2) { \ |
---|
162 | printf("findrule %s - matches (COFF executable); rule %d\n", \ |
---|
163 | pathname, i); \ |
---|
164 | } \ |
---|
165 | return i; \ |
---|
166 | } |
---|
167 | |
---|
168 | #ifdef B16MAGIC |
---|
169 | /* Basic-16 */ |
---|
170 | xxx(B16MAGIC); |
---|
171 | xxx(BTVMAGIC); |
---|
172 | #endif |
---|
173 | #ifdef X86MAGIC |
---|
174 | /* x86 */ |
---|
175 | xxx(X86MAGIC); |
---|
176 | xxx(XTVMAGIC); |
---|
177 | #endif |
---|
178 | #ifdef I286SMAGIC |
---|
179 | xxx(I286SMAGIC); |
---|
180 | xxx(I286LMAGIC); |
---|
181 | #endif |
---|
182 | #ifdef N3BMAGIC |
---|
183 | /* n3b */ |
---|
184 | xxx(N3BMAGIC); |
---|
185 | xxx(NTVMAGIC); |
---|
186 | #endif |
---|
187 | #ifdef FBOMAGIC |
---|
188 | /* MAC-32, 3b-5 */ |
---|
189 | xxx(FBOMAGIC); |
---|
190 | xxx(RBOMAGIC); |
---|
191 | xxx(MTVMAGIC); |
---|
192 | #endif |
---|
193 | #ifdef VAXWRMAGIC |
---|
194 | /* VAX 11/780 and VAX 11/750 */ |
---|
195 | xxx(VAXWRMAGIC); |
---|
196 | xxx(VAXROMAGIC); |
---|
197 | #endif |
---|
198 | #ifdef MC68MAGIC |
---|
199 | /* Motorola 68000 */ |
---|
200 | xxx(MC68MAGIC); |
---|
201 | xxx(MC68TVMAGIC); |
---|
202 | xxx(M68MAGIC); |
---|
203 | xxx(M68TVMAGIC); |
---|
204 | #endif |
---|
205 | #ifdef M68NSMAGIC |
---|
206 | /* UniSoft additions for 68000 */ |
---|
207 | xxx(M68NSMAGIC); |
---|
208 | #endif |
---|
209 | #ifdef AMDWRMAGIC |
---|
210 | /* Amdahl 470/580 */ |
---|
211 | xxx(AMDWRMAGIC); |
---|
212 | xxx(AMDROMAGIC); |
---|
213 | #endif |
---|
214 | #ifdef U370WRMAGIC |
---|
215 | /* IBM 370 */ |
---|
216 | xxx(U370WRMAGIC); |
---|
217 | xxx(U370ROMAGIC); |
---|
218 | #endif |
---|
219 | #ifdef U800WRMAGIC |
---|
220 | /* IBM RT */ |
---|
221 | xxx(U800WRMAGIC); |
---|
222 | xxx(U800ROMAGIC); |
---|
223 | xxx(U800TOCMAGIC); |
---|
224 | #endif |
---|
225 | #ifdef U802WRMAGIC |
---|
226 | /* IBM R2 */ |
---|
227 | xxx(U802WRMAGIC); |
---|
228 | xxx(U802ROMAGIC); |
---|
229 | xxx(U802TOCMAGIC); |
---|
230 | #endif |
---|
231 | #ifdef MIPSEBMAGIC |
---|
232 | /* DEC Mips */ |
---|
233 | xxx(MIPSEBMAGIC); |
---|
234 | xxx(MIPSELMAGIC); |
---|
235 | xxx(SMIPSEBMAGIC); |
---|
236 | xxx(SMIPSELMAGIC); |
---|
237 | xxx(MIPSEBUMAGIC); |
---|
238 | xxx(MIPSELUMAGIC); |
---|
239 | #endif |
---|
240 | |
---|
241 | #undef xxx |
---|
242 | #endif /* F_EXEC */ |
---|
243 | break; /* Not an executable */ |
---|
244 | } |
---|
245 | } |
---|
246 | break; |
---|
247 | case R_WHEN: |
---|
248 | if ((rtype == R_WHEN) && |
---|
249 | hastype(rules[i].u.u_when.file_types,ftype) && |
---|
250 | glob_match(rules[i].u.u_when.globexp,pathname)) |
---|
251 | return i; |
---|
252 | break; |
---|
253 | case R_IF: |
---|
254 | if (rules[i].u.u_if.inactive) { |
---|
255 | i = rules[i].u.u_if.first; /* will be decremented in a moment... */ |
---|
256 | continue; |
---|
257 | } |
---|
258 | break; |
---|
259 | case R_IF_ELSE: |
---|
260 | if (rules[i].u.u_if.inactive) { |
---|
261 | /* do nothing (we do the else clause and then hit the skip) */ |
---|
262 | } else { |
---|
263 | i = rules[i].u.u_if.first; /* will be decremented in a moment... */ |
---|
264 | continue; |
---|
265 | } |
---|
266 | break; |
---|
267 | case R_SKIP: |
---|
268 | i = rules[i].u.u_skip.first; |
---|
269 | continue; |
---|
270 | case R_FRAMEMARKER: |
---|
271 | break; |
---|
272 | default: |
---|
273 | panic("findrule: unknown rule type"); |
---|
274 | } |
---|
275 | } |
---|
276 | |
---|
277 | /* we did not find a rule */ |
---|
278 | switch(rtype) { |
---|
279 | case R_CHASE: |
---|
280 | case R_WHEN: |
---|
281 | /* the code that looks for these types of rules can deal with |
---|
282 | * this error return value */ |
---|
283 | return -1; |
---|
284 | default: |
---|
285 | panic("findrule: did not find rule"); |
---|
286 | } |
---|
287 | } |
---|
288 | |
---|
289 | |
---|
290 | void getrules(src,dst) |
---|
291 | char *src; |
---|
292 | char *dst; |
---|
293 | { |
---|
294 | char *srcrules,*dstrules; |
---|
295 | static firstread = 0; |
---|
296 | extern int aflag; |
---|
297 | extern char *afile; |
---|
298 | |
---|
299 | newrule(); |
---|
300 | lstrule.type = R_FRAMEMARKER; |
---|
301 | |
---|
302 | vtable_push(); |
---|
303 | |
---|
304 | srcrules = (char *) malloc(strlen(src) + strlen(src_rule_file) + 2); |
---|
305 | (void) strcpy(srcrules,src); |
---|
306 | (void) strcat(srcrules,"/"); |
---|
307 | (void) strcat(srcrules,src_rule_file); |
---|
308 | |
---|
309 | dstrules = (char *) malloc(strlen(dst) + strlen(dst_rule_file) + 2); |
---|
310 | (void) strcpy(dstrules,dst); |
---|
311 | (void) strcat(dstrules,"/"); |
---|
312 | (void) strcat(dstrules,dst_rule_file); |
---|
313 | |
---|
314 | if (nosrcrules == FALSE) |
---|
315 | if (readrules(srcrules,src,dst) != 0) |
---|
316 | { fprintf(stderr,"Error while reading %s\n", srcrules); |
---|
317 | panic("Syntax error in conf file."); |
---|
318 | } |
---|
319 | |
---|
320 | if (nodstrules == FALSE) |
---|
321 | if (readrules(dstrules,src,dst) != 0) |
---|
322 | { fprintf(stderr,"Error while reading %s\n",dstrules); |
---|
323 | panic("Syntax error in conf file."); |
---|
324 | } |
---|
325 | |
---|
326 | if (!(firstread++) && aflag && readrules(afile,src,dst) != 0) |
---|
327 | { fprintf(stderr,"Error while reading %s\n",afile); |
---|
328 | panic("Syntax error in conf file."); |
---|
329 | } |
---|
330 | |
---|
331 | compute_ifs(); /* see below */ |
---|
332 | free(dstrules); |
---|
333 | free(srcrules); |
---|
334 | } |
---|
335 | |
---|
336 | |
---|
337 | void poprules() |
---|
338 | { |
---|
339 | vtable_pop(); |
---|
340 | |
---|
341 | for(;;lastrule--) { |
---|
342 | switch(lstrule.type) { |
---|
343 | case R_MAP: |
---|
344 | sfree(lstrule.u.u_map.globexp); |
---|
345 | svecfree(lstrule.u.u_map.dests); |
---|
346 | continue; |
---|
347 | case R_CHASE: |
---|
348 | sfree(lstrule.u.u_chase.globexp); |
---|
349 | continue; |
---|
350 | case R_ACTION: |
---|
351 | sfree(lstrule.u.u_action.globexp); |
---|
352 | continue; |
---|
353 | case R_WHEN: |
---|
354 | sfree(lstrule.u.u_when.globexp); |
---|
355 | svecfree(lstrule.u.u_when.cmds); |
---|
356 | continue; |
---|
357 | case R_IF: |
---|
358 | case R_IF_ELSE: |
---|
359 | bool_free(lstrule.u.u_if.boolexp); |
---|
360 | continue; |
---|
361 | case R_FRAMEMARKER: |
---|
362 | break; |
---|
363 | default: |
---|
364 | panic("poprules: unknown rule type"); |
---|
365 | } |
---|
366 | lastrule--; |
---|
367 | break; |
---|
368 | } |
---|
369 | |
---|
370 | #ifdef notdef |
---|
371 | /* This doesn't need to be done here because, reconcile will not call */ |
---|
372 | /* findrule after calling this without first calling getrules. If */ |
---|
373 | /* this ever changes, this will have to be turned on again. */ |
---|
374 | compute_ifs(); /* defined below */ |
---|
375 | #endif notdef |
---|
376 | } |
---|
377 | |
---|
378 | static void compute_ifs() |
---|
379 | { |
---|
380 | int i; |
---|
381 | |
---|
382 | rflag &= ~RFLAG_SCAN_TARGET; |
---|
383 | |
---|
384 | for(i = lastrule; i >= 0; i--) { |
---|
385 | switch(rules[i].type) { |
---|
386 | case R_IF: |
---|
387 | case R_IF_ELSE: |
---|
388 | rules[i].u.u_if.inactive = (bool) ! bool_eval(rules[i].u.u_if.boolexp); |
---|
389 | break; |
---|
390 | case R_CHASE: |
---|
391 | case R_MAP: |
---|
392 | case R_WHEN: |
---|
393 | case R_FRAMEMARKER: |
---|
394 | break; |
---|
395 | case R_ACTION: |
---|
396 | if (rules[i].u.u_action.type == ACTION_DELETE) |
---|
397 | rflag |= RFLAG_SCAN_TARGET; |
---|
398 | break; |
---|
399 | default: |
---|
400 | panic("compute_ifs: unknown rule type"); |
---|
401 | } |
---|
402 | } |
---|
403 | } |
---|
404 | |
---|
405 | |
---|
406 | void newrule() |
---|
407 | { |
---|
408 | if (++lastrule >= MAXNRULES) |
---|
409 | panic("newrule: too many rules"); |
---|
410 | if (verbosef > 2) |
---|
411 | printf("newrule: lastrule = %d\n",lastrule); |
---|
412 | } |
---|
413 | |
---|
414 | |
---|