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