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