|
|
1.1 ! root 1: /* ! 2: * Archive manager. ! 3: * Also manages libraries for the ! 4: * link editor, ! 5: * including ranlib header updates. ! 6: */ ! 7: #define PORTAR 1 /* COFF frmat */ ! 8: ! 9: #ifdef COHERENT ! 10: #define SLASH '/' ! 11: #else ! 12: #define SLASH '\\' ! 13: #endif ! 14: ! 15: #include <stdlib.h> ! 16: #include <stdio.h> ! 17: #include <string.h> ! 18: #include <arcoff.h> ! 19: #include <ar.h> ! 20: #if !PORTAR ! 21: #include <canon.h> ! 22: #else ! 23: #include <coff.h> ! 24: #endif ! 25: #include <sys/types.h> ! 26: #include <sys/stat.h> ! 27: ! 28: #define RO 0 ! 29: #define RW 1 ! 30: ! 31: #define NONE 0 ! 32: #define BEFORE 1 ! 33: #define AFTER 2 ! 34: ! 35: #define ALLOK 0 ! 36: #define NOTALL 1 ! 37: #define ERROR 2 ! 38: ! 39: #define aechk() { if(ferror(afp)) ioerr(anp); } ! 40: #define techk() { if(ferror(tfp)) ioerr(tnp); } ! 41: ! 42: char nwork[] = "No work"; ! 43: char found[] = "found"; ! 44: char copen[] = "%s: cannot open"; ! 45: char ccrea[] = "%s: cannot create"; ! 46: char creop[] = "%s: cannot reopen"; ! 47: ! 48: FILE *afp; ! 49: FILE *tfp; ! 50: FILE *rfp; ! 51: #define DIRSIZ 14 ! 52: #if PORTAR ! 53: struct old_ar_hdr ahb; ! 54: char rnp[] = ""; ! 55: char rnpx[] = "SYMDEF.__"; ! 56: #else ! 57: #define SARMAG sizeof(short) ! 58: char rnp[] = HDRNAME; ! 59: char *rnpx = rnp; ! 60: struct ar_hdr ahb; ! 61: #endif ! 62: ! 63: int usage(); ! 64: long fsize(); ! 65: ! 66: long ranCt; /* count of ranlib entrys for coff */ ! 67: ! 68: int nname; ! 69: char **namep; ! 70: int cflag; ! 71: int kflag; ! 72: int lflag; ! 73: int sflag; ! 74: int uflag; ! 75: int vflag; ! 76: int xflag; ! 77: char *pnp; ! 78: char *anp; ! 79: char *tnp; ! 80: int xstat = ALLOK; ! 81: int pos = NONE; ! 82: int (*ffp)() = usage; ! 83: FILE *makeh(); ! 84: ! 85: char state[] = "'%s' file not found"; ! 86: ! 87: /* ! 88: * ar called as ranlib. ! 89: */ ! 90: ranlib(argv) ! 91: char *argv[]; ! 92: { ! 93: int rfunc(); ! 94: ! 95: ffp = rfunc; ! 96: ++sflag; ! 97: anp = argv[1]; ! 98: (*ffp)(); ! 99: delexit(xstat); ! 100: } ! 101: ! 102: main(argc, argv) ! 103: char *argv[]; ! 104: { ! 105: register i; ! 106: char *p; ! 107: int usage(), rfunc(); ! 108: ! 109: if (NULL == (p = strrchr(argv[0], SLASH))) ! 110: p = argv[0]; ! 111: else ! 112: p++; ! 113: ! 114: if (!strcmp(p, "ranlib")) ! 115: ranlib(argv); ! 116: ! 117: if (strcmp(p, "ar")) ! 118: diag(1, "called as %s, expecting ar, or ranlib", p); ! 119: ! 120: _addargs("AR", &argc, &argv); ! 121: if (argc < 2) ! 122: usage(); ! 123: key(argv[1]); ! 124: nname = argc - 2; ! 125: namep = &argv[2]; ! 126: for (i = 2; i < argc; ++i) { ! 127: if (pos != NONE && pnp == NULL) { ! 128: pnp = argv[i]; ! 129: ++namep; ! 130: --nname; ! 131: } else { ! 132: anp = argv[i]; ! 133: ++namep; ! 134: --nname; ! 135: break; ! 136: } ! 137: } ! 138: if (anp == NULL) ! 139: usage(); ! 140: if (pos != NONE) { ! 141: if (pnp == NULL) ! 142: usage(); ! 143: if (ffp == usage) ! 144: ffp = rfunc; ! 145: } ! 146: (*ffp)(); ! 147: delexit(xstat); ! 148: } ! 149: ! 150: /* ! 151: * Decode key. ! 152: * Save function name in 'ffp'. ! 153: * Set 'c', 'l', 'k' and 'v' flags. ! 154: */ ! 155: key(p) ! 156: register char *p; ! 157: { ! 158: register c; ! 159: int dfunc(), rfunc(), qfunc(), tfunc(); ! 160: int mfunc(), xfunc(), pfunc(); ! 161: ! 162: while (c = *p++) { ! 163: switch (c) { ! 164: ! 165: case 'd': /* Delete */ ! 166: ffp = dfunc; ! 167: break; ! 168: ! 169: case 'r': /* Replace */ ! 170: ffp = rfunc; ! 171: break; ! 172: ! 173: case 'q': /* Quick append */ ! 174: ffp = qfunc; ! 175: break; ! 176: ! 177: case 't': /* Tabulate */ ! 178: ffp = tfunc; ! 179: break; ! 180: ! 181: case 'p': /* Print */ ! 182: ffp = pfunc; ! 183: break; ! 184: ! 185: case 'm': /* Move */ ! 186: ffp = mfunc; ! 187: break; ! 188: ! 189: case 'x': /* Extract */ ! 190: ffp = xfunc; ! 191: ++xflag; ! 192: break; ! 193: ! 194: case 'c': /* no create message */ ! 195: ++cflag; ! 196: break; ! 197: ! 198: case 'k': /* keep dates */ ! 199: ++kflag; ! 200: break; ! 201: ! 202: case 'l': /* local temp file */ ! 203: ++lflag; ! 204: break; ! 205: ! 206: case 's': /* ranlib symbol table */ ! 207: ++sflag; ! 208: break; ! 209: ! 210: case 'u': /* update replace */ ! 211: ++uflag; ! 212: break; ! 213: ! 214: case 'v': /* verbose */ ! 215: ++vflag; ! 216: break; ! 217: ! 218: case 'a': /* after position or append */ ! 219: pos = AFTER; ! 220: break; ! 221: ! 222: case 'b': /* before position */ ! 223: case 'i': /* insert */ ! 224: pos = BEFORE; ! 225: break; ! 226: ! 227: default: ! 228: usage(); ! 229: } ! 230: } ! 231: } ! 232: ! 233: /* ! 234: * Seek forward for ahb.ar_size rounded up. ! 235: */ ! 236: static ! 237: seekPast() ! 238: { ! 239: long len; ! 240: ! 241: len = (ahb.ar_size + 1) & ~1; ! 242: fseek(afp, len, 1); ! 243: } ! 244: ! 245: /* ! 246: * Replace. ! 247: * Eliminate dead stuff if 'u'. ! 248: * Copy up to insert point. ! 249: * Copy in new files. ! 250: * Copy the rest of the file. ! 251: * Copy back. ! 252: */ ! 253: rfunc() ! 254: { ! 255: register char *qfn; ! 256: register i, nef; ! 257: FILE *qfp; ! 258: ! 259: if (nname == 0 && sflag == 0) ! 260: diag(1, nwork); ! 261: aopen(RW); /* open archive */ ! 262: ropen(); /* maybe open ranlib */ ! 263: if (uflag) { ! 264: update(); ! 265: fseek(afp, (long)SARMAG, 0); /* bypass magic */ ! 266: if (rfp != NULL) { ! 267: geth(); ! 268: if (eqh(rnp)) /* if SYMBOL header bypass */ ! 269: seekPast(); ! 270: else ! 271: fseek(afp, (long)SARMAG, 0); ! 272: } ! 273: } ! 274: topen(); /* open tmpfile */ ! 275: while (nef = geth()) { ! 276: if (pos==BEFORE && eqh(pnp)) { ! 277: fseek(afp, (long)-sizeof(struct ar_hdr), 1); ! 278: break; ! 279: } ! 280: if (pos == NONE) { ! 281: for (i=0; i<nname; ++i) { ! 282: if ((qfn=namep[i])!=NULL && eqh(qfn)) ! 283: break; ! 284: } ! 285: if (i != nname) { ! 286: seekPast(); ! 287: namep[i] = NULL; ! 288: remove(i, qfn); ! 289: qfp = makeh(qfn); ! 290: if (vflag) ! 291: printf("%s: in place replace.\n", qfn); ! 292: puth(tfp, tnp); ! 293: ffcopy(tfp, tnp, qfp, qfn, (long)ahb.ar_size); ! 294: fclose(qfp); ! 295: continue; ! 296: } ! 297: } ! 298: mmove(0); ! 299: if (pos==AFTER && eqh(pnp)) ! 300: break; ! 301: } ! 302: if (nef==0 && pos!=NONE) ! 303: diag(1, "%s: not in archive", pnp); ! 304: for (i=0; i<nname; ++i) { ! 305: if ((qfn=namep[i]) == NULL) ! 306: continue; ! 307: remove(i, qfn); ! 308: qfp = makeh(qfn); ! 309: if (vflag) ! 310: printf("%s: replaced.\n", qfn); ! 311: puth(tfp, tnp); ! 312: ffcopy(tfp, tnp, qfp, qfn, (long)ahb.ar_size); ! 313: fclose(qfp); ! 314: } ! 315: while (geth()) ! 316: mmove(0); ! 317: tacopy(); ! 318: } ! 319: ! 320: /* ! 321: * Handle the 'u' option. ! 322: * Read through the archive, comparing ! 323: * the dates in the headers to the last ! 324: * modification dates of the files in ! 325: * the command line. Make some files ! 326: * go away. ! 327: */ ! 328: update() ! 329: { ! 330: register char *p; ! 331: register i; ! 332: struct stat sb; ! 333: ! 334: while (geth()) { ! 335: for (i=0; i<nname; ++i) { ! 336: p = namep[i]; ! 337: if (p!=NULL && eqh(p)) { ! 338: if (stat(p, &sb) < 0) ! 339: diag(1, state, p); ! 340: if (ahb.ar_date >= sb.st_mtime) { ! 341: if (vflag) ! 342: printf("%s: no update.\n", p); ! 343: namep[i] = NULL; ! 344: remove(i, p); ! 345: } ! 346: } ! 347: } ! 348: seekPast(); ! 349: } ! 350: for (i=0; i<nname && namep[i]==NULL; ++i) ! 351: ; ! 352: if (i >= nname) { ! 353: if (vflag) ! 354: fprintf(stderr, "%s.\n", nwork); ! 355: delexit(ALLOK); ! 356: } ! 357: } ! 358: ! 359: /* ! 360: * Move. ! 361: * Copy stuff before insert. ! 362: * Copy moved stuff. ! 363: * Copy remainder. ! 364: * Copy back to archive. ! 365: */ ! 366: mfunc() ! 367: { ! 368: register nef; ! 369: long s; ! 370: ! 371: aopen(RW); ! 372: ropen(); ! 373: topen(); ! 374: while (nef = geth()) { ! 375: if (pos==BEFORE && eqh(pnp)) ! 376: break; ! 377: mmove(0); ! 378: if (pos==AFTER && eqh(pnp)) ! 379: break; ! 380: } ! 381: if (nef==0 && pos!=NONE) ! 382: diag(1, "%s: not in archive", pnp); ! 383: s = ftell(afp); ! 384: if (pos == BEFORE) ! 385: s -= sizeof(struct ar_hdr); ! 386: fseek(afp, (long)SARMAG, 0); ! 387: while (geth()) ! 388: mmove(1); ! 389: if (nef) { ! 390: fseek(afp, s, 0); ! 391: while (geth()) ! 392: mmove(0); ! 393: } ! 394: tacopy(); ! 395: } ! 396: ! 397: /* ! 398: * Conditional move to the ! 399: * temp file from the archive ! 400: * file. Used by move and replace ! 401: */ ! 402: mmove(f1) ! 403: register f1; ! 404: { ! 405: register f2, i; ! 406: register long size; ! 407: ! 408: f2 = 0; ! 409: for (i=0; i<nname; ++i) { ! 410: if (eqh(namep[i])) { ! 411: ++f2; ! 412: break; ! 413: } ! 414: } ! 415: if (f1 == f2) { ! 416: if (vflag) ! 417: amsg("copied"); ! 418: size = ahb.ar_size; ! 419: puth(tfp, tnp); ! 420: ffcopy(tfp, tnp, afp, anp, size); ! 421: } else { ! 422: if (vflag) ! 423: amsg("skipped"); ! 424: seekPast(); ! 425: } ! 426: } ! 427: ! 428: /* ! 429: * Print. ! 430: */ ! 431: pfunc() ! 432: { ! 433: aopen(RO); ! 434: while (geth()) { ! 435: if (nname==0 || match()) ! 436: pfile(); ! 437: else ! 438: seekPast(); ! 439: } ! 440: if (nname != 0) ! 441: notdone(found); ! 442: } ! 443: ! 444: pfile() ! 445: { ! 446: if (vflag) ! 447: amsg(NULL); ! 448: ffcopy(stdout, "Stdout", afp, anp, ahb.ar_size); ! 449: } ! 450: ! 451: /* ! 452: * Delete. ! 453: * Copy archive to temp, deleting ! 454: * members along the way. If all of ! 455: * the files have been deleted then ! 456: * copy back. ! 457: */ ! 458: dfunc() ! 459: { ! 460: register long size; ! 461: ! 462: if (nname == 0) ! 463: diag(1, nwork); ! 464: aopen(RW); ! 465: ropen(); ! 466: topen(); ! 467: while (geth()) { ! 468: if (match()) { ! 469: if (vflag) ! 470: amsg("deleted"); ! 471: seekPast(); ! 472: continue; ! 473: } ! 474: if (vflag) ! 475: amsg("copied"); ! 476: size = ahb.ar_size; ! 477: puth(tfp, tnp); ! 478: ffcopy(tfp, tnp, afp, anp, size); ! 479: } ! 480: if (notdone("deleted")) ! 481: delexit(ERROR); ! 482: tacopy(); ! 483: } ! 484: ! 485: /* ! 486: * Quick insert. ! 487: * Copy archive to temp file. ! 488: * Tack new files onto the end. ! 489: * If no errors, copy back. ! 490: */ ! 491: qfunc() ! 492: { ! 493: register char *qfn; ! 494: register FILE *qfp; ! 495: register i; ! 496: ! 497: if (nname == 0) ! 498: diag(1, nwork); ! 499: aopen(RW); ! 500: if (geth() != 0 && eqh(rnp)) { ! 501: fseek(afp, (long)-sizeof(ahb), 1); ! 502: ahb.ar_date = 0; ! 503: puth(afp, anp); ! 504: } ! 505: fseek(afp, (long)0, 2); ! 506: for (i=0; i<nname; ++i) { ! 507: if ((qfn=namep[i]) == NULL) ! 508: continue; ! 509: remove(i, qfn); ! 510: qfp = makeh(qfn); ! 511: if (vflag) ! 512: printf("%s: quick insert.\n", qfn); ! 513: puth(afp, anp); ! 514: ffcopy(afp, anp, qfp, qfn, (long)ahb.ar_size); ! 515: fclose(qfp); ! 516: } ! 517: } ! 518: ! 519: /* ! 520: * Table. ! 521: * Read through archive. ! 522: * If good member print its name. ! 523: * If verbose, print extra stuff. ! 524: */ ! 525: tfunc() ! 526: { ! 527: register char *p; ! 528: register c, n; ! 529: ! 530: aopen(RO); ! 531: while (geth()) { ! 532: if (nname==0 || match()) { ! 533: if (!*(p = ahb.ar_name)) { ! 534: seekPast(); ! 535: continue; ! 536: } ! 537: n = 0; ! 538: while (n<DIRSIZ && (c=*p++)) { ! 539: putchar(c); ! 540: ++n; ! 541: } ! 542: if (vflag) { ! 543: while (n++ < DIRSIZ+1) ! 544: putchar(' '); ! 545: #if COHERENT ! 546: printf("%5d %5d ", ahb.ar_gid, ahb.ar_uid); ! 547: printf("%03o ", ahb.ar_mode & 0777); ! 548: #endif ! 549: printf("%10ld ", ahb.ar_size); ! 550: printf("%s", ctime(&ahb.ar_date)); ! 551: } else ! 552: putchar('\n'); ! 553: } ! 554: seekPast(); ! 555: } ! 556: if (nname != 0) ! 557: notdone(found); ! 558: } ! 559: ! 560: /* ! 561: * Extract. ! 562: * Read through archive. ! 563: * Extract any files you find. ! 564: * At end, mutter about files ! 565: * that were not there. ! 566: */ ! 567: xfunc() ! 568: { ! 569: register char *p1, *p2; ! 570: register c; ! 571: char fnb[DIRSIZ+1]; ! 572: FILE *xfp; ! 573: ! 574: aopen(RO); ! 575: while (geth()) { ! 576: if (nname==0 || match()) { ! 577: if (!*(p1 = ahb.ar_name)) { ! 578: seekPast(); ! 579: continue; ! 580: } ! 581: p2 = fnb; ! 582: while (p1<&ahb.ar_name[DIRSIZ] && (c=*p1++)) ! 583: *p2++ = c; ! 584: *p2 = 0; ! 585: if ((xfp=fopen(fnb, "wb")) == NULL) { ! 586: diag(0, ccrea, fnb); ! 587: seekPast(); ! 588: continue; ! 589: } ! 590: if (vflag) ! 591: amsg("extracting"); ! 592: ffcopy(xfp, fnb, afp, anp, ahb.ar_size); ! 593: chmod(fnb, ahb.ar_mode); ! 594: ! 595: fclose(xfp); ! 596: if (kflag) { ! 597: time_t times[2]; ! 598: time_t time(); ! 599: ! 600: time(times+0); ! 601: times[1] = ahb.ar_date; ! 602: if (utime(fnb, times) < 0) ! 603: diag(0, "Unable to set time for %s", ! 604: fnb); ! 605: } ! 606: } else ! 607: seekPast(); ! 608: } ! 609: if (nname != 0) ! 610: notdone(found); ! 611: } ! 612: ! 613: /* ! 614: * Make an archive header. ! 615: * Put it in the external archive ! 616: * header buffer 'ahb'. The arg. ! 617: * 'fn' is the file name. The file ! 618: * is open on 'fp'. ! 619: */ ! 620: FILE * ! 621: makeh(fn) ! 622: char *fn; ! 623: { ! 624: FILE *fp; ! 625: char *p1; ! 626: ! 627: struct stat sb; ! 628: ! 629: #if GEMDOS ! 630: if (stat(fn, &sb) < 0) ! 631: diag(1, state, fn); ! 632: ! 633: if (NULL == (fp = fopen(fn, "rb"))) ! 634: diag(1, copen, fn); ! 635: #else ! 636: if (NULL == (fp = fopen(fn, "rb"))) ! 637: diag(1, copen, fn); ! 638: ! 639: if (fstat(fileno(fp), &sb) < 0) ! 640: diag(1, state, fn); ! 641: #endif ! 642: if (fn == rnpx) ! 643: fn = ""; ! 644: ! 645: if (NULL == (p1 = strrchr(fn, SLASH))) ! 646: p1 = fn - 1; ! 647: ! 648: strncpy(ahb.ar_name, p1 + 1, DIRSIZ); ! 649: ! 650: if (kflag) ! 651: ahb.ar_date = sb.st_mtime; ! 652: else ! 653: time(&ahb.ar_date); ! 654: ahb.ar_uid = sb.st_uid; ! 655: ahb.ar_gid = sb.st_gid; ! 656: ahb.ar_mode = sb.st_mode & 07777; ! 657: ahb.ar_size = sb.st_size; ! 658: ! 659: return (fp); ! 660: } ! 661: ! 662: /* ! 663: * Test if the member whose ! 664: * header is held in the archive ! 665: * header buffer is mentioned in ! 666: * the user's list of members. ! 667: * Return the number of matches. ! 668: * All matches are NULLed. ! 669: */ ! 670: match() ! 671: { ! 672: register char *p; ! 673: register i, n; ! 674: ! 675: n = 0; ! 676: for (i=0; i<nname; ++i) { ! 677: if ((p=namep[i]) == NULL) ! 678: continue; ! 679: if (eqh(p)) { ! 680: ++n; ! 681: namep[i] = NULL; ! 682: } ! 683: } ! 684: return (n); ! 685: } ! 686: ! 687: /* ! 688: * Remove all instances of name ! 689: * 'fn' from the list of names that ! 690: * is described by 'namep' and ! 691: * 'nname'. ! 692: * Start at index 'i+1'. ! 693: */ ! 694: remove(i, fn) ! 695: register i; ! 696: register char *fn; ! 697: { ! 698: register char *p; ! 699: ! 700: for (++i; i<nname; ++i) { ! 701: if ((p=namep[i]) == NULL) ! 702: continue; ! 703: if (strcmp(fn, p) == 0) ! 704: namep[i] = NULL; ! 705: } ! 706: } ! 707: ! 708: /* ! 709: * This routine digs through the ! 710: * list of names described by 'namep' ! 711: * and 'nname' looking for names that ! 712: * have not been NULLed out. If any ! 713: * are found it prints a title and ! 714: * the names. The number of names that ! 715: * were found is returned. ! 716: */ ! 717: notdone(s) ! 718: char *s; ! 719: { ! 720: register char *p; ! 721: register i, n; ! 722: ! 723: n = 0; ! 724: for (i=0; i<nname; ++i) { ! 725: p = namep[i]; ! 726: if (p != NULL) { ! 727: if (n++ == 0) ! 728: fprintf(stderr, "Not %s:\n", s); ! 729: fprintf(stderr, "%s\n", p); ! 730: } ! 731: } ! 732: return (n); ! 733: } ! 734: ! 735: /* ! 736: * File to file copy. ! 737: * With ranlib construction. ! 738: */ ! 739: ffcopy(tfp, tfn, ffp, ffn, s) ! 740: FILE *tfp, *ffp; ! 741: char *tfn, *ffn; ! 742: long s; ! 743: { ! 744: register n; ! 745: int pad; ! 746: static char fb[BUFSIZ]; ! 747: ! 748: if (rfp != NULL) ! 749: raddmod(tfp, ffp, s); ! 750: ! 751: pad = s & 1; ! 752: for (n = ftell(ffp) % BUFSIZ; s; (s -= n), (n = 0)) { ! 753: if ((n = BUFSIZ - n) > s) ! 754: n = s; ! 755: if (fread (fb, sizeof(char), n, ffp) != n) ! 756: ioerr(ffn); ! 757: if (fwrite(fb, sizeof(char), n, tfp) != n) ! 758: ioerr(tfn); ! 759: } ! 760: if (pad) { ! 761: fgetc(ffp); ! 762: if (!xflag) ! 763: fputc(0, tfp); ! 764: } ! 765: } ! 766: ! 767: /* ! 768: * Get the next archive header ! 769: * into 'ahb'. Check for any I/O ! 770: * errors. Return true if a header ! 771: * was read and false on EOF. ! 772: */ ! 773: geth() ! 774: { ! 775: #if PORTAR ! 776: struct ar_hdr hdr; ! 777: int uid, gid, mode; ! 778: register char *p; ! 779: ! 780: if (fread(&hdr, sizeof(hdr), 1, afp) != 1) { ! 781: aechk(); ! 782: return (0); ! 783: } ! 784: ! 785: memset(&ahb, '\0', sizeof(ahb)); ! 786: memcpy(ahb.ar_name, hdr.ar_name, DIRSIZ); ! 787: if (NULL != (p = strchr(ahb.ar_name, '/'))) ! 788: *p = '\0'; ! 789: ! 790: sscanf(hdr.ar_date, "%d %d %d %o %d", ! 791: &ahb.ar_date, &uid, &gid, &mode, &ahb.ar_size); ! 792: ahb.ar_uid = uid; /* use intermediate fields for shorts */ ! 793: ahb.ar_gid = gid; ! 794: ahb.ar_mode = mode & 07777; ! 795: ! 796: #else ! 797: if (fread(&ahb, sizeof(ahb), 1, afp) != 1) { ! 798: aechk(); ! 799: return (0); ! 800: } ! 801: cantime(ahb.ar_date); ! 802: canshort(ahb.ar_gid); ! 803: canshort(ahb.ar_uid); ! 804: canshort(ahb.ar_mode); ! 805: cansize(ahb.ar_size); ! 806: #endif ! 807: return (1); ! 808: } ! 809: ! 810: /* ! 811: * Write the header in 'ahb' to ! 812: * the temp file. ! 813: */ ! 814: puth(fp, np) ! 815: FILE *fp; ! 816: char *np; ! 817: { ! 818: #if PORTAR ! 819: struct ar_hdr hdr; ! 820: register i; ! 821: ! 822: sprintf(hdr.ar_date, "%-12ld%-6d%-6d%-8o%-10ld", ! 823: ahb.ar_date, ahb.ar_uid, ! 824: ahb.ar_gid, ahb.ar_mode & 07777, ahb.ar_size); ! 825: ! 826: memcpy(hdr.ar_fmag, ARFMAG, sizeof(hdr.ar_fmag)); ! 827: ! 828: for (i = 0; (i < DIRSIZ) && ahb.ar_name[i]; i++) ! 829: hdr.ar_name[i] = ahb.ar_name[i]; ! 830: hdr.ar_name[i++] = '/'; ! 831: for (; i < sizeof(hdr.ar_name); i++) ! 832: hdr.ar_name[i] = ' '; ! 833: ! 834: fwrite(&hdr, sizeof(hdr), 1, fp); ! 835: #else ! 836: cantime(ahb.ar_date); ! 837: canshort(ahb.ar_gid); ! 838: canshort(ahb.ar_uid); ! 839: canshort(ahb.ar_mode); ! 840: cansize(ahb.ar_size); ! 841: fwrite(&ahb, sizeof(ahb), 1, fp); ! 842: #endif ! 843: if(ferror(fp)) ! 844: ioerr(np); ! 845: } ! 846: ! 847: /* ! 848: * Compare a string to the name ! 849: * of the member in the archive header ! 850: * buffer. True return if same. ! 851: */ ! 852: eqh(p) ! 853: char *p; ! 854: { ! 855: register char *p1; ! 856: ! 857: if (NULL == (p1 = strrchr(p, SLASH))) ! 858: p1 = p; ! 859: else ! 860: p1++; ! 861: ! 862: return (!strncmp(p1, ahb.ar_name, DIRSIZ)); ! 863: } ! 864: ! 865: /* ! 866: * Open archive. ! 867: * The argument 'aam' is the ! 868: * access mode (RO or RW). ! 869: */ ! 870: aopen(aam) ! 871: { ! 872: #ifdef PORTAR ! 873: char buf[SARMAG]; ! 874: #else ! 875: int i; ! 876: #endif ! 877: ! 878: if ((afp=fopen(anp, "rb")) == NULL) { ! 879: if (aam == RO) ! 880: diag(1, copen, anp); ! 881: if ((afp=fopen(anp, "wb"))==NULL ! 882: || (afp=freopen(anp, "wrb", afp))==NULL) ! 883: diag(1, ccrea, anp); ! 884: if (cflag == 0) ! 885: printf("%s: new archive.\n", anp); ! 886: #if PORTAR ! 887: fputs(ARMAG, afp); ! 888: #else ! 889: i = ARMAG; ! 890: canint(i); ! 891: fwrite(&i, sizeof(i), 1, afp); ! 892: #endif ! 893: aechk(); ! 894: return; ! 895: } ! 896: if (aam != RO) { ! 897: fclose(afp); ! 898: if ((afp=fopen(anp, "rwb"))==NULL) ! 899: diag(1, copen, anp); ! 900: } ! 901: #if PORTAR ! 902: fread(buf, SARMAG, 1, afp); ! 903: aechk(); ! 904: if(memcmp(buf, ARMAG, SARMAG)) ! 905: #else ! 906: fread(&i, sizeof(i), 1, afp); ! 907: aechk(); ! 908: canint(i); ! 909: if (i != ARMAG) ! 910: #endif ! 911: diag(1, "%s: not an archive", anp); ! 912: } ! 913: ! 914: /* ! 915: * Open tempfile. ! 916: * Stash the name in 'tnp' for ! 917: * the benefit of 'delexit'. ! 918: * Honour the 'l' option w.r.t. ! 919: * file placement. ! 920: */ ! 921: topen() ! 922: { ! 923: int i; ! 924: ! 925: extern char *tempnam(); ! 926: tnp = tempnam((lflag ? "." : NULL), "v"); ! 927: ! 928: if ((tfp=fopen(tnp, "wb")) == NULL) ! 929: diag(1, ccrea, tnp); ! 930: #if PORTAR ! 931: fputs(ARMAG, tfp); ! 932: #else ! 933: i = ARMAG; ! 934: canint(i); ! 935: fwrite(&i, sizeof(i), 1, tfp); ! 936: #endif ! 937: techk(); ! 938: } ! 939: ! 940: /* ! 941: * Copy tempfile back to the ! 942: * archive. ! 943: */ ! 944: tacopy() ! 945: { ! 946: register FILE *xtp; ! 947: #if PORTAR ! 948: char buf[SARMAG]; ! 949: #else ! 950: int i; ! 951: #endif ! 952: ! 953: fclose(tfp); ! 954: tfp = NULL; /* Scare off delexit */ ! 955: fclose(afp); ! 956: if ((xtp=fopen(tnp, "rb")) == NULL) ! 957: diag(1, creop, tnp); ! 958: if ((afp=fopen(anp, "wb")) == NULL) ! 959: diag(1, creop, anp); ! 960: if (vflag) ! 961: printf("%s: copy back.\n", anp); ! 962: #if PORTAR ! 963: if (fread(buf, SARMAG, 1, xtp) != 1) ! 964: ioerr(tnp); ! 965: if (fwrite(buf, SARMAG, 1, afp) != 1) ! 966: ioerr(anp); ! 967: if (rfp != NULL) ! 968: rcopy(); ! 969: ffcopy(afp, anp, xtp, tnp, fsize(xtp, tnp) - SARMAG); ! 970: #else ! 971: if (fread(&i, sizeof(i), 1, xtp) != 1) ! 972: ioerr(tnp); ! 973: if (fwrite(&i, sizeof(i), 1, afp) != 1) ! 974: ioerr(anp); ! 975: if (rfp != NULL) ! 976: rcopy(); ! 977: ffcopy(afp, anp, xtp, tnp, fsize(xtp, tnp) - sizeof(int)); ! 978: #endif ! 979: tfp = xtp; /* Delete */ ! 980: } ! 981: ! 982: /* ! 983: * Write diagnostic. ! 984: * The flag 'f' marks fatal errors. ! 985: */ ! 986: diag(f, a) ! 987: { ! 988: fprintf(stderr, "%r.\n", &a); ! 989: if (f) ! 990: delexit(ERROR); ! 991: xstat = NOTALL; ! 992: } ! 993: ! 994: /* ! 995: * Print a message for a ! 996: * given archive member. The header ! 997: * is in the header buffer. ! 998: */ ! 999: amsg(s) ! 1000: char *s; ! 1001: { ! 1002: register char *p; ! 1003: register c; ! 1004: ! 1005: p = ahb.ar_name; ! 1006: while (p<&ahb.ar_name[DIRSIZ] && (c=*p++)!=0) ! 1007: putchar(c); ! 1008: putchar(':'); ! 1009: if (s != NULL) ! 1010: printf(" %s.", s); ! 1011: putchar('\n'); ! 1012: } ! 1013: ! 1014: /* ! 1015: * Exit. ! 1016: * Delete the tempfile if ! 1017: * present. ! 1018: */ ! 1019: delexit(s) ! 1020: { ! 1021: if (tfp != NULL) ! 1022: unlink(tnp); ! 1023: #ifdef DEBUG ! 1024: if (s) ! 1025: abort(); ! 1026: #endif ! 1027: unlink(rnpx); ! 1028: exit(s); ! 1029: } ! 1030: ! 1031: /* ! 1032: * Mutter about an I/O error ! 1033: * on file 's'. ! 1034: */ ! 1035: ioerr(s) ! 1036: char *s; ! 1037: { ! 1038: diag(1, "%s: I/O error", s); ! 1039: } ! 1040: ! 1041: /* ! 1042: * Print usage message. ! 1043: */ ! 1044: usage() ! 1045: { ! 1046: fprintf(stderr, "Usage: ar options [posname] afile [name ...].\n"); ! 1047: delexit(ERROR); ! 1048: } ! 1049: ! 1050: /* ! 1051: * Compute the size of a file. ! 1052: * In bytes. ! 1053: * The file must not be seeked. ! 1054: */ ! 1055: long ! 1056: fsize(fp, fn) ! 1057: FILE *fp; ! 1058: char *fn; ! 1059: { ! 1060: struct stat sb; ! 1061: ! 1062: #if GEMDOS ! 1063: if (stat(fn, &sb) < 0) ! 1064: diag(1, state, fn); ! 1065: #else ! 1066: fstat(fileno(fp), &sb); ! 1067: #endif ! 1068: return (sb.st_size); ! 1069: } ! 1070: ! 1071: /* ! 1072: * Ranlib stuff. ! 1073: * If the current archive has HDRNAME as first module, ! 1074: * then skip it and open rfp for creation of new ranlib header, ! 1075: * otherwise backup and make a vanilla archive. ! 1076: * Unless sflag was set as an option, ! 1077: * in which case make rfp anyway. ! 1078: * Unless HDRNAME matches the name list and ffp == dfunc, ! 1079: * in which case make rfp only if sflag was set. ! 1080: */ ! 1081: ropen() ! 1082: { ! 1083: extern int dfunc(); ! 1084: long loc; ! 1085: ! 1086: ranCt = 0; ! 1087: loc = ftell(afp); ! 1088: if (geth() != 0) { /* Must not be end of file */ ! 1089: if (eqh(rnp)) { /* Symbol header */ ! 1090: seekPast(); ! 1091: if (ffp == dfunc && match()) { ! 1092: if (vflag) ! 1093: amsg("deleted"); ! 1094: } else ! 1095: ++sflag; ! 1096: } else { ! 1097: fseek(afp, loc, 0); ! 1098: if (sflag && ffp == dfunc) { ! 1099: strcpy(ahb.ar_name, rnp); ! 1100: match(); ! 1101: } ! 1102: } ! 1103: } ! 1104: if (sflag && (rfp = fopen(rnpx, "wb")) == NULL) ! 1105: diag(1, ccrea, rnpx); ! 1106: } ! 1107: ! 1108: /* ! 1109: * Add the symbols in mfp to the ranlib header, ! 1110: * and seek mfp back to where it began. ! 1111: * The postion of this module in the archive ! 1112: * is -sizeof(arhdr) from current position of afp. ! 1113: */ ! 1114: #if PORTAR ! 1115: raddmod(afp, mfp, s) ! 1116: FILE *afp, *mfp; ! 1117: long s; ! 1118: { ! 1119: FILEHDR fdh; ! 1120: SYMENT sym; ! 1121: long off; ! 1122: long str_length, aroff, i; ! 1123: int len, j, c, aux; ! 1124: char *str_tab; ! 1125: ! 1126: aroff = ftell(afp) - sizeof(struct ar_hdr); ! 1127: off = ftell(mfp); ! 1128: str_length = fdh.f_magic = 0; ! 1129: if (1 != fread(&fdh, sizeof(fdh), 1, mfp) || ! 1130: (C_386_MAGIC != fdh.f_magic) || ! 1131: !fdh.f_nsyms) ! 1132: goto done; ! 1133: ! 1134: i = fdh.f_symptr + (SYMESZ * fdh.f_nsyms); ! 1135: str_length = 0; ! 1136: if (!fdh.f_symptr) ! 1137: goto done; ! 1138: if (i < s) { /* make our own eof inside archive */ ! 1139: fseek(mfp, i + off, 0); ! 1140: if (1 != fread(&str_length, sizeof(str_length), 1, mfp)) ! 1141: str_length = 0; ! 1142: } ! 1143: if (str_length) { ! 1144: len = str_length -= 4; ! 1145: if (len != str_length) ! 1146: diag(1, "Cannot process %.*s small model", ! 1147: DIRSIZ, ahb.ar_name); ! 1148: if(NULL == (str_tab = malloc(len))) ! 1149: diag(1, "out of space %.*s", DIRSIZ, ahb.ar_name); ! 1150: if (1 != fread(str_tab, len, 1, mfp)) ! 1151: diag(1, "truncated module %.*s", DIRSIZ, ahb.ar_name); ! 1152: } ! 1153: ! 1154: fseek(mfp, fdh.f_symptr + off, 0); ! 1155: ! 1156: for (aux = i = 0; i < fdh.f_nsyms; i++) { ! 1157: if (1 != fread(&sym, sizeof(sym), 1, mfp)) ! 1158: diag(1, "truncated module %.*s", DIRSIZ, ahb.ar_name); ! 1159: ! 1160: /* bypass aux symbols */ ! 1161: if (aux) { ! 1162: aux--; ! 1163: continue; ! 1164: } ! 1165: aux = sym.n_numaux; ! 1166: ! 1167: if (C_EXT != sym.n_sclass || ! 1168: (!sym.n_scnum && !sym.n_value)) ! 1169: continue; ! 1170: ! 1171: fwrite(&aroff, sizeof(aroff), 1, rfp); ! 1172: ranCt++; ! 1173: ! 1174: if (!sym._n._n_n._n_zeroes) { ! 1175: fputs(str_tab + sym._n._n_n._n_offset - 4, rfp); ! 1176: fputc(0, rfp); ! 1177: continue; ! 1178: } ! 1179: for (j = 0; (j < SYMNMLEN) && (c = sym._n._n_name[j]); j++) ! 1180: fputc(c, rfp); ! 1181: fputc(0, rfp); ! 1182: } ! 1183: if (str_length) ! 1184: free(str_tab); ! 1185: done: ! 1186: fseek(mfp, off, 0); ! 1187: } ! 1188: ! 1189: /* ! 1190: * Reverse byte order on 386s ! 1191: */ ! 1192: flipwrite(x) ! 1193: unsigned long x; ! 1194: { ! 1195: #ifdef GEMDOS ! 1196: if (1 != fwrite(&x, sizeof(x), 1, afp)) ! 1197: ioerr(anp); ! 1198: #else ! 1199: union full { ! 1200: unsigned char uc[4]; ! 1201: unsigned long ul; ! 1202: } l; ! 1203: unsigned char c; ! 1204: ! 1205: l.ul = x; ! 1206: c = l.uc[0]; l.uc[0] = l.uc[3]; l.uc[3] = c; ! 1207: c = l.uc[1]; l.uc[1] = l.uc[2]; l.uc[2] = c; ! 1208: ! 1209: if (1 != fwrite(&l, sizeof(x), 1, afp)) ! 1210: ioerr(anp); ! 1211: #endif ! 1212: } ! 1213: ! 1214: /* ! 1215: * Copy the ranlib header to the output archive. ! 1216: * Close and null the ranlib file pointer ! 1217: */ ! 1218: rcopy() ! 1219: { ! 1220: register FILE *fp; ! 1221: int c, pad; ! 1222: long i, x, ranLen; ! 1223: ! 1224: ranLen = ftell(rfp); /* we are at the end */ ! 1225: fclose(rfp); ! 1226: rfp = NULL; ! 1227: ! 1228: fp = makeh(rnpx); ! 1229: pad = ranLen & 1; ! 1230: ahb.ar_size = ranLen += pad + sizeof(ranCt); ! 1231: ! 1232: time(&ahb.ar_date); ! 1233: ahb.ar_date += (long)(10*365+3)*24*60*60; ! 1234: ! 1235: puth(afp, anp); ! 1236: tfp = NULL; ! 1237: flipwrite(ranCt); ! 1238: ranLen += sizeof(struct ar_hdr); ! 1239: ! 1240: for (i = 0; i < ranCt; i++) { ! 1241: if (1 != fread(&x, sizeof(x), 1, fp)) ! 1242: ioerr(rnpx); ! 1243: flipwrite(x + ranLen); ! 1244: while(fgetc(fp)) ! 1245: ; ! 1246: } ! 1247: ! 1248: fseek (fp, 0L, 0); ! 1249: for (i = 0; i < ranCt; i++) { ! 1250: if (1 != fread(&x, sizeof(x), 1, fp)) ! 1251: ioerr(rnpx); ! 1252: while (c = fgetc(fp)) ! 1253: fputc(c, afp); ! 1254: fputc(0, afp); ! 1255: } ! 1256: if (pad) ! 1257: fputc(0, afp); ! 1258: ! 1259: fclose(fp); ! 1260: unlink(rnpx); ! 1261: } ! 1262: #else ! 1263: struct ldheader ldh; ! 1264: struct ldsym lds; ! 1265: struct ar_sym ars; ! 1266: ! 1267: xwrite() ! 1268: { ! 1269: if (fwrite(lds.ls_id, sizeof(lds.ls_id), 1, rfp) != 1 ! 1270: || fwrite(&ars.ar_off, sizeof(ars.ar_off), 1, rfp) != 1) ! 1271: ioerr(rnpx); ! 1272: } ! 1273: ! 1274: xread(fp) register FILE *fp; ! 1275: { ! 1276: register int r; ! 1277: union { long l; unsigned u[2]; } u; ! 1278: ! 1279: if ((ldh.l_flag & LF_32) == 0) { ! 1280: r = fread(&lds, sizeof(lds)-sizeof(short), 1, fp); ! 1281: u.l = lds.ls_addr; ! 1282: canshort(u.u[0]); ! 1283: lds.ls_addr = u.u[0]; ! 1284: } else { ! 1285: r = fread(&lds, sizeof(lds), 1, fp); ! 1286: canlong(lds.ls_addr); ! 1287: } ! 1288: canshort(lds.ls_type); ! 1289: return (r); ! 1290: } ! 1291: ! 1292: raddmod(afp, mfp) FILE *afp, *mfp; ! 1293: { ! 1294: fsize_t off, offset; ! 1295: int seg, nsym; ! 1296: ! 1297: ars.ar_off = ftell(afp) - sizeof(ahb) - SARMAG; ! 1298: cansize(ars.ar_off); ! 1299: off = ftell(mfp); ! 1300: ldh.l_magic = 0; /* in case fread fails */ ! 1301: if (fread(&ldh, sizeof ldh, 1, mfp) != 1) ! 1302: goto done; ! 1303: canshort(ldh.l_magic); ! 1304: if (ldh.l_magic != L_MAGIC) ! 1305: goto done; ! 1306: canshort(ldh.l_flag); ! 1307: if ((ldh.l_flag & LF_32) == 0) ! 1308: ldh.l_tbase = sizeof(ldh) - 2*sizeof(short); ! 1309: else ! 1310: canshort(ldh.l_tbase); ! 1311: offset = ldh.l_tbase - (fsize_t)sizeof(ldh); ! 1312: for (seg=0; seg<L_SYM; seg++) { ! 1313: if (seg==L_BSSI || seg==L_BSSD) ! 1314: continue; ! 1315: cansize(ldh.l_ssize[seg]); ! 1316: offset += ldh.l_ssize[seg]; ! 1317: } ! 1318: fseek(mfp, offset, 1); ! 1319: cansize(ldh.l_ssize[L_SYM]); ! 1320: if ((ldh.l_flag & LF_32) == 0) ! 1321: nsym = ldh.l_ssize[L_SYM] ! 1322: / (sizeof(struct ldsym) - sizeof(short)); ! 1323: else ! 1324: nsym = ldh.l_ssize[L_SYM]/sizeof(struct ldsym); ! 1325: while (nsym--) { ! 1326: if (xread(mfp) == 0) ! 1327: diag(1, "truncated module %.*s", DIRSIZ, ahb.ar_name); ! 1328: if ((lds.ls_type&L_GLOBAL) == 0) ! 1329: continue; ! 1330: if ((lds.ls_type&LR_SEG) != L_REF) ! 1331: xwrite(); ! 1332: } ! 1333: done: ! 1334: fseek(mfp, off, 0); /* back to beginning of module */ ! 1335: } ! 1336: ! 1337: /* ! 1338: * Copy the ranlib header to the output archive ! 1339: * close and null the ranlib file pointer. ! 1340: */ ! 1341: rcopy() ! 1342: { ! 1343: register FILE *fp; ! 1344: fclose(rfp); ! 1345: rfp = NULL; ! 1346: fp = makeh(rnpx); ! 1347: time(&ahb.ar_date); ! 1348: ahb.ar_date += (long)(10*365+3)*24*60*60; ! 1349: puth(afp, anp); ! 1350: tfp = NULL; ! 1351: ffcopy(afp, anp, fp, rnpx, fsize(fp, rnpx)); ! 1352: fclose(fp); ! 1353: unlink(rnpx); ! 1354: } ! 1355: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.