|
|
1.1 ! root 1: /* @(#)ar.c 2.8 10/12/83 */ ! 2: /* ar: UNIX Archive Maintainer */ ! 3: ! 4: ! 5: #include <stdio.h> ! 6: #include <signal.h> ! 7: #include <sys/types.h> ! 8: #include <sys/stat.h> ! 9: #include <ar.h> ! 10: #include <filehdr.h> ! 11: #include <syms.h> ! 12: #include <string.h> ! 13: ! 14: ! 15: #define SKIP 1 ! 16: #define IODD 2 ! 17: #define OODD 4 ! 18: #define HEAD 8 ! 19: ! 20: #define SUID 04000 ! 21: #define SGID 02000 ! 22: #define ROWN 0400 ! 23: #define WOWN 0200 ! 24: #define XOWN 0100 ! 25: #define RGRP 040 ! 26: #define WGRP 020 ! 27: #define XGRP 010 ! 28: #define ROTH 04 ! 29: #define WOTH 02 ! 30: #define XOTH 01 ! 31: #define STXT 01000 ! 32: ! 33: #define TABSZ 2000 ! 34: ! 35: #define SYMDIRNAME "/ " /* symbol directory filename */ ! 36: ! 37: struct stat stbuf; ! 38: ! 39: struct ar_hdr ariobuf; /* input/output copy of archive member header */ ! 40: ! 41: struct /* usable copy of archive file member header */ ! 42: { ! 43: char ar_name[16]; ! 44: long ar_date; ! 45: int ar_uid; ! 46: int ar_gid; ! 47: long ar_mode; ! 48: long ar_size; ! 49: } arbuf; ! 50: ! 51: long sym_ptr[TABSZ]; /* offsets for symbol directory */ ! 52: char sym_offsets[TABSZ][4]; /* sputl'd version of the offsets */ ! 53: char *sym_name[TABSZ]; /* names for symbols in directory */ ! 54: char sym_nsyms[4]; /* sputl'd number of symbols */ ! 55: ! 56: struct filehdr ml_filhdr; /* COFF machine language file header */ ! 57: ! 58: char *man = { "mrxtdpq" }; ! 59: char *opt = { "uvcbailso" }; ! 60: ! 61: int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0}; ! 62: char flg[26]; ! 63: char **namv; ! 64: int namc; ! 65: char *arnam; ! 66: char *ponam; ! 67: char *tmpdir = ""; /* default temp file directory to environment */ ! 68: char *tfnam; ! 69: char *tf1nam; ! 70: char *tf2nam; ! 71: char *file; ! 72: char name[16]; ! 73: int af; ! 74: int tf; ! 75: int tf1; ! 76: int tf2; ! 77: int qf; ! 78: ! 79: int bastate; ! 80: char buf[BUFSIZ]; ! 81: ! 82: ! 83: int update; /* was archive written or updated */ ! 84: int nsyms; /* nbr of symbol directory entries */ ! 85: long mem_ptr; /* position of archive member in the archive */ ! 86: long mem_skip; /* adjustment to add to mem_ptr for "real" position */ ! 87: ! 88: int filenum = 0; /* incremented by ml_file() for getname()'s benefit */ ! 89: ! 90: char *str_base, /* start of string table for names */ ! 91: *str_top; /* pointer to next available location */ ! 92: ! 93: ! 94: int m1[] = { 1, ROWN, 'r', '-' }; ! 95: int m2[] = { 1, WOWN, 'w', '-' }; ! 96: int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; ! 97: int m4[] = { 1, RGRP, 'r', '-' }; ! 98: int m5[] = { 1, WGRP, 'w', '-' }; ! 99: int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; ! 100: int m7[] = { 1, ROTH, 'r', '-' }; ! 101: int m8[] = { 1, WOTH, 'w', '-' }; ! 102: int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; ! 103: ! 104: int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; ! 105: ! 106: ! 107: /* declare all archive functions */ ! 108: ! 109: int setcom(), rcmd(), dcmd(), xcmd(), ! 110: pcmd(), mcmd(), tcmd(), qcmd(), ! 111: init(), getaf(), getqf(), usage(), ! 112: noar(), sigdone(), done(), notfound(), ! 113: morefil(), cleanup(), install(), movefil(), ! 114: stats(), copyfil(), getdir(), match(), ! 115: bamatch(), phserr(), mesg(), longt(), ! 116: pmode(), select(), wrerr(), mksymtab(), ! 117: ml_file(), sputl(); ! 118: char *trim(), *trimslash(), *getname(); ! 119: ! 120: char *tempnam(); ! 121: char *ctime(); ! 122: long time(); ! 123: ! 124: int (*comfun)(); ! 125: ! 126: ! 127: ! 128: main(argc, argv) ! 129: int argc; ! 130: char **argv; ! 131: { ! 132: register int i; ! 133: register char *cp; ! 134: ! 135: for (i = 0; signum[i]; i++) ! 136: if (signal(signum[i], SIG_IGN) != SIG_IGN) ! 137: signal(signum[i], sigdone); ! 138: if (argc < 3) ! 139: usage(); ! 140: cp = argv[1]; ! 141: if (*cp == '-') /* skip a '-', make ar more like other commands */ ! 142: cp++; ! 143: for (; *cp; cp++) ! 144: { ! 145: switch (*cp) ! 146: { ! 147: case 'l': ! 148: case 'v': ! 149: case 'u': ! 150: case 'a': ! 151: case 'b': ! 152: case 'c': ! 153: case 'i': ! 154: case 's': ! 155: case 'o': ! 156: flg[*cp - 'a']++; ! 157: continue; ! 158: case 'r': ! 159: setcom(rcmd); ! 160: flg[*cp - 'a']++; ! 161: continue; ! 162: case 'd': ! 163: setcom(dcmd); ! 164: flg[*cp - 'a']++; ! 165: continue; ! 166: case 'x': ! 167: setcom(xcmd); ! 168: flg[*cp - 'a']++; ! 169: continue; ! 170: case 't': ! 171: setcom(tcmd); ! 172: flg[*cp - 'a']++; ! 173: continue; ! 174: case 'p': ! 175: setcom(pcmd); ! 176: flg[*cp - 'a']++; ! 177: continue; ! 178: case 'm': ! 179: setcom(mcmd); ! 180: flg[*cp - 'a']++; ! 181: continue; ! 182: case 'q': ! 183: setcom(qcmd); ! 184: flg[*cp - 'a']++; ! 185: continue; ! 186: default: ! 187: fprintf(stderr, "ar: bad option `%c'\n", *cp); ! 188: done(1); ! 189: } ! 190: } ! 191: if (flg['l' - 'a']) ! 192: tmpdir = "."; /* use local directory for temp files */ ! 193: if (flg['i' - 'a']) ! 194: flg['b' - 'a']++; ! 195: if (flg['a' - 'a'] || flg['b' - 'a']) ! 196: { ! 197: bastate = 1; ! 198: ponam = trim(argv[2]); ! 199: argv++; ! 200: argc--; ! 201: if (argc < 3) ! 202: usage(); ! 203: } ! 204: arnam = argv[2]; ! 205: namv = argv + 3; ! 206: namc = argc - 3; ! 207: if (comfun == 0) ! 208: { ! 209: if (flg['u' - 'a'] == 0) ! 210: { ! 211: fprintf(stderr, ! 212: "ar: one of [%s] must be specified\n", man); ! 213: done(1); ! 214: } ! 215: setcom(rcmd); ! 216: } ! 217: update = (flg['d' - 'a'] | flg['q' - 'a'] | flg['m' - 'a'] | ! 218: flg['r' - 'a'] | flg['u' - 'a'] | flg['s' - 'a']); ! 219: (*comfun)(); ! 220: if (update) /* make archive symbol table */ ! 221: mksymtab(); ! 222: done(notfound()); ! 223: } ! 224: ! 225: ! 226: ! 227: setcom(fun) ! 228: int (*fun)(); ! 229: { ! 230: ! 231: if (comfun != 0) ! 232: { ! 233: fprintf(stderr, "ar: only one of [%s] allowed\n", man); ! 234: done(1); ! 235: } ! 236: comfun = fun; ! 237: } ! 238: ! 239: ! 240: ! 241: rcmd() ! 242: { ! 243: register int f; ! 244: ! 245: init(); ! 246: getaf(); ! 247: while (!getdir()) ! 248: { ! 249: bamatch(); ! 250: if (namc == 0 || match()) ! 251: { ! 252: f = stats(); ! 253: if (f < 0) ! 254: { ! 255: if (namc) ! 256: fprintf(stderr, ! 257: "ar: cannot open %s\n", file); ! 258: goto cp; ! 259: } ! 260: if (flg['u' - 'a']) ! 261: if (stbuf.st_mtime <= arbuf.ar_date) ! 262: { ! 263: close(f); ! 264: goto cp; ! 265: } ! 266: mesg('r'); ! 267: copyfil(af, -1, IODD + SKIP); ! 268: movefil(f); ! 269: continue; ! 270: } ! 271: cp: ! 272: mesg('c'); ! 273: copyfil(af, tf, IODD + OODD + HEAD); ! 274: } ! 275: cleanup(); ! 276: } ! 277: ! 278: ! 279: ! 280: ! 281: dcmd() ! 282: { ! 283: init(); ! 284: if (getaf()) ! 285: noar(); ! 286: while (!getdir()) ! 287: { ! 288: if (match()) ! 289: { ! 290: mesg('d'); ! 291: copyfil(af, -1, IODD + SKIP); ! 292: continue; ! 293: } ! 294: mesg('c'); ! 295: copyfil(af, tf, IODD + OODD + HEAD); ! 296: } ! 297: install(); ! 298: } ! 299: ! 300: ! 301: ! 302: ! 303: xcmd() ! 304: { ! 305: register int f; ! 306: ! 307: if (getaf()) ! 308: noar(); ! 309: while (!getdir()) ! 310: { ! 311: if (namc == 0 || match()) ! 312: { ! 313: f = creat(file, arbuf.ar_mode & 0777); ! 314: if (f < 0) ! 315: { ! 316: fprintf(stderr, "ar: %s cannot create\n", file); ! 317: goto sk; ! 318: } ! 319: mesg('x'); ! 320: copyfil(af, f, IODD); ! 321: close(f); ! 322: if(flg['o'-'a']) { ! 323: long timep[2]; ! 324: timep[0] = arbuf.ar_date; ! 325: timep[1] = arbuf.ar_date; ! 326: utime(file, timep); ! 327: } ! 328: continue; ! 329: } ! 330: sk: ! 331: mesg('c'); ! 332: copyfil(af, -1, IODD + SKIP); ! 333: if (namc > 0 && !morefil()) ! 334: done(0); ! 335: } ! 336: } ! 337: ! 338: ! 339: ! 340: ! 341: pcmd() ! 342: { ! 343: if (getaf()) ! 344: noar(); ! 345: while (!getdir()) ! 346: { ! 347: if (namc == 0 || match()) ! 348: { ! 349: if (flg['v' - 'a']) ! 350: { ! 351: fprintf(stdout, "\n<%s>\n\n", file); ! 352: fflush(stdout); ! 353: } ! 354: copyfil(af, 1, IODD); ! 355: continue; ! 356: } ! 357: copyfil(af, -1, IODD + SKIP); ! 358: } ! 359: } ! 360: ! 361: ! 362: ! 363: ! 364: mcmd() ! 365: { ! 366: init(); ! 367: if (getaf()) ! 368: noar(); ! 369: tf2nam = tempnam(tmpdir, "ar"); ! 370: close(creat(tf2nam, 0600)); ! 371: tf2 = open(tf2nam, 2); ! 372: if (tf2 < 0) ! 373: { ! 374: fprintf(stderr, "ar: cannot create third temp\n"); ! 375: done(1); ! 376: } ! 377: while (!getdir()) ! 378: { ! 379: bamatch(); ! 380: if (match()) ! 381: { ! 382: mesg('m'); ! 383: copyfil(af, tf2, IODD + OODD + HEAD); ! 384: continue; ! 385: } ! 386: mesg('c'); ! 387: copyfil(af, tf, IODD + OODD + HEAD); ! 388: } ! 389: install(); ! 390: } ! 391: ! 392: ! 393: ! 394: ! 395: tcmd() ! 396: { ! 397: if (getaf()) ! 398: noar(); ! 399: while (!getdir()) ! 400: { ! 401: if (namc == 0 || match()) ! 402: { ! 403: if (flg['v' - 'a']) ! 404: longt(); ! 405: fprintf(stdout, "%s\n", trim(file)); ! 406: } ! 407: copyfil(af, -1, IODD + SKIP); ! 408: } ! 409: } ! 410: ! 411: ! 412: ! 413: ! 414: qcmd() ! 415: { ! 416: register int i, f; ! 417: char *tmpfilname; ! 418: int n; ! 419: int mode=0644; ! 420: ! 421: if (flg['a' - 'a'] || flg['b' - 'a']) ! 422: { ! 423: fprintf(stderr, "ar: abi not allowed with q\n"); ! 424: done(1); ! 425: } ! 426: getqf(); ! 427: tmpfilname = tempnam(tmpdir, "ar"); ! 428: close(creat(tmpfilname, 0600)); ! 429: tf = open(tmpfilname, 2); ! 430: if (tf < 0) ! 431: { ! 432: fprintf(stderr, "ar: cannot create temp file\n"); ! 433: done(1); ! 434: } ! 435: lseek(qf, 0l, 0); ! 436: while ((n = read(qf, buf, BUFSIZ)) > 0) ! 437: if (write(tf, buf, n) != n) ! 438: wrerr; ! 439: for (i = 0; signum[i]; i++) ! 440: signal(signum[i], SIG_IGN); ! 441: lseek(tf, 0l, 2); ! 442: for (i = 0; i < namc; i++) ! 443: { ! 444: file = namv[i]; ! 445: if (file == 0) ! 446: continue; ! 447: namv[i] = 0; ! 448: mesg('q'); ! 449: f = stats(); ! 450: if (f < 0) ! 451: { ! 452: fprintf(stderr, "ar: %s cannot open\n", file); ! 453: continue; ! 454: } ! 455: movefil(f); ! 456: } ! 457: lseek(tf, 0l, 0); ! 458: lseek(qf, 0l, 0); ! 459: while ((n = read(tf, buf, BUFSIZ)) > 0) ! 460: if (write(qf, buf, n) != n) ! 461: wrerr; ! 462: } ! 463: ! 464: ! 465: ! 466: ! 467: init() ! 468: { ! 469: tfnam = tempnam(tmpdir, "ar"); ! 470: close(creat(tfnam, 0600)); ! 471: tf = open(tfnam, 2); ! 472: if (tf < 0) ! 473: { ! 474: fprintf(stderr, "ar: cannot create temp file\n"); ! 475: done(1); ! 476: } ! 477: if (write(tf, ARMAG, sizeof(char) * SARMAG) != sizeof(char) * SARMAG) ! 478: wrerr(); ! 479: } ! 480: ! 481: ! 482: ! 483: ! 484: getaf() ! 485: { ! 486: char buf[SARMAG + 1]; ! 487: long home; ! 488: ! 489: af = open(arnam, 0); ! 490: if (af < 0) ! 491: return (1); ! 492: if (read(af, buf, sizeof(char) * SARMAG) != sizeof(char) * SARMAG || ! 493: strncmp(buf, ARMAG, SARMAG)) ! 494: { ! 495: fprintf(stderr, "ar: %s not in archive format\n", arnam); ! 496: done(1); ! 497: } ! 498: /* ! 499: * If the first entry is the symbol directory, skip it ! 500: */ ! 501: home = lseek(af, 0L, 1); ! 502: if (!getdir() && file[0] == '\0') ! 503: { ! 504: copyfil(af, -1, IODD + SKIP); ! 505: return (0); ! 506: } ! 507: /* ! 508: * Otherwise, get back to beginning of first file header ! 509: */ ! 510: if (lseek(af, home, 0) < 0) ! 511: { ! 512: fprintf(stderr, "ar: %s cannot seek\n", arnam); ! 513: done(1); ! 514: } ! 515: return (0); ! 516: } ! 517: ! 518: ! 519: ! 520: ! 521: getqf() ! 522: { ! 523: char buf[SARMAG + 1]; ! 524: ! 525: if ((qf = open(arnam, 2)) < 0) /* a new archive */ ! 526: { ! 527: if (!flg['c' - 'a']) ! 528: fprintf(stderr, "ar: creating %s\n", arnam); ! 529: close(creat(arnam, 0666)); ! 530: if ((qf = open(arnam, 2)) < 0) ! 531: { ! 532: fprintf(stderr, "ar: cannot create %s\n", arnam); ! 533: done(1); ! 534: } ! 535: if (write(qf, ARMAG, sizeof(char) * SARMAG) != ! 536: sizeof(char) * SARMAG) ! 537: { ! 538: wrerr(); ! 539: } ! 540: } ! 541: else if (read(qf, buf, sizeof(char) * SARMAG) != ! 542: sizeof(char) * SARMAG || strncmp(buf, ARMAG, SARMAG)) ! 543: { ! 544: fprintf(stderr, "ar: %s not in archive format\n", arnam); ! 545: done(1); ! 546: } ! 547: return (0); ! 548: } ! 549: ! 550: ! 551: ! 552: ! 553: usage() ! 554: { ! 555: fprintf(stderr, "usage: ar [%s][%s] [posname] archive files ...\n", ! 556: man, opt); ! 557: done(1); ! 558: } ! 559: ! 560: ! 561: ! 562: ! 563: noar() ! 564: { ! 565: fprintf(stderr, "ar: %s does not exist\n", arnam); ! 566: done(1); ! 567: } ! 568: ! 569: ! 570: ! 571: ! 572: sigdone() ! 573: { ! 574: done(100); ! 575: } ! 576: ! 577: ! 578: ! 579: ! 580: done(c) ! 581: int c; ! 582: { ! 583: if (tfnam) ! 584: unlink(tfnam); ! 585: if (tf1nam) ! 586: unlink(tf1nam); ! 587: if (tf2nam) ! 588: unlink(tf2nam); ! 589: exit(c); ! 590: } ! 591: ! 592: ! 593: ! 594: ! 595: notfound() ! 596: { ! 597: register int i, n; ! 598: ! 599: n = 0; ! 600: for (i = 0; i < namc; i++) ! 601: if (namv[i]) ! 602: { ! 603: fprintf(stderr, "ar: %s not found\n", namv[i]); ! 604: n++; ! 605: } ! 606: return (n); ! 607: } ! 608: ! 609: ! 610: ! 611: ! 612: morefil() ! 613: { ! 614: register int i, n; ! 615: ! 616: n = 0; ! 617: for (i = 0; i < namc; i++) ! 618: if (namv[i]) ! 619: n++; ! 620: return (n); ! 621: } ! 622: ! 623: ! 624: ! 625: ! 626: cleanup() ! 627: { ! 628: register int i, f; ! 629: ! 630: for (i = 0; i < namc; i++) ! 631: { ! 632: file = namv[i]; ! 633: if (file == 0) ! 634: continue; ! 635: namv[i] = 0; ! 636: mesg('a'); ! 637: f = stats(); ! 638: if (f < 0) ! 639: { ! 640: fprintf(stderr, "ar: %s cannot open\n", file); ! 641: continue; ! 642: } ! 643: movefil(f); ! 644: } ! 645: install(); ! 646: } ! 647: ! 648: ! 649: ! 650: ! 651: install() ! 652: { ! 653: register int i; ! 654: ! 655: for (i = 0; signum[i]; i++) ! 656: signal(signum[i], SIG_IGN); ! 657: if (af < 0) ! 658: { ! 659: if (!flg['c' - 'a']) ! 660: fprintf(stderr, "ar: creating %s\n", arnam); ! 661: } ! 662: close(af); ! 663: af = creat(arnam, 0666); ! 664: if (af < 0) ! 665: { ! 666: fprintf(stderr, "ar: cannot create %s\n", arnam); ! 667: done(1); ! 668: } ! 669: if (tfnam) ! 670: { ! 671: lseek(tf, 0l, 0); ! 672: while ((i = read(tf, buf, BUFSIZ)) > 0) ! 673: if (write(af, buf, i) != i) ! 674: wrerr(); ! 675: } ! 676: if (tf2nam) ! 677: { ! 678: lseek(tf2, 0l, 0); ! 679: while ((i = read(tf2, buf, BUFSIZ)) > 0) ! 680: if (write(af, buf, i) != i) ! 681: wrerr(); ! 682: } ! 683: if (tf1nam) ! 684: { ! 685: lseek(tf1, 0l, 0); ! 686: while ((i = read(tf1, buf, BUFSIZ)) > 0) ! 687: if (write(af, buf, i) != i) ! 688: wrerr(); ! 689: } ! 690: } ! 691: ! 692: ! 693: ! 694: /* ! 695: * insert the file 'file' into the temporary file ! 696: */ ! 697: movefil(f) ! 698: int f; ! 699: { ! 700: (void)strcpy(arbuf.ar_name, trim(file)); ! 701: arbuf.ar_size = stbuf.st_size; ! 702: arbuf.ar_date = stbuf.st_mtime; ! 703: arbuf.ar_uid = stbuf.st_uid; ! 704: arbuf.ar_gid = stbuf.st_gid; ! 705: arbuf.ar_mode = stbuf.st_mode; ! 706: copyfil(f, tf, OODD + HEAD); ! 707: close(f); ! 708: } ! 709: ! 710: ! 711: ! 712: stats() ! 713: { ! 714: register int f; ! 715: ! 716: f = open(file, 0); ! 717: if (f < 0) ! 718: return(f); ! 719: if (fstat(f, &stbuf) < 0) ! 720: { ! 721: close(f); ! 722: return(-1); ! 723: } ! 724: return (f); ! 725: } ! 726: ! 727: ! 728: ! 729: ! 730: /* ! 731: * copy next file size given in arbuf ! 732: */ ! 733: copyfil(fin, fout, flag) ! 734: int fin, fout, flag; ! 735: { ! 736: register int i, o; ! 737: int pe; ! 738: int c; ! 739: ! 740: if (flag & HEAD) ! 741: { ! 742: char buf[sizeof(ariobuf) + 1]; ! 743: ! 744: #ifndef sun ! 745: if ( ! 746: #endif sun ! 747: sprintf(buf, "%-16s%-12ld%-6u%-6u%-8o%-10ld%-2s", ! 748: trimslash(file), arbuf.ar_date, arbuf.ar_uid, ! 749: arbuf.ar_gid, arbuf.ar_mode, arbuf.ar_size, ! 750: ARFMAG) ! 751: #if sun ! 752: ; ! 753: #else ! 754: != sizeof(ariobuf)) ! 755: { ! 756: fprintf(stderr, ! 757: "ar: %s internal header generation error\n", ! 758: arnam); ! 759: done(1); ! 760: } ! 761: #endif sun ! 762: (void)strncpy((char *)&ariobuf, buf, sizeof(ariobuf)); ! 763: if (write(fout, &ariobuf, sizeof(ariobuf)) != sizeof(ariobuf)) ! 764: wrerr(); ! 765: } ! 766: pe = 0; ! 767: while (arbuf.ar_size > 0) ! 768: { ! 769: i = o = BUFSIZ; ! 770: if (arbuf.ar_size < i) ! 771: { ! 772: i = o = arbuf.ar_size; ! 773: if (i & 1) ! 774: { ! 775: buf[i] = '\n'; ! 776: if (flag & IODD) ! 777: i++; ! 778: if (flag & OODD) ! 779: o++; ! 780: } ! 781: } ! 782: if (read(fin, buf, i) != i) ! 783: pe++; ! 784: if ((flag & SKIP) == 0) ! 785: if (write(fout, buf, o) != o) ! 786: wrerr(); ! 787: arbuf.ar_size -= BUFSIZ; ! 788: } ! 789: if (pe) ! 790: phserr(); ! 791: } ! 792: ! 793: ! 794: ! 795: ! 796: getdir() ! 797: { ! 798: register char *cp; ! 799: register int i; ! 800: ! 801: i = read(af, (char *)&ariobuf, sizeof(ariobuf)); ! 802: if (i != sizeof(ariobuf)) ! 803: { ! 804: if (tf1nam) ! 805: { ! 806: i = tf; ! 807: tf = tf1; ! 808: tf1 = i; ! 809: } ! 810: return (1); ! 811: } ! 812: if (strncmp(ariobuf.ar_fmag, ARFMAG, sizeof(ariobuf.ar_fmag))) ! 813: { ! 814: fprintf(stderr, "ar: malformed archive (at %ld)\n", ! 815: lseek(af, 0L, 1)); ! 816: done(1); ! 817: } ! 818: cp = ariobuf.ar_name + sizeof(ariobuf.ar_name); ! 819: while (*--cp == ' ') ! 820: ; ! 821: if (*cp == '/') ! 822: *cp = '\0'; ! 823: else ! 824: *++cp = '\0'; ! 825: file = strcpy(name, ariobuf.ar_name); ! 826: (void)strncpy(arbuf.ar_name, name, sizeof(arbuf.ar_name)); ! 827: if (sscanf(ariobuf.ar_date, "%ld", &arbuf.ar_date) != 1 || ! 828: sscanf(ariobuf.ar_uid, "%d", &arbuf.ar_uid) != 1 || ! 829: sscanf(ariobuf.ar_gid, "%d", &arbuf.ar_gid) != 1 || ! 830: sscanf(ariobuf.ar_mode, "%o", &arbuf.ar_mode) != 1 || ! 831: sscanf(ariobuf.ar_size, "%ld", &arbuf.ar_size) != 1) ! 832: { ! 833: fprintf(stderr, "ar: %s bad header layout for %s\n", ! 834: arnam, name); ! 835: done(1); ! 836: } ! 837: return (0); ! 838: } ! 839: ! 840: ! 841: ! 842: ! 843: match() ! 844: { ! 845: register int i; ! 846: ! 847: for (i = 0; i < namc; i++) ! 848: { ! 849: if (namv[i] == 0) ! 850: continue; ! 851: if (strcmp(trim(namv[i]), file) == 0) ! 852: { ! 853: file = namv[i]; ! 854: namv[i] = 0; ! 855: return (1); ! 856: } ! 857: } ! 858: return (0); ! 859: } ! 860: ! 861: ! 862: ! 863: ! 864: bamatch() ! 865: { ! 866: register int f; ! 867: ! 868: switch (bastate) ! 869: { ! 870: case 1: ! 871: if (strcmp(file, ponam) != 0) ! 872: return; ! 873: bastate = 2; ! 874: if (flg['a' - 'a']) ! 875: return; ! 876: case 2: ! 877: bastate = 0; ! 878: tf1nam = tempnam(tmpdir, "ar"); ! 879: close(creat(tf1nam, 0600)); ! 880: f = open(tf1nam, 2); ! 881: if (f < 0) ! 882: { ! 883: fprintf(stderr, "ar: cannot create second temp\n"); ! 884: return; ! 885: } ! 886: tf1 = tf; ! 887: tf = f; ! 888: } ! 889: } ! 890: ! 891: ! 892: ! 893: ! 894: phserr() ! 895: { ! 896: fprintf(stderr, "ar: phase error on %s\n", file); ! 897: done(1); ! 898: } ! 899: ! 900: ! 901: ! 902: ! 903: mesg(c) ! 904: int c; ! 905: { ! 906: if (flg['v' - 'a']) ! 907: if (c != 'c' || flg['v' - 'a'] > 1) ! 908: fprintf(stdout, "%c - %s\n", c, file); ! 909: } ! 910: ! 911: ! 912: ! 913: ! 914: char * ! 915: trimslash(s) ! 916: char *s; ! 917: { ! 918: static char buf[sizeof(arbuf.ar_name)]; ! 919: ! 920: (void)strncpy(buf, trim(s), sizeof(arbuf.ar_name) - 2); ! 921: buf[sizeof(arbuf.ar_name) - 2] = '\0'; ! 922: return (strcat(buf, "/")); ! 923: } ! 924: ! 925: ! 926: char * ! 927: trim(s) ! 928: char *s; ! 929: { ! 930: register char *p1, *p2; ! 931: ! 932: for (p1 = s; *p1; p1++) ! 933: ; ! 934: while (p1 > s) ! 935: { ! 936: if (*--p1 != '/') ! 937: break; ! 938: *p1 = 0; ! 939: } ! 940: p2 = s; ! 941: for (p1 = s; *p1; p1++) ! 942: if (*p1 == '/') ! 943: p2 = p1 + 1; ! 944: return (p2); ! 945: } ! 946: ! 947: ! 948: ! 949: ! 950: longt() ! 951: { ! 952: register char *cp; ! 953: ! 954: pmode(); ! 955: fprintf(stdout, "%6d/%6d", arbuf.ar_uid, arbuf.ar_gid); ! 956: fprintf(stdout, "%7ld", arbuf.ar_size); ! 957: cp = ctime(&arbuf.ar_date); ! 958: fprintf(stdout, " %-12.12s %-4.4s ", cp + 4, cp + 20); ! 959: } ! 960: ! 961: ! 962: ! 963: ! 964: pmode() ! 965: { ! 966: register int **mp; ! 967: ! 968: for (mp = &m[0]; mp < &m[9];) ! 969: select(*mp++); ! 970: } ! 971: ! 972: ! 973: ! 974: ! 975: select(pairp) ! 976: int *pairp; ! 977: { ! 978: register int n, *ap; ! 979: ! 980: ap = pairp; ! 981: n = *ap++; ! 982: while (--n >= 0 && (arbuf.ar_mode & *ap++) == 0) ! 983: ap++; ! 984: putchar(*ap); ! 985: } ! 986: ! 987: ! 988: ! 989: ! 990: wrerr() ! 991: { ! 992: perror("ar write error"); ! 993: done(1); ! 994: } ! 995: ! 996: ! 997: ! 998: ! 999: mksymtab() ! 1000: { ! 1001: int i, j, offset; ! 1002: struct syment symbol; /* usable copy of a symbol entry */ ! 1003: char buf[sizeof(ariobuf) + 1]; ! 1004: ! 1005: if (getaf()) ! 1006: { ! 1007: fprintf(stderr, "ar: cannot make symbol directory\n"); ! 1008: done(1); ! 1009: } ! 1010: nsyms = 0; ! 1011: mem_ptr = sizeof(char) * SARMAG; ! 1012: mem_skip = lseek(af, 0L, 1) - mem_ptr; ! 1013: while (!getdir()) ! 1014: { ! 1015: /* ! 1016: * scan machine language file members for symbols ! 1017: */ ! 1018: if (i = ml_file()) /* read the symbol table */ ! 1019: { ! 1020: while (i > 0) ! 1021: { ! 1022: i--; ! 1023: if (read(af, (char *)&symbol, SYMESZ) != SYMESZ) ! 1024: { ! 1025: fprintf(stderr, "ar: internal error, archive %s out of order!\n", ! 1026: arnam); ! 1027: done(1); ! 1028: } ! 1029: /* ! 1030: * check out symbol, is it ! 1031: * text, data, bss or common ! 1032: */ ! 1033: if ((symbol.n_scnum > 0 && /* defined */ ! 1034: symbol.n_sclass == C_EXT) || ! 1035: (symbol.n_scnum == 0 && /* common */ ! 1036: symbol.n_sclass == C_EXT && ! 1037: symbol.n_value != 0)) ! 1038: { ! 1039: sym_ptr[nsyms] = mem_ptr; ! 1040: sym_name[nsyms] = getname(&symbol); ! 1041: if (++nsyms > TABSZ) /* too many! */ ! 1042: { ! 1043: fprintf(stderr, "ar: too many external symbols\n"); ! 1044: done(1); ! 1045: } ! 1046: } ! 1047: /* ! 1048: * skip over any auxilliary entries ! 1049: */ ! 1050: j = symbol.n_numaux; ! 1051: while (j) ! 1052: { ! 1053: j--; ! 1054: i--; ! 1055: if (read(af, (char *)&symbol, SYMESZ) ! 1056: != SYMESZ) ! 1057: { ! 1058: fprintf(stderr, "ar: internal error, archive %s out of order!\n", ! 1059: arnam); ! 1060: done(1); ! 1061: } ! 1062: } ! 1063: } ! 1064: /* ! 1065: * Be careful with odd length .o files (now possible) ! 1066: */ ! 1067: mem_ptr += ((arbuf.ar_size + 1) & ~01) + sizeof(struct ar_hdr); ! 1068: /* ! 1069: * Skip string table (if any) ! 1070: */ ! 1071: if (lseek(af, mem_ptr + mem_skip, 0) < 0) ! 1072: { ! 1073: fprintf(stderr, ! 1074: "ar: %s cannot skip string table for %s\n", ! 1075: arnam, file); ! 1076: done(1); ! 1077: } ! 1078: } ! 1079: } ! 1080: /* ! 1081: * rewrite the archive to include the symbol directory ! 1082: */ ! 1083: close(af); ! 1084: /* ! 1085: * clean up the garbage that may have been left around ! 1086: */ ! 1087: unlink(tfnam); ! 1088: tfnam = 0; ! 1089: unlink(tf1nam); ! 1090: tf1nam = 0; ! 1091: unlink(tf2nam); ! 1092: tf2nam = 0; ! 1093: init(); /* rewrite the archive header */ ! 1094: /* ! 1095: * patch up archive pointers and write the symbol entries ! 1096: */ ! 1097: if ((str_top - str_base) & 01) /* round up string table */ ! 1098: *++str_top = '\0'; ! 1099: offset = (nsyms + 1) * sizeof(sym_offsets[0]) + ! 1100: sizeof(char) * (str_top - str_base) + sizeof(struct ar_hdr); ! 1101: for (i = 0; i < nsyms; i++) ! 1102: { ! 1103: sym_ptr[i] += offset; ! 1104: sputl(sym_ptr[i], sym_offsets[i]); ! 1105: } ! 1106: if (nsyms > 0) ! 1107: { ! 1108: sputl(nsyms, sym_nsyms); ! 1109: #ifndef sun ! 1110: if ( ! 1111: #endif sun ! 1112: sprintf(buf, "%-16s%-12ld%-6u%-6u%-8o%-10ld%-2s", ! 1113: SYMDIRNAME, time(0), 0, 0, 0, ! 1114: (long)(offset - sizeof(struct ar_hdr)), ARFMAG) ! 1115: #if sun ! 1116: ; ! 1117: #else ! 1118: != sizeof(ariobuf)) ! 1119: { ! 1120: fprintf(stderr, ! 1121: "ar: %s internal header generation error\n", ! 1122: arnam); ! 1123: done(1); ! 1124: } ! 1125: #endif sun ! 1126: if (write(tf, buf, sizeof(ariobuf)) != sizeof(ariobuf) || ! 1127: write(tf, sym_nsyms, sizeof(sym_nsyms)) ! 1128: != sizeof(sym_nsyms) || write(tf, (char *)sym_offsets, ! 1129: nsyms * sizeof(sym_offsets[0])) ! 1130: != nsyms * sizeof(sym_offsets[0]) || ! 1131: write(tf, str_base, sizeof(char) * (str_top - str_base)) ! 1132: != sizeof(char) * (str_top - str_base)) ! 1133: { ! 1134: wrerr(); ! 1135: } ! 1136: } ! 1137: /* ! 1138: * copy the rest of the archive to finish up ! 1139: */ ! 1140: getaf(); /* skip past the old header */ ! 1141: while (!getdir()) ! 1142: copyfil(af, tf, IODD + OODD + HEAD); ! 1143: install(); ! 1144: } ! 1145: ! 1146: ! 1147: ! 1148: ! 1149: ml_file() ! 1150: { ! 1151: long save_size; ! 1152: ! 1153: /* ! 1154: * is this a recognizable machine language file ! 1155: * if so, then skip down to the beginning of the symbol table ! 1156: * function returns the number of symbol table entries ! 1157: * if not, then skip to the next file ! 1158: */ ! 1159: filenum++; ! 1160: if (arbuf.ar_size <= sizeof(ml_filhdr)) /* don't bother */ ! 1161: { ! 1162: copyfil(af, -1, IODD + SKIP); ! 1163: return (0); ! 1164: } ! 1165: /* ! 1166: * check the "magic" number ! 1167: */ ! 1168: if (read(af, (char *)&ml_filhdr, sizeof(ml_filhdr)) ! 1169: != sizeof(ml_filhdr)) ! 1170: { ! 1171: fprintf(stderr, ! 1172: "ar: internal error, archive %s out of order!\n",arnam); ! 1173: done(1); ! 1174: } ! 1175: switch (ml_filhdr.f_magic) ! 1176: { ! 1177: default: /* skip to the next archive file member */ ! 1178: /* beware of old format .o files (pre-5.0) */ ! 1179: if (ml_filhdr.f_magic == 0407 || ml_filhdr.f_magic == 0410) ! 1180: { ! 1181: fprintf(stderr, ! 1182: "ar: (warning) file %.16s in pre 5.0 format\n", ! 1183: arbuf.ar_name); ! 1184: } ! 1185: skip_it:; ! 1186: save_size = arbuf.ar_size; ! 1187: arbuf.ar_size -= sizeof(ml_filhdr); ! 1188: copyfil(af, -1, IODD + SKIP); ! 1189: arbuf.ar_size = save_size; ! 1190: return (0); ! 1191: case B16MAGIC: ! 1192: case BTVMAGIC: ! 1193: case X86MAGIC: ! 1194: case XTVMAGIC: ! 1195: case N3BMAGIC: ! 1196: case NTVMAGIC: ! 1197: case FBOMAGIC: ! 1198: case RBOMAGIC: ! 1199: case MTVMAGIC: ! 1200: case VAXWRMAGIC: ! 1201: case VAXROMAGIC: ! 1202: case XLMAGIC: ! 1203: case MC68MAGIC: ! 1204: case MC68TVMAGIC: ! 1205: case M68MAGIC: ! 1206: case M68TVMAGIC: ! 1207: case U370WRMAGIC: ! 1208: case U370ROMAGIC: ! 1209: /* ! 1210: * skip to the beginning of the symbol table and return the ! 1211: * number of symbols in the table ! 1212: */ ! 1213: save_size = arbuf.ar_size; ! 1214: if (ml_filhdr.f_symptr < 0 || ml_filhdr.f_symptr > save_size) ! 1215: { ! 1216: #if unix && (u3b || u3b5) ! 1217: /* ! 1218: * Check for special case of sccs file. This type ! 1219: * of file looks like an object file on the 3b family. ! 1220: * The special numbers are the strings '^As 0' through ! 1221: * '^As 9' which are what can be found in an sccs file ! 1222: * on these machines. If the object file header is ! 1223: * changed, or the structure of sccs files is modified, ! 1224: * this code will no longer be valid. ! 1225: */ ! 1226: if (ml_filhdr.f_symptr >= 0x01732030 && /* in ascii */ ! 1227: ml_filhdr.f_symptr <= 0x01732039) ! 1228: { ! 1229: goto skip_it; /* don't bother with warning */ ! 1230: } ! 1231: #endif ! 1232: fprintf(stderr, "ar: (warning) file %.16s pretends to be an object file\n", ! 1233: arbuf.ar_name); ! 1234: goto skip_it; ! 1235: } ! 1236: arbuf.ar_size = ml_filhdr.f_symptr - sizeof(ml_filhdr); ! 1237: copyfil(af, -1, IODD + SKIP); ! 1238: arbuf.ar_size = save_size; ! 1239: return (ml_filhdr.f_nsyms); /* return the nbr of entries */ ! 1240: } ! 1241: } ! 1242: ! 1243: ! 1244: #define max(A,B) (((A) < (B)) ? (B) : (A)) ! 1245: ! 1246: extern char *malloc(), *realloc(), *getenv(), *mktemp(); ! 1247: extern void free(); ! 1248: extern int access(); ! 1249: static char *pcopy(), *seed="AAA"; ! 1250: ! 1251: ! 1252: ! 1253: char * ! 1254: tempnam(dir, pfx) ! 1255: char *dir; /* use this directory please (if non-NULL) */ ! 1256: char *pfx; /* use this (if non-NULL) as filename prefix */ ! 1257: { ! 1258: register char *p, *q, *tdir; ! 1259: int x = 0, y = 0, z; ! 1260: ! 1261: z = strlen(P_tmpdir); ! 1262: if ((tdir = getenv("TMPDIR")) != NULL) ! 1263: x = strlen(tdir); ! 1264: if (dir != NULL) ! 1265: y = strlen(dir); ! 1266: if ((p = malloc((unsigned)(max(max(x, y), z) + 16))) == NULL) ! 1267: return (NULL); ! 1268: if (x > 0 && access(pcopy(p, tdir), 3) == 0) ! 1269: goto OK; ! 1270: if (y > 0 && access(pcopy(p, dir), 3) == 0) ! 1271: goto OK; ! 1272: if (access(pcopy(p, P_tmpdir), 3) == 0) ! 1273: goto OK; ! 1274: if (access(pcopy(p, "/tmp"), 3) != 0) ! 1275: return (NULL); ! 1276: OK: ! 1277: (void)strcat(p, "/"); ! 1278: if (pfx) ! 1279: { ! 1280: *(p + strlen(p) + 5) = '\0'; ! 1281: (void)strncat(p, pfx, 5); ! 1282: } ! 1283: (void)strcat(p, seed); ! 1284: (void)strcat(p, "XXXXXX"); ! 1285: q = seed; ! 1286: while (*q == 'Z') ! 1287: *q++ = 'A'; ! 1288: ++*q; ! 1289: if (*mktemp(p) == '\0') ! 1290: return (NULL); ! 1291: return (p); ! 1292: } ! 1293: ! 1294: ! 1295: ! 1296: static char * ! 1297: pcopy(space, arg) ! 1298: char *space, *arg; ! 1299: { ! 1300: char *p; ! 1301: ! 1302: if (arg) ! 1303: { ! 1304: (void)strcpy(space, arg); ! 1305: p = space - 1 + strlen(space); ! 1306: if (*p == '/') ! 1307: *p = '\0'; ! 1308: } ! 1309: return (space); ! 1310: } ! 1311: ! 1312: ! 1313: ! 1314: char * ! 1315: getname(symbol) ! 1316: struct syment *symbol; ! 1317: { ! 1318: static int str_length = BUFSIZ * 5; ! 1319: #ifdef FLEXNAMES ! 1320: static int lastfilenum = 0; ! 1321: static char *strtab = NULL; ! 1322: static long strtablen = 0; ! 1323: #endif ! 1324: ! 1325: if (str_base == (char *)0) /* no space allocated yet */ ! 1326: { ! 1327: if ((str_base = malloc((unsigned)str_length)) == NULL) ! 1328: { ! 1329: fprintf(stderr, ! 1330: "ar: %s cannot get string table space\n", ! 1331: arnam); ! 1332: done(1); ! 1333: } ! 1334: str_top = str_base; ! 1335: } ! 1336: #ifdef FLEXNAMES ! 1337: if (symbol->n_zeroes == 0) /* symbol is in string table */ ! 1338: { ! 1339: char *p; ! 1340: register int i; ! 1341: ! 1342: if (lastfilenum != filenum || strtab == NULL) /* read it in */ ! 1343: { ! 1344: union ! 1345: { ! 1346: long l; ! 1347: char c[sizeof(long) / sizeof(char)]; ! 1348: } u; ! 1349: long home = lseek(af, 0L, 1); ! 1350: long len, len1; ! 1351: ! 1352: if (strtab != NULL) ! 1353: free(strtab); ! 1354: len = ml_filhdr.f_symptr + ml_filhdr.f_nsyms * SYMESZ; ! 1355: len1 = arbuf.ar_size - len; ! 1356: if (len1 < 4L) /* room for string table */ ! 1357: { ! 1358: fprintf(stderr, ! 1359: "ar: %s missing string table for %s\n", ! 1360: arnam, file); ! 1361: done(1); ! 1362: } ! 1363: len += sizeof(struct ar_hdr) + mem_ptr + mem_skip; ! 1364: if ((strtab = malloc((unsigned)len1)) == NULL || ! 1365: lseek(af, len, 0) < 0 || ! 1366: read(af, strtab, len1) != len1 || ! 1367: lseek(af, home, 0) < 0 || ! 1368: strtab[len1 - 1] != '\0') ! 1369: { ! 1370: fprintf(stderr, ! 1371: "ar: %s bad strings table for %s\n", ! 1372: arnam, file); ! 1373: done(1); ! 1374: } ! 1375: lastfilenum = filenum; ! 1376: for (i = 0; i < sizeof(u.c); i++) ! 1377: u.c[i] = strtab[i]; ! 1378: strtablen = u.l; ! 1379: } ! 1380: if (symbol->n_offset < 4 || symbol->n_offset >= strtablen) ! 1381: { ! 1382: fprintf(stderr, ! 1383: "ar: %s bad string table offset for %s\n", ! 1384: arnam, file); ! 1385: done(1); ! 1386: } ! 1387: p = str_top; ! 1388: str_top += strlen(strtab + symbol->n_offset) + 1; ! 1389: if (str_top > str_base + str_length) ! 1390: { ! 1391: char *old_base = str_base; ! 1392: int diff; ! 1393: ! 1394: str_length += BUFSIZ * 2; ! 1395: if ((str_base = realloc(str_base, str_length)) == NULL) ! 1396: { ! 1397: fprintf(stderr, ! 1398: "ar: %s cannot grow string table\n", ! 1399: arnam); ! 1400: done(1); ! 1401: } ! 1402: /* ! 1403: * Re-adjust other pointers ! 1404: */ ! 1405: diff = str_base - old_base; ! 1406: p += diff; ! 1407: str_top += diff; ! 1408: } ! 1409: (void)strcpy(p, strtab + symbol->n_offset); ! 1410: return (p); ! 1411: } ! 1412: else /* old COFF version - copy into string table */ ! 1413: #endif ! 1414: { ! 1415: register char *p, *s; ! 1416: register int i; ! 1417: ! 1418: if (str_top + SYMNMLEN >= str_base + str_length) ! 1419: { ! 1420: char *old_base = str_base; ! 1421: int diff; ! 1422: ! 1423: str_length += BUFSIZ * 2; ! 1424: if ((str_base = realloc(str_base, str_length)) == NULL) ! 1425: { ! 1426: fprintf(stderr, ! 1427: "ar: %s cannot grow string table\n", ! 1428: arnam); ! 1429: done(1); ! 1430: } ! 1431: /* ! 1432: * Re-adjust other pointers ! 1433: */ ! 1434: diff = str_base - old_base; ! 1435: p += diff; ! 1436: str_top += diff; ! 1437: } ! 1438: for (i = 0, p = str_top, s = symbol->n_name; ! 1439: i < SYMNMLEN && *s != '\0'; i++) ! 1440: { ! 1441: *p++ = *s++; ! 1442: } ! 1443: *p++ = '\0'; ! 1444: s = str_top; ! 1445: str_top = p; ! 1446: return (s); ! 1447: } ! 1448: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.