|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)ar.c 4.5 (Berkeley) 9/25/83"; ! 3: #endif ! 4: ! 5: /* ! 6: * ar - portable (ascii) format version ! 7: */ ! 8: #include <sys/types.h> ! 9: #include <sys/stat.h> ! 10: #include <sys/time.h> ! 11: ! 12: #include <stdio.h> ! 13: #include <ar.h> ! 14: #include <signal.h> ! 15: ! 16: struct stat stbuf; ! 17: struct ar_hdr arbuf; ! 18: struct lar_hdr { ! 19: char lar_name[16]; ! 20: long lar_date; ! 21: u_short lar_uid; ! 22: u_short lar_gid; ! 23: u_short lar_mode; ! 24: long lar_size; ! 25: } larbuf; ! 26: ! 27: #define SKIP 1 ! 28: #define IODD 2 ! 29: #define OODD 4 ! 30: #define HEAD 8 ! 31: ! 32: char *man = { "mrxtdpq" }; ! 33: char *opt = { "uvnbailo" }; ! 34: ! 35: int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0}; ! 36: int sigdone(); ! 37: long lseek(); ! 38: int rcmd(); ! 39: int dcmd(); ! 40: int xcmd(); ! 41: int tcmd(); ! 42: int pcmd(); ! 43: int mcmd(); ! 44: int qcmd(); ! 45: int (*comfun)(); ! 46: char flg[26]; ! 47: char **namv; ! 48: int namc; ! 49: char *arnam; ! 50: char *ponam; ! 51: char *tmpnam = { "/tmp/vXXXXX" }; ! 52: char *tmp1nam = { "/tmp/v1XXXXX" }; ! 53: char *tmp2nam = { "/tmp/v2XXXXX" }; ! 54: char *tfnam; ! 55: char *tf1nam; ! 56: char *tf2nam; ! 57: char *file; ! 58: char name[16]; ! 59: int af; ! 60: int tf; ! 61: int tf1; ! 62: int tf2; ! 63: int qf; ! 64: int bastate; ! 65: char buf[BUFSIZ]; ! 66: int truncate; /* ok to truncate argument filenames */ ! 67: ! 68: char *trim(); ! 69: char *mktemp(); ! 70: char *ctime(); ! 71: ! 72: main(argc, argv) ! 73: char *argv[]; ! 74: { ! 75: register i; ! 76: register char *cp; ! 77: ! 78: for(i=0; signum[i]; i++) ! 79: if(signal(signum[i], SIG_IGN) != SIG_IGN) ! 80: signal(signum[i], sigdone); ! 81: if(argc < 3) ! 82: usage(); ! 83: cp = argv[1]; ! 84: for(cp = argv[1]; *cp; cp++) ! 85: switch(*cp) { ! 86: case 'o': ! 87: case 'l': ! 88: case 'v': ! 89: case 'u': ! 90: case 'n': ! 91: case 'a': ! 92: case 'b': ! 93: case 'c': ! 94: case 'i': ! 95: flg[*cp - 'a']++; ! 96: continue; ! 97: ! 98: case 'r': ! 99: setcom(rcmd); ! 100: continue; ! 101: ! 102: case 'd': ! 103: setcom(dcmd); ! 104: continue; ! 105: ! 106: case 'x': ! 107: setcom(xcmd); ! 108: continue; ! 109: ! 110: case 't': ! 111: setcom(tcmd); ! 112: continue; ! 113: ! 114: case 'p': ! 115: setcom(pcmd); ! 116: continue; ! 117: ! 118: case 'm': ! 119: setcom(mcmd); ! 120: continue; ! 121: ! 122: case 'q': ! 123: setcom(qcmd); ! 124: continue; ! 125: ! 126: default: ! 127: fprintf(stderr, "ar: bad option `%c'\n", *cp); ! 128: done(1); ! 129: } ! 130: if(flg['l'-'a']) { ! 131: tmpnam = "vXXXXX"; ! 132: tmp1nam = "v1XXXXX"; ! 133: tmp2nam = "v2XXXXX"; ! 134: } ! 135: if(flg['i'-'a']) ! 136: flg['b'-'a']++; ! 137: if(flg['a'-'a'] || flg['b'-'a']) { ! 138: bastate = 1; ! 139: ponam = trim(argv[2]); ! 140: argv++; ! 141: argc--; ! 142: if(argc < 3) ! 143: usage(); ! 144: } ! 145: arnam = argv[2]; ! 146: namv = argv+3; ! 147: namc = argc-3; ! 148: if(comfun == 0) { ! 149: if(flg['u'-'a'] == 0) { ! 150: fprintf(stderr, "ar: one of [%s] must be specified\n", man); ! 151: done(1); ! 152: } ! 153: setcom(rcmd); ! 154: } ! 155: (*comfun)(); ! 156: done(notfound()); ! 157: } ! 158: ! 159: setcom(fun) ! 160: int (*fun)(); ! 161: { ! 162: ! 163: if(comfun != 0) { ! 164: fprintf(stderr, "ar: only one of [%s] allowed\n", man); ! 165: done(1); ! 166: } ! 167: comfun = fun; ! 168: } ! 169: ! 170: rcmd() ! 171: { ! 172: register f; ! 173: ! 174: init(); ! 175: getaf(); ! 176: while(!getdir()) { ! 177: bamatch(); ! 178: if(namc == 0 || match()) { ! 179: f = stats(); ! 180: if(f < 0) { ! 181: if(namc) ! 182: fprintf(stderr, "ar: cannot open %s\n", file); ! 183: goto cp; ! 184: } ! 185: if(flg['u'-'a']) ! 186: if(stbuf.st_mtime <= larbuf.lar_date) { ! 187: close(f); ! 188: goto cp; ! 189: } ! 190: mesg('r'); ! 191: copyfil(af, -1, IODD+SKIP); ! 192: movefil(f); ! 193: continue; ! 194: } ! 195: cp: ! 196: mesg('c'); ! 197: copyfil(af, tf, IODD+OODD+HEAD); ! 198: } ! 199: cleanup(); ! 200: } ! 201: ! 202: dcmd() ! 203: { ! 204: ! 205: init(); ! 206: if(getaf()) ! 207: noar(); ! 208: while(!getdir()) { ! 209: if(match()) { ! 210: mesg('d'); ! 211: copyfil(af, -1, IODD+SKIP); ! 212: continue; ! 213: } ! 214: mesg('c'); ! 215: copyfil(af, tf, IODD+OODD+HEAD); ! 216: } ! 217: install(); ! 218: } ! 219: ! 220: xcmd() ! 221: { ! 222: register f; ! 223: struct timeval tv[2]; ! 224: ! 225: if(getaf()) ! 226: noar(); ! 227: while(!getdir()) { ! 228: if(namc == 0 || match()) { ! 229: f = creat(file, larbuf.lar_mode & 0777); ! 230: if(f < 0) { ! 231: fprintf(stderr, "ar: %s cannot create\n", file); ! 232: goto sk; ! 233: } ! 234: mesg('x'); ! 235: copyfil(af, f, IODD); ! 236: close(f); ! 237: if (flg['o'-'a']) { ! 238: tv[0].tv_sec = tv[1].tv_sec = larbuf.lar_date; ! 239: tv[0].tv_usec = tv[1].tv_usec = 0; ! 240: utimes(file, tv); ! 241: } ! 242: continue; ! 243: } ! 244: sk: ! 245: mesg('c'); ! 246: copyfil(af, -1, IODD+SKIP); ! 247: if (namc > 0 && !morefil()) ! 248: done(0); ! 249: } ! 250: } ! 251: ! 252: pcmd() ! 253: { ! 254: ! 255: if(getaf()) ! 256: noar(); ! 257: while(!getdir()) { ! 258: if(namc == 0 || match()) { ! 259: if(flg['v'-'a']) { ! 260: printf("\n<%s>\n\n", file); ! 261: fflush(stdout); ! 262: } ! 263: copyfil(af, 1, IODD); ! 264: continue; ! 265: } ! 266: copyfil(af, -1, IODD+SKIP); ! 267: } ! 268: } ! 269: ! 270: mcmd() ! 271: { ! 272: ! 273: init(); ! 274: if(getaf()) ! 275: noar(); ! 276: tf2nam = mktemp(tmp2nam); ! 277: close(creat(tf2nam, 0600)); ! 278: tf2 = open(tf2nam, 2); ! 279: if(tf2 < 0) { ! 280: fprintf(stderr, "ar: cannot create third temp\n"); ! 281: done(1); ! 282: } ! 283: while(!getdir()) { ! 284: bamatch(); ! 285: if(match()) { ! 286: mesg('m'); ! 287: copyfil(af, tf2, IODD+OODD+HEAD); ! 288: continue; ! 289: } ! 290: mesg('c'); ! 291: copyfil(af, tf, IODD+OODD+HEAD); ! 292: } ! 293: install(); ! 294: } ! 295: ! 296: tcmd() ! 297: { ! 298: ! 299: if(getaf()) ! 300: noar(); ! 301: while(!getdir()) { ! 302: if(namc == 0 || match()) { ! 303: if(flg['v'-'a']) ! 304: longt(); ! 305: printf("%s\n", trim(file)); ! 306: } ! 307: copyfil(af, -1, IODD+SKIP); ! 308: } ! 309: } ! 310: ! 311: qcmd() ! 312: { ! 313: register i, f; ! 314: ! 315: if (flg['a'-'a'] || flg['b'-'a']) { ! 316: fprintf(stderr, "ar: abi not allowed with q\n"); ! 317: done(1); ! 318: } ! 319: truncate++; ! 320: getqf(); ! 321: for(i=0; signum[i]; i++) ! 322: signal(signum[i], SIG_IGN); ! 323: lseek(qf, 0l, 2); ! 324: for(i=0; i<namc; i++) { ! 325: file = namv[i]; ! 326: if(file == 0) ! 327: continue; ! 328: namv[i] = 0; ! 329: mesg('q'); ! 330: f = stats(); ! 331: if(f < 0) { ! 332: fprintf(stderr, "ar: %s cannot open\n", file); ! 333: continue; ! 334: } ! 335: tf = qf; ! 336: movefil(f); ! 337: qf = tf; ! 338: } ! 339: } ! 340: ! 341: init() ! 342: { ! 343: ! 344: tfnam = mktemp(tmpnam); ! 345: close(creat(tfnam, 0600)); ! 346: tf = open(tfnam, 2); ! 347: if(tf < 0) { ! 348: fprintf(stderr, "ar: cannot create temp file\n"); ! 349: done(1); ! 350: } ! 351: if (write(tf, ARMAG, SARMAG) != SARMAG) ! 352: wrerr(); ! 353: } ! 354: ! 355: getaf() ! 356: { ! 357: char mbuf[SARMAG]; ! 358: ! 359: af = open(arnam, 0); ! 360: if(af < 0) ! 361: return(1); ! 362: if (read(af, mbuf, SARMAG) != SARMAG || strncmp(mbuf, ARMAG, SARMAG)) { ! 363: fprintf(stderr, "ar: %s not in archive format\n", arnam); ! 364: done(1); ! 365: } ! 366: return(0); ! 367: } ! 368: ! 369: getqf() ! 370: { ! 371: char mbuf[SARMAG]; ! 372: ! 373: if ((qf = open(arnam, 2)) < 0) { ! 374: if(!flg['c'-'a']) ! 375: fprintf(stderr, "ar: creating %s\n", arnam); ! 376: if ((qf = creat(arnam, 0666)) < 0) { ! 377: fprintf(stderr, "ar: cannot create %s\n", arnam); ! 378: done(1); ! 379: } ! 380: if (write(qf, ARMAG, SARMAG) != SARMAG) ! 381: wrerr(); ! 382: } else if (read(qf, mbuf, SARMAG) != SARMAG ! 383: || strncmp(mbuf, ARMAG, SARMAG)) { ! 384: fprintf(stderr, "ar: %s not in archive format\n", arnam); ! 385: done(1); ! 386: } ! 387: } ! 388: ! 389: usage() ! 390: { ! 391: printf("usage: ar [%s][%s] archive files ...\n", man, opt); ! 392: done(1); ! 393: } ! 394: ! 395: noar() ! 396: { ! 397: ! 398: fprintf(stderr, "ar: %s does not exist\n", arnam); ! 399: done(1); ! 400: } ! 401: ! 402: sigdone() ! 403: { ! 404: done(100); ! 405: } ! 406: ! 407: done(c) ! 408: { ! 409: ! 410: if(tfnam) ! 411: unlink(tfnam); ! 412: if(tf1nam) ! 413: unlink(tf1nam); ! 414: if(tf2nam) ! 415: unlink(tf2nam); ! 416: exit(c); ! 417: } ! 418: ! 419: notfound() ! 420: { ! 421: register i, n; ! 422: ! 423: n = 0; ! 424: for(i=0; i<namc; i++) ! 425: if(namv[i]) { ! 426: fprintf(stderr, "ar: %s not found\n", namv[i]); ! 427: n++; ! 428: } ! 429: return(n); ! 430: } ! 431: ! 432: morefil() ! 433: { ! 434: register i, n; ! 435: ! 436: n = 0; ! 437: for(i=0; i<namc; i++) ! 438: if(namv[i]) ! 439: n++; ! 440: return(n); ! 441: } ! 442: ! 443: cleanup() ! 444: { ! 445: register i, f; ! 446: ! 447: truncate++; ! 448: for(i=0; i<namc; i++) { ! 449: file = namv[i]; ! 450: if(file == 0) ! 451: continue; ! 452: namv[i] = 0; ! 453: mesg('a'); ! 454: f = stats(); ! 455: if(f < 0) { ! 456: fprintf(stderr, "ar: %s cannot open\n", file); ! 457: continue; ! 458: } ! 459: movefil(f); ! 460: } ! 461: install(); ! 462: } ! 463: ! 464: install() ! 465: { ! 466: register i; ! 467: ! 468: for(i=0; signum[i]; i++) ! 469: signal(signum[i], SIG_IGN); ! 470: if(af < 0) ! 471: if(!flg['c'-'a']) ! 472: fprintf(stderr, "ar: creating %s\n", arnam); ! 473: close(af); ! 474: af = creat(arnam, 0666); ! 475: if(af < 0) { ! 476: fprintf(stderr, "ar: cannot create %s\n", arnam); ! 477: done(1); ! 478: } ! 479: if(tfnam) { ! 480: lseek(tf, 0l, 0); ! 481: while((i = read(tf, buf, BUFSIZ)) > 0) ! 482: if (write(af, buf, i) != i) ! 483: wrerr(); ! 484: } ! 485: if(tf2nam) { ! 486: lseek(tf2, 0l, 0); ! 487: while((i = read(tf2, buf, BUFSIZ)) > 0) ! 488: if (write(af, buf, i) != i) ! 489: wrerr(); ! 490: } ! 491: if(tf1nam) { ! 492: lseek(tf1, 0l, 0); ! 493: while((i = read(tf1, buf, BUFSIZ)) > 0) ! 494: if (write(af, buf, i) != i) ! 495: wrerr(); ! 496: } ! 497: } ! 498: ! 499: /* ! 500: * insert the file 'file' ! 501: * into the temporary file ! 502: */ ! 503: movefil(f) ! 504: { ! 505: char buf[sizeof(arbuf)+1]; ! 506: ! 507: sprintf(buf, "%-16s%-12ld%-6u%-6u%-8o%-10ld%-2s", ! 508: trim(file), ! 509: stbuf.st_mtime, ! 510: stbuf.st_uid, ! 511: stbuf.st_gid, ! 512: stbuf.st_mode, ! 513: stbuf.st_size, ! 514: ARFMAG); ! 515: strncpy((char *)&arbuf, buf, sizeof(arbuf)); ! 516: larbuf.lar_size = stbuf.st_size; ! 517: copyfil(f, tf, OODD+HEAD); ! 518: close(f); ! 519: } ! 520: ! 521: stats() ! 522: { ! 523: register f; ! 524: ! 525: f = open(file, 0); ! 526: if(f < 0) ! 527: return(f); ! 528: if(fstat(f, &stbuf) < 0) { ! 529: close(f); ! 530: return(-1); ! 531: } ! 532: return(f); ! 533: } ! 534: ! 535: /* ! 536: * copy next file ! 537: * size given in arbuf ! 538: */ ! 539: copyfil(fi, fo, flag) ! 540: { ! 541: register i, o; ! 542: int pe; ! 543: ! 544: if(flag & HEAD) { ! 545: for (i=sizeof(arbuf.ar_name)-1; i>=0; i--) { ! 546: if (arbuf.ar_name[i]==' ') ! 547: continue; ! 548: else if (arbuf.ar_name[i]=='\0') ! 549: arbuf.ar_name[i] = ' '; ! 550: else ! 551: break; ! 552: } ! 553: if (write(fo, (char *)&arbuf, sizeof arbuf) != sizeof arbuf) ! 554: wrerr(); ! 555: } ! 556: pe = 0; ! 557: while(larbuf.lar_size > 0) { ! 558: i = o = BUFSIZ; ! 559: if(larbuf.lar_size < i) { ! 560: i = o = larbuf.lar_size; ! 561: if(i&1) { ! 562: buf[i] = '\n'; ! 563: if(flag & IODD) ! 564: i++; ! 565: if(flag & OODD) ! 566: o++; ! 567: } ! 568: } ! 569: if(read(fi, buf, i) != i) ! 570: pe++; ! 571: if((flag & SKIP) == 0) ! 572: if (write(fo, buf, o) != o) ! 573: wrerr(); ! 574: larbuf.lar_size -= BUFSIZ; ! 575: } ! 576: if(pe) ! 577: phserr(); ! 578: } ! 579: ! 580: getdir() ! 581: { ! 582: register char *cp; ! 583: register i; ! 584: ! 585: i = read(af, (char *)&arbuf, sizeof arbuf); ! 586: if(i != sizeof arbuf) { ! 587: if(tf1nam) { ! 588: i = tf; ! 589: tf = tf1; ! 590: tf1 = i; ! 591: } ! 592: return(1); ! 593: } ! 594: if (strncmp(arbuf.ar_fmag, ARFMAG, sizeof(arbuf.ar_fmag))) { ! 595: fprintf(stderr, "ar: malformed archive (at %ld)\n", lseek(af, 0L, 1)); ! 596: done(1); ! 597: } ! 598: cp = arbuf.ar_name + sizeof(arbuf.ar_name); ! 599: while (*--cp==' ') ! 600: ; ! 601: *++cp = '\0'; ! 602: strncpy(name, arbuf.ar_name, sizeof(arbuf.ar_name)); ! 603: file = name; ! 604: strncpy(larbuf.lar_name, name, sizeof(larbuf.lar_name)); ! 605: sscanf(arbuf.ar_date, "%ld", &larbuf.lar_date); ! 606: sscanf(arbuf.ar_uid, "%hd", &larbuf.lar_uid); ! 607: sscanf(arbuf.ar_gid, "%hd", &larbuf.lar_gid); ! 608: sscanf(arbuf.ar_mode, "%ho", &larbuf.lar_mode); ! 609: sscanf(arbuf.ar_size, "%ld", &larbuf.lar_size); ! 610: return(0); ! 611: } ! 612: ! 613: match() ! 614: { ! 615: register i; ! 616: ! 617: for(i=0; i<namc; i++) { ! 618: if(namv[i] == 0) ! 619: continue; ! 620: if(strcmp(trim(namv[i]), file) == 0) { ! 621: file = namv[i]; ! 622: namv[i] = 0; ! 623: return(1); ! 624: } ! 625: } ! 626: return(0); ! 627: } ! 628: ! 629: bamatch() ! 630: { ! 631: register f; ! 632: ! 633: switch(bastate) { ! 634: ! 635: case 1: ! 636: if(strcmp(file, ponam) != 0) ! 637: return; ! 638: bastate = 2; ! 639: if(flg['a'-'a']) ! 640: return; ! 641: ! 642: case 2: ! 643: bastate = 0; ! 644: tf1nam = mktemp(tmp1nam); ! 645: close(creat(tf1nam, 0600)); ! 646: f = open(tf1nam, 2); ! 647: if(f < 0) { ! 648: fprintf(stderr, "ar: cannot create second temp\n"); ! 649: return; ! 650: } ! 651: tf1 = tf; ! 652: tf = f; ! 653: } ! 654: } ! 655: ! 656: phserr() ! 657: { ! 658: ! 659: fprintf(stderr, "ar: phase error on %s\n", file); ! 660: } ! 661: ! 662: mesg(c) ! 663: { ! 664: ! 665: if(flg['v'-'a']) ! 666: if(c != 'c' || flg['v'-'a'] > 1) ! 667: printf("%c - %s\n", c, file); ! 668: } ! 669: ! 670: char * ! 671: trim(s) ! 672: char *s; ! 673: { ! 674: register char *p1, *p2; ! 675: ! 676: /* Strip trailing slashes */ ! 677: for(p1 = s; *p1; p1++) ! 678: ; ! 679: while(p1 > s) { ! 680: if(*--p1 != '/') ! 681: break; ! 682: *p1 = 0; ! 683: } ! 684: ! 685: /* Find last component of path; do not zap the path */ ! 686: p2 = s; ! 687: for(p1 = s; *p1; p1++) ! 688: if(*p1 == '/') ! 689: p2 = p1+1; ! 690: ! 691: /* ! 692: * Truncate name if too long, only if we are doing an 'add' ! 693: * type operation. We only allow 15 cause rest of ar ! 694: * isn't smart enough to deal with non-null terminated ! 695: * names. Need an exit status convention... ! 696: * Need yet another new archive format... ! 697: */ ! 698: if (truncate && strlen(p2) > sizeof(arbuf.ar_name) - 1) { ! 699: fprintf(stderr, "ar: filename %s truncated to ", p2); ! 700: *(p2 + sizeof(arbuf.ar_name) - 1) = '\0'; ! 701: fprintf(stderr, "%s\n", p2); ! 702: } ! 703: return(p2); ! 704: } ! 705: ! 706: #define IFMT 060000 ! 707: #define ISARG 01000 ! 708: #define LARGE 010000 ! 709: #define SUID 04000 ! 710: #define SGID 02000 ! 711: #define ROWN 0400 ! 712: #define WOWN 0200 ! 713: #define XOWN 0100 ! 714: #define RGRP 040 ! 715: #define WGRP 020 ! 716: #define XGRP 010 ! 717: #define ROTH 04 ! 718: #define WOTH 02 ! 719: #define XOTH 01 ! 720: #define STXT 01000 ! 721: ! 722: longt() ! 723: { ! 724: register char *cp; ! 725: ! 726: pmode(); ! 727: printf("%3d/%1d", larbuf.lar_uid, larbuf.lar_gid); ! 728: printf("%7ld", larbuf.lar_size); ! 729: cp = ctime(&larbuf.lar_date); ! 730: printf(" %-12.12s %-4.4s ", cp+4, cp+20); ! 731: } ! 732: ! 733: int m1[] = { 1, ROWN, 'r', '-' }; ! 734: int m2[] = { 1, WOWN, 'w', '-' }; ! 735: int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; ! 736: int m4[] = { 1, RGRP, 'r', '-' }; ! 737: int m5[] = { 1, WGRP, 'w', '-' }; ! 738: int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; ! 739: int m7[] = { 1, ROTH, 'r', '-' }; ! 740: int m8[] = { 1, WOTH, 'w', '-' }; ! 741: int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; ! 742: ! 743: int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; ! 744: ! 745: pmode() ! 746: { ! 747: register int **mp; ! 748: ! 749: for (mp = &m[0]; mp < &m[9];) ! 750: select(*mp++); ! 751: } ! 752: ! 753: select(pairp) ! 754: int *pairp; ! 755: { ! 756: register int n, *ap; ! 757: ! 758: ap = pairp; ! 759: n = *ap++; ! 760: while (--n>=0 && (larbuf.lar_mode&*ap++)==0) ! 761: ap++; ! 762: putchar(*ap); ! 763: } ! 764: ! 765: wrerr() ! 766: { ! 767: perror("ar write error"); ! 768: done(1); ! 769: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.