|
|
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.