|
|
1.1 root 1: /*
2: * Glenn Fowler
3: * AT&T Bell Laboratories
4: *
5: * ship support -- a single file for easy bootstrap
6: *
7: * shipop newer [ reference [ file ... ] ]
8: *
9: * true if reference file is newer than file ...
10: * false if any of the files do not exist
11: *
12: * shipop seal [ file ... ]
13: *
14: * generate 32 bit multiplicative congruential PRG checksum for files
15: *
16: * shipop state reference [ file ... | <files ]
17: *
18: * generate mam state file
19: *
20: * shipop time [ file ]
21: *
22: * generate seconds-since-epoch time in hex for today [ file ]
23: *
24: * shipop xap [ file ... ]
25: *
26: * restore pax self-delta files extracted by non-pax cpio
27: */
28:
29: #if !lint
30: static char id[] = "\n@(#)shipop (AT&T Bell Laboratories) 02/11/91\0\n";
31: #endif
32:
33: #include <stdio.h>
34: #include <sys/types.h>
35: #include <sys/stat.h>
36:
37: #define elements(x) (sizeof(x)/sizeof(x[0]))
38:
39: struct optab
40: {
41: char* name;
42: int (*func)();
43: };
44:
45: static char* cmd = "shipop";
46:
47: static int shipnewer();
48: static int shipseal();
49: static int shipstate();
50: static int shiptime();
51: static int shipxap();
52:
53: static struct optab ops[] =
54: {
55: "newer", shipnewer,
56: "seal", shipseal,
57: "state", shipstate,
58: "time", shiptime,
59: "xap", shipxap,
60: };
61:
62: static char* op;
63:
64: static int status;
65:
66: static void error();
67:
68: main(argc, argv)
69: int argc;
70: char** argv;
71: {
72: register char* s;
73: register int i;
74:
75: if (!(s = *++argv))
76: exit(0);
77: for (i = 0; i < elements(ops); i++)
78: if (!strcmp(s, ops[i].name))
79: {
80: op = ops[i].name;
81: exit((*ops[i].func)(argv + 1));
82: }
83: fprintf(stderr, "Usage: %s %s", cmd, ops[0].name);
84: for (i = 1; i < elements(ops); i++)
85: fprintf(stderr, " | %s", ops[i].name);
86: fprintf(stderr, " [ file ... ]\n");
87: exit(2);
88: }
89:
90: static void
91: error(level, file, msg)
92: char* file;
93: char* msg;
94: {
95: fprintf(stderr, "%s: %s", cmd, op);
96: if (level == 1) fprintf(stderr, ": warning");
97: if (file) fprintf(stderr, ": %s", file);
98: if (msg) fprintf(stderr, ": %s", msg);
99: fprintf(stderr, "\n");
100: if (level > status)
101: {
102: if (level > 2) exit(level - 2);
103: status = level;
104: }
105: }
106:
107: /*
108: * shipop newer [ reference [ file ... ] ]
109: */
110:
111: static int
112: shipnewer(argv)
113: register char** argv;
114: {
115: unsigned long ref;
116: struct stat st;
117:
118: if (!*argv || stat(*argv, &st)) return(1);
119: ref = (unsigned long)st.st_mtime;
120: while (*++argv)
121: if (stat(*argv, &st) || ref < (unsigned long)st.st_mtime) return(1);
122: return(0);
123: }
124:
125: /*
126: * shipop seal [ file ... ]
127: */
128:
129: #define HASHPART(h,c) (h = (h) * 987654321L + 123456879L + (c))
130:
131: static char buf[4096];
132:
133: static unsigned long sealfile();
134:
135: static int
136: shipseal(argv)
137: register char** argv;
138: {
139: register char* f;
140: register int fd;
141: unsigned long s;
142:
143: s = 0;
144: if (!*argv) s = sealfile("/dev/stdin", 0, s);
145: else while (f = *argv++)
146: {
147: if (*f == '-' && !*(f + 1)) s = sealfile("/dev/stdin", 0, s);
148: else if ((fd = open(f, 0)) < 0) error(2, f, "cannot read");
149: else
150: {
151: s = sealfile(f, fd, s);
152: (void)close(fd);
153: }
154: }
155: printf("%08x\n", s);
156: return(status);
157: }
158:
159: static unsigned long
160: sealfile(file, fd, s)
161: char* file;
162: int fd;
163: unsigned long s;
164: {
165: register unsigned char* b;
166: register unsigned char* e;
167: register int n;
168:
169: HASHPART(s, 0);
170: while ((n = read(fd, buf, sizeof(buf))) > 0)
171: {
172: b = (unsigned char*)buf;
173: e = b + n;
174: while (b < e) HASHPART(s, *b++);
175: }
176: if (n < 0) error(2, file, "read error");
177: return(s);
178: }
179:
180: /*
181: * shipop state reference [ file ... | <file-list ]
182: */
183:
184: static int
185: shipstate(argv)
186: register char** argv;
187: {
188: register char* s;
189: register int c;
190: long ref;
191: struct stat st;
192:
193: if (!(s = *argv++) || stat(s, &st)) error(3, (char*)0, "reference file omitted");
194: ref = (long)st.st_mtime;
195: if (s = *argv++) do
196: {
197: if (!stat(s, &st))
198: printf("%s %ld\n", s, (long)st.st_mtime - ref);
199: } while (s = *argv++);
200: else do
201: {
202: s = buf;
203: while ((c = getchar()) != EOF && c != ' ' && c != '\n')
204: if (s < buf + sizeof(buf) - 1) *s++ = c;
205: if (s > buf)
206: {
207: *s = 0;
208: if (!stat(buf, &st))
209: printf("%s %ld\n", buf, (long)st.st_mtime - ref);
210: }
211: } while (c != EOF);
212: return(status);
213: }
214:
215: /*
216: * shipop time [ file ]
217: */
218:
219: static int
220: shiptime(argv)
221: register char** argv;
222: {
223: struct stat st;
224: time_t date;
225:
226: extern time_t time();
227:
228: if (*argv && !stat(*argv, &st)) date = st.st_mtime;
229: else time(&date);
230: printf("%08x\n", (long)date);
231: return(status);
232: }
233:
234: /*
235: * shipop xap [ file ... ]
236: */
237:
238: #define XAPHEADER 1024
239:
240: #define round(x) (((x)+(XAPHEADER*8)-1)&~((XAPHEADER*8)-1))
241:
242: static void xapfile();
243: static int isdelta();
244:
245: extern char* malloc();
246:
247: /* ----- enough of sfio and delta/update to do update() ----- */
248: #define reg register
249: #define NIL(t) ((t)0)
250:
251: typedef struct
252: {
253: unsigned char* buf;
254: unsigned char* nxt;
255: unsigned char* end;
256: long siz;
257: } Sfile_t;
258:
259: #define sfgetc(f) ((f)->nxt<(f)->end?*(f)->nxt++:(-1))
260: #define sfgetu(f) ((_Sfi = sfgetc(f)) < 0 ? -1 : \
261: ((_Sfi&SF_MORE) ? _sfgetu(f) : (unsigned long)_Sfi))
262: #define sfread(f,b,n) (((f)->nxt+=(n))<=(f)->end?(n):(-1))
263: #define sfseek(f,o,w) ((f)->nxt=(f)->buf+(o),(o))
264: #define sfsync(f)
265:
266: #define SFUVALUE(v) ((v)&(SF_MORE-1))
267: #define SF_UBITS 7
268: #define SF_MORE (1<<SF_UBITS)
269:
270: static long _Sfi;
271:
272: static unsigned long
273: _sfgetu(f)
274: Sfile_t* f;
275: {
276: register int c;
277: register unsigned long v;
278:
279: v = SFUVALUE(_Sfi);
280: do
281: {
282: if ((c = sfgetc(f)) < 0) return(-1);
283: v = (v << SF_UBITS) | SFUVALUE(c);
284: } while (c & SF_MORE);
285: return(v);
286: }
287:
288: static int
289: sfmove(fr, fw, n)
290: Sfile_t* fr;
291: Sfile_t* fw;
292: register int n;
293: {
294: register char* r;
295: register char* w;
296: register char* e;
297:
298: r = (char*)fr->nxt;
299: w = (char*)fw->nxt;
300: e = w + n;
301: while (w < e) *w++ = *r++;
302: fr->nxt = (unsigned char*)r;
303: fw->nxt = (unsigned char*)w;
304: return(n);
305: }
306:
307: #define CODE_BIT 8
308: #define DELTA_ADD (0)
309: #define DELTA_MOVE (1<<(CODE_BIT-1))
310: #define M_MIN 4
311: #define C_BITS (3)
312: #define C_SIZE ((1<<C_BITS)-3)
313: #define A_SIZE (1 << CODE_BIT)
314: #define C_ADDRS (C_SIZE)
315: #define C_CADDR (C_SIZE+1)
316: #define C_RADDR (C_SIZE+2)
317: #define C_SIZEOF(addr,indx) (indx == C_ADDRS ? 1 : sfulen(addr))
318: #define C_INIT(c,cache,addrs) \
319: { cache[c=0] = 128; while((c += 1) < C_SIZE) cache[c] = (c+1)*128; \
320: addrs[c=0] = 256; while((c += 1) < A_SIZE) addrs[c] = c+256; \
321: }
322: #define C_SET(real,indx,cache,c,addrs) \
323: { if((c += 1) >= C_SIZE) c = 0; cache[c] = real; \
324: if(indx != C_ADDRS) addrs[real&(A_SIZE-1)] = real; \
325: }
326: #define C_REAL(real,addr,indx,caddr,cache,addrs) \
327: { real = indx == C_RADDR ? addr : \
328: indx == C_ADDRS ? addrs[addr] : \
329: indx == C_CADDR ? caddr-addr : addr+cache[indx]; \
330: }
331: #define A_BITS (CODE_BIT-3)
332: #define A_HERE(i) ((i) & ((1<<A_BITS)-2))
333: #define A_LOCAL ((1<<A_BITS)-1)
334: #define A_read(f,i,s) ((s) = A_HERE(i) ? ((i)&A_LOCAL)-1 : sfgetu(f)+A_LOCAL )
335:
336: #define M_BITS (CODE_BIT-(C_BITS+1))
337: #define M_LOCAL ((1<<M_BITS) + M_MIN-1)
338: #define M_HERE(i) ((i) & ((1<<M_BITS)-1))
339: #define M_sread(f,i,s) ((s) = ((s) = M_HERE(i)) ? \
340: (s)+(M_MIN-1) : sfgetu(f)+M_LOCAL )
341: #define M_cread(i,c) ((c) = ((i)>>M_BITS) & ((1<<C_BITS)-1) )
342: #define M_aread(f,c,a) ((a) = (c) == C_ADDRS ? sfgetc(f) : sfgetu(f) )
343: #define M_READ(f,i,a,c,s) \
344: ((M_cread(i,c)<0 || M_aread(f,c,a)<0 || M_sread(f,i,s)<0) ? -1 : 0)
345:
346: #define T_MBITS (CODE_BIT - (A_BITS+1))
347: #define T_ABITS (CODE_BIT - (T_MBITS+C_BITS+1))
348: #define T_TINY(i) ((i) & (((1<<T_MBITS)-1) << (C_BITS+T_ABITS)) )
349: #define T_MREAD(f,i,a,c,s) \
350: (((c) = ((i)>>T_ABITS) & ((1<<C_BITS)-1)), \
351: ((s) = (((i)>>(C_BITS+T_ABITS))&((1<<T_MBITS)-1)) + M_MIN-1), \
352: M_aread(f,c,a) )
353: #define T_AREAD(i,s) ((s) = ((i) & ((1<<T_ABITS)-1)) + 1)
354: #define A_READ(f,i,s) (T_TINY(i) ? T_AREAD(i,s) : A_read(f,i,s))
355:
356: /* now the untouched libdelta/update.c */
357:
358: /*
359: ** Reconstruct a target file from a source file and a delta file.
360: ** The delta file contain block move instructions computed by delta().
361: **
362: ** Written by Kiem-Phong Vo, 03/27/90
363: */
364:
365: static long supdate(fsrc,fdel,wtar,rtar,sbase,tbase)
366: Sfile_t *fsrc; /* source file */
367: Sfile_t *fdel; /* delta instruction file */
368: Sfile_t *wtar; /* target file for writing */
369: Sfile_t *rtar; /* target file for reading */
370: reg long *sbase, *tbase; /* current bases */
371: {
372: reg int inst;
373: reg int c;
374: reg long caddr;
375: long cache[C_SIZE], addrs[A_SIZE];
376: long n_src, n_tar;
377: #ifdef DEBUG
378: int n_inst = 0;
379: #endif
380: if((n_src = sfgetu(fdel)) < 0 || (n_tar = sfgetu(fdel)) < 0)
381: return -1;
382:
383: C_INIT(c,cache,addrs);
384: caddr = n_src;
385: while((inst = sfgetc(fdel)) >= 0)
386: {
387: reg long addr, real, size;
388: reg int indx;
389: #ifdef DEBUG
390: n_inst++;
391: #endif
392: if(inst == 0)
393: {
394: if(sbase)
395: *sbase += n_src;
396: if(tbase)
397: *tbase += n_tar;
398: return caddr == (n_tar+n_src) ? n_tar : -1L;
399: }
400:
401: if((inst&DELTA_MOVE) == 0)
402: { /* do add */
403: if(A_READ(fdel,inst,size) < 0)
404: return -1L;
405: if(sfmove(fdel,wtar,size) < 0)
406: return -1L;
407: caddr += size;
408:
409: if(T_TINY(inst))
410: { /* read the merged move instruction */
411: if(T_MREAD(fdel,inst,addr,indx,size) < 0)
412: return -1;
413: goto do_move;
414: }
415: }
416: else
417: { /* move instruction */
418: if(M_READ(fdel,inst,addr,indx,size) < 0)
419: return -1;
420: do_move:
421: C_REAL(real,addr,indx,caddr,cache,addrs);
422: C_SET(real,indx,cache,c,addrs);
423: if(real >= n_src || !sbase)
424: { /* self-move */
425: sfsync(wtar);
426: real = (real-n_src) + *tbase;
427: if(sfseek(rtar,real,0) < 0)
428: return -1L;
429: if(sfmove(rtar,wtar,size) < 0)
430: return -1L;
431: }
432: else
433: { /* source-move */
434: if(sbase)
435: real += *sbase;
436: if(sfseek(fsrc,real,0) < 0)
437: return -1L;
438: if(sfmove(fsrc,wtar,size) < 0)
439: return -1L;
440: }
441: caddr += size;
442: }
443: }
444:
445: /* should never get here */
446: return -1L;
447: }
448:
449: long update(fsrc,fdel,wtar,rtar)
450: Sfile_t *fsrc; /* source stream */
451: Sfile_t *fdel; /* delta stream */
452: Sfile_t *wtar; /* write stream for target file */
453: Sfile_t *rtar; /* read stream for target file */
454: {
455: reg long nsrc, ntar, header, t, tar;
456: char magic[4];
457: long sbase, tbase;
458: extern long supdate();
459:
460: if(sfread(fdel,magic,4) != 4 || sfgetc(fdel) < 0)
461: return -1L;
462:
463: if((nsrc = sfgetu(fdel)) < 0 || (ntar = sfgetu(fdel)) < 0 ||
464: (header = sfgetu(fdel)) < 0)
465: return -1L;
466:
467: /* ----- cheat here to setup wtar and rtar ----- */
468: if (wtar->siz < ntar)
469: {
470: if (wtar->buf) free(wtar->buf);
471: wtar->siz = round(ntar);
472: if (!(wtar->buf = (unsigned char*)malloc(wtar->siz)))
473: error(3, (char*)0, "out of space");
474: rtar->siz = wtar->siz;
475: }
476: rtar->nxt = rtar->buf = wtar->nxt = wtar->buf;
477: /* ----- */
478: for(tbase = sbase = tar = 0; ;)
479: { /* process all windows */
480: if(header > 0)
481: t = supdate(fsrc,fdel,wtar,rtar,NIL(long*),&tbase);
482: else t = supdate(fsrc,fdel,wtar,rtar,&sbase,&tbase);
483: if(t >= 0)
484: {
485: if((tar += t) == ntar)
486: break;
487: else if(tar < ntar)
488: continue;
489: }
490:
491: /* error happened */
492: ntar = -1L;
493: break;
494: }
495:
496: return ntar;
497: }
498: /* ----- */
499:
500: static int
501: shipxap(argv)
502: char** argv;
503: {
504: char* file;
505:
506: umask(0);
507: while (file = *argv++) xapfile(file);
508: return(status);
509: }
510:
511: static void
512: xapfile(file)
513: char* file;
514: {
515: int fd;
516: long n;
517: int m;
518: struct stat st;
519:
520: static Sfile_t fdel;
521: static Sfile_t rtar;
522: static Sfile_t wtar;
523:
524: if ((fd = open(file, 0)) < 0)
525: {
526: error(2, file, "cannot read");
527: return;
528: }
529: if (fstat(fd, &st))
530: {
531: error(2, file, "cannot stat");
532: close(fd);
533: return;
534: }
535: n = st.st_size;
536: if (n > fdel.siz)
537: {
538: if (fdel.buf) free(fdel.buf);
539: fdel.siz = round(n);
540: if (!(fdel.buf = (unsigned char*)malloc(fdel.siz)))
541: error(3, file, "out of space");
542: }
543: m = n > XAPHEADER ? XAPHEADER : n;
544: if (read(fd, fdel.buf, m) != m)
545: {
546: error(2, file, "cannot read header");
547: close(fd);
548: return;
549: }
550: fdel.nxt = fdel.buf;
551: fdel.end = fdel.buf + m;
552: if (!isdelta(&fdel))
553: {
554: close(fd);
555: return;
556: }
557: if ((n -= m) > 0)
558: {
559: if (read(fd, fdel.buf + m, n) != n)
560: {
561: error(2, file, "cannot read");
562: close(fd);
563: return;
564: }
565: fdel.end += n;
566: }
567: close(fd);
568: if ((n = update((Sfile_t*)0, &fdel, &wtar, &rtar)) < 0)
569: {
570: error(2, file, "cannot update");
571: return;
572: }
573: if ((fd = creat(file, st.st_mode&0777)) < 0)
574: {
575: if (chmod(file, st.st_mode | 0200) || (fd = creat(file, st.st_mode&0777)) < 0)
576: {
577: error(2, file, "cannot open for writing");
578: return;
579: }
580: chmod(file, st.st_mode);
581: }
582: if (write(fd, wtar.buf, n) != n)
583: error(2, file, "cannot write");
584: close(fd);
585: }
586:
587: static int
588: isdelta(f)
589: register Sfile_t* f;
590: {
591: register int b;
592: register int c;
593:
594: if (sfgetc(f) != 'c' || sfgetc(f) != 'A') return(0);
595: b = 0;
596: for (;;)
597: {
598: if ((c = sfgetc(f)) < 0) return(0);
599: if (c) b = 0;
600: else
601: {
602: if (b) return(1);
603: b = 1;
604: }
605: }
606: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.