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