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