|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)ar.c 4.5 (Berkeley) 9/25/83";
3: #endif
4:
5: /*
6: * ar - portable (ascii) format version
7: */
8: #include <sys/types.h>
9: #include <sys/stat.h>
10: #include <sys/time.h>
11:
12: #include <stdio.h>
13: #include <ar.h>
14: #include <signal.h>
15:
16: struct stat stbuf;
17: struct ar_hdr arbuf;
18: struct lar_hdr {
19: char lar_name[16];
20: long lar_date;
21: u_short lar_uid;
22: u_short lar_gid;
23: u_short lar_mode;
24: long lar_size;
25: } larbuf;
26:
27: #define SKIP 1
28: #define IODD 2
29: #define OODD 4
30: #define HEAD 8
31:
32: char *man = { "mrxtdpq" };
33: char *opt = { "uvnbailo" };
34:
35: int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0};
36: int sigdone();
37: long lseek();
38: int rcmd();
39: int dcmd();
40: int xcmd();
41: int tcmd();
42: int pcmd();
43: int mcmd();
44: int qcmd();
45: int (*comfun)();
46: char flg[26];
47: char **namv;
48: int namc;
49: char *arnam;
50: char *ponam;
51: char *tmpnam = { "/tmp/vXXXXX" };
52: char *tmp1nam = { "/tmp/v1XXXXX" };
53: char *tmp2nam = { "/tmp/v2XXXXX" };
54: char *tfnam;
55: char *tf1nam;
56: char *tf2nam;
57: char *file;
58: char name[16];
59: int af;
60: int tf;
61: int tf1;
62: int tf2;
63: int qf;
64: int bastate;
65: char buf[BUFSIZ];
66: int truncate; /* ok to truncate argument filenames */
67:
68: char *trim();
69: char *mktemp();
70: char *ctime();
71:
72: main(argc, argv)
73: char *argv[];
74: {
75: register i;
76: register char *cp;
77:
78: for(i=0; signum[i]; i++)
79: if(signal(signum[i], SIG_IGN) != SIG_IGN)
80: signal(signum[i], sigdone);
81: if(argc < 3)
82: usage();
83: cp = argv[1];
84: for(cp = argv[1]; *cp; cp++)
85: switch(*cp) {
86: case 'o':
87: case 'l':
88: case 'v':
89: case 'u':
90: case 'n':
91: case 'a':
92: case 'b':
93: case 'c':
94: case 'i':
95: flg[*cp - 'a']++;
96: continue;
97:
98: case 'r':
99: setcom(rcmd);
100: continue;
101:
102: case 'd':
103: setcom(dcmd);
104: continue;
105:
106: case 'x':
107: setcom(xcmd);
108: continue;
109:
110: case 't':
111: setcom(tcmd);
112: continue;
113:
114: case 'p':
115: setcom(pcmd);
116: continue;
117:
118: case 'm':
119: setcom(mcmd);
120: continue;
121:
122: case 'q':
123: setcom(qcmd);
124: continue;
125:
126: default:
127: fprintf(stderr, "ar: bad option `%c'\n", *cp);
128: done(1);
129: }
130: if(flg['l'-'a']) {
131: tmpnam = "vXXXXX";
132: tmp1nam = "v1XXXXX";
133: tmp2nam = "v2XXXXX";
134: }
135: if(flg['i'-'a'])
136: flg['b'-'a']++;
137: if(flg['a'-'a'] || flg['b'-'a']) {
138: bastate = 1;
139: ponam = trim(argv[2]);
140: argv++;
141: argc--;
142: if(argc < 3)
143: usage();
144: }
145: arnam = argv[2];
146: namv = argv+3;
147: namc = argc-3;
148: if(comfun == 0) {
149: if(flg['u'-'a'] == 0) {
150: fprintf(stderr, "ar: one of [%s] must be specified\n", man);
151: done(1);
152: }
153: setcom(rcmd);
154: }
155: (*comfun)();
156: done(notfound());
157: }
158:
159: setcom(fun)
160: int (*fun)();
161: {
162:
163: if(comfun != 0) {
164: fprintf(stderr, "ar: only one of [%s] allowed\n", man);
165: done(1);
166: }
167: comfun = fun;
168: }
169:
170: rcmd()
171: {
172: register f;
173:
174: init();
175: getaf();
176: while(!getdir()) {
177: bamatch();
178: if(namc == 0 || match()) {
179: f = stats();
180: if(f < 0) {
181: if(namc)
182: fprintf(stderr, "ar: cannot open %s\n", file);
183: goto cp;
184: }
185: if(flg['u'-'a'])
186: if(stbuf.st_mtime <= larbuf.lar_date) {
187: close(f);
188: goto cp;
189: }
190: mesg('r');
191: copyfil(af, -1, IODD+SKIP);
192: movefil(f);
193: continue;
194: }
195: cp:
196: mesg('c');
197: copyfil(af, tf, IODD+OODD+HEAD);
198: }
199: cleanup();
200: }
201:
202: dcmd()
203: {
204:
205: init();
206: if(getaf())
207: noar();
208: while(!getdir()) {
209: if(match()) {
210: mesg('d');
211: copyfil(af, -1, IODD+SKIP);
212: continue;
213: }
214: mesg('c');
215: copyfil(af, tf, IODD+OODD+HEAD);
216: }
217: install();
218: }
219:
220: xcmd()
221: {
222: register f;
223: struct timeval tv[2];
224:
225: if(getaf())
226: noar();
227: while(!getdir()) {
228: if(namc == 0 || match()) {
229: f = creat(file, larbuf.lar_mode & 0777);
230: if(f < 0) {
231: fprintf(stderr, "ar: %s cannot create\n", file);
232: goto sk;
233: }
234: mesg('x');
235: copyfil(af, f, IODD);
236: close(f);
237: if (flg['o'-'a']) {
238: tv[0].tv_sec = tv[1].tv_sec = larbuf.lar_date;
239: tv[0].tv_usec = tv[1].tv_usec = 0;
240: utimes(file, tv);
241: }
242: continue;
243: }
244: sk:
245: mesg('c');
246: copyfil(af, -1, IODD+SKIP);
247: if (namc > 0 && !morefil())
248: done(0);
249: }
250: }
251:
252: pcmd()
253: {
254:
255: if(getaf())
256: noar();
257: while(!getdir()) {
258: if(namc == 0 || match()) {
259: if(flg['v'-'a']) {
260: printf("\n<%s>\n\n", file);
261: fflush(stdout);
262: }
263: copyfil(af, 1, IODD);
264: continue;
265: }
266: copyfil(af, -1, IODD+SKIP);
267: }
268: }
269:
270: mcmd()
271: {
272:
273: init();
274: if(getaf())
275: noar();
276: tf2nam = mktemp(tmp2nam);
277: close(creat(tf2nam, 0600));
278: tf2 = open(tf2nam, 2);
279: if(tf2 < 0) {
280: fprintf(stderr, "ar: cannot create third temp\n");
281: done(1);
282: }
283: while(!getdir()) {
284: bamatch();
285: if(match()) {
286: mesg('m');
287: copyfil(af, tf2, IODD+OODD+HEAD);
288: continue;
289: }
290: mesg('c');
291: copyfil(af, tf, IODD+OODD+HEAD);
292: }
293: install();
294: }
295:
296: tcmd()
297: {
298:
299: if(getaf())
300: noar();
301: while(!getdir()) {
302: if(namc == 0 || match()) {
303: if(flg['v'-'a'])
304: longt();
305: printf("%s\n", trim(file));
306: }
307: copyfil(af, -1, IODD+SKIP);
308: }
309: }
310:
311: qcmd()
312: {
313: register i, f;
314:
315: if (flg['a'-'a'] || flg['b'-'a']) {
316: fprintf(stderr, "ar: abi not allowed with q\n");
317: done(1);
318: }
319: truncate++;
320: getqf();
321: for(i=0; signum[i]; i++)
322: signal(signum[i], SIG_IGN);
323: lseek(qf, 0l, 2);
324: for(i=0; i<namc; i++) {
325: file = namv[i];
326: if(file == 0)
327: continue;
328: namv[i] = 0;
329: mesg('q');
330: f = stats();
331: if(f < 0) {
332: fprintf(stderr, "ar: %s cannot open\n", file);
333: continue;
334: }
335: tf = qf;
336: movefil(f);
337: qf = tf;
338: }
339: }
340:
341: init()
342: {
343:
344: tfnam = mktemp(tmpnam);
345: close(creat(tfnam, 0600));
346: tf = open(tfnam, 2);
347: if(tf < 0) {
348: fprintf(stderr, "ar: cannot create temp file\n");
349: done(1);
350: }
351: if (write(tf, ARMAG, SARMAG) != SARMAG)
352: wrerr();
353: }
354:
355: getaf()
356: {
357: char mbuf[SARMAG];
358:
359: af = open(arnam, 0);
360: if(af < 0)
361: return(1);
362: if (read(af, mbuf, SARMAG) != SARMAG || strncmp(mbuf, ARMAG, SARMAG)) {
363: fprintf(stderr, "ar: %s not in archive format\n", arnam);
364: done(1);
365: }
366: return(0);
367: }
368:
369: getqf()
370: {
371: char mbuf[SARMAG];
372:
373: if ((qf = open(arnam, 2)) < 0) {
374: if(!flg['c'-'a'])
375: fprintf(stderr, "ar: creating %s\n", arnam);
376: if ((qf = creat(arnam, 0666)) < 0) {
377: fprintf(stderr, "ar: cannot create %s\n", arnam);
378: done(1);
379: }
380: if (write(qf, ARMAG, SARMAG) != SARMAG)
381: wrerr();
382: } else if (read(qf, mbuf, SARMAG) != SARMAG
383: || strncmp(mbuf, ARMAG, SARMAG)) {
384: fprintf(stderr, "ar: %s not in archive format\n", arnam);
385: done(1);
386: }
387: }
388:
389: usage()
390: {
391: printf("usage: ar [%s][%s] archive files ...\n", man, opt);
392: done(1);
393: }
394:
395: noar()
396: {
397:
398: fprintf(stderr, "ar: %s does not exist\n", arnam);
399: done(1);
400: }
401:
402: sigdone()
403: {
404: done(100);
405: }
406:
407: done(c)
408: {
409:
410: if(tfnam)
411: unlink(tfnam);
412: if(tf1nam)
413: unlink(tf1nam);
414: if(tf2nam)
415: unlink(tf2nam);
416: exit(c);
417: }
418:
419: notfound()
420: {
421: register i, n;
422:
423: n = 0;
424: for(i=0; i<namc; i++)
425: if(namv[i]) {
426: fprintf(stderr, "ar: %s not found\n", namv[i]);
427: n++;
428: }
429: return(n);
430: }
431:
432: morefil()
433: {
434: register i, n;
435:
436: n = 0;
437: for(i=0; i<namc; i++)
438: if(namv[i])
439: n++;
440: return(n);
441: }
442:
443: cleanup()
444: {
445: register i, f;
446:
447: truncate++;
448: for(i=0; i<namc; i++) {
449: file = namv[i];
450: if(file == 0)
451: continue;
452: namv[i] = 0;
453: mesg('a');
454: f = stats();
455: if(f < 0) {
456: fprintf(stderr, "ar: %s cannot open\n", file);
457: continue;
458: }
459: movefil(f);
460: }
461: install();
462: }
463:
464: install()
465: {
466: register i;
467:
468: for(i=0; signum[i]; i++)
469: signal(signum[i], SIG_IGN);
470: if(af < 0)
471: if(!flg['c'-'a'])
472: fprintf(stderr, "ar: creating %s\n", arnam);
473: close(af);
474: af = creat(arnam, 0666);
475: if(af < 0) {
476: fprintf(stderr, "ar: cannot create %s\n", arnam);
477: done(1);
478: }
479: if(tfnam) {
480: lseek(tf, 0l, 0);
481: while((i = read(tf, buf, BUFSIZ)) > 0)
482: if (write(af, buf, i) != i)
483: wrerr();
484: }
485: if(tf2nam) {
486: lseek(tf2, 0l, 0);
487: while((i = read(tf2, buf, BUFSIZ)) > 0)
488: if (write(af, buf, i) != i)
489: wrerr();
490: }
491: if(tf1nam) {
492: lseek(tf1, 0l, 0);
493: while((i = read(tf1, buf, BUFSIZ)) > 0)
494: if (write(af, buf, i) != i)
495: wrerr();
496: }
497: }
498:
499: /*
500: * insert the file 'file'
501: * into the temporary file
502: */
503: movefil(f)
504: {
505: char buf[sizeof(arbuf)+1];
506:
507: sprintf(buf, "%-16s%-12ld%-6u%-6u%-8o%-10ld%-2s",
508: trim(file),
509: stbuf.st_mtime,
510: stbuf.st_uid,
511: stbuf.st_gid,
512: stbuf.st_mode,
513: stbuf.st_size,
514: ARFMAG);
515: strncpy((char *)&arbuf, buf, sizeof(arbuf));
516: larbuf.lar_size = stbuf.st_size;
517: copyfil(f, tf, OODD+HEAD);
518: close(f);
519: }
520:
521: stats()
522: {
523: register f;
524:
525: f = open(file, 0);
526: if(f < 0)
527: return(f);
528: if(fstat(f, &stbuf) < 0) {
529: close(f);
530: return(-1);
531: }
532: return(f);
533: }
534:
535: /*
536: * copy next file
537: * size given in arbuf
538: */
539: copyfil(fi, fo, flag)
540: {
541: register i, o;
542: int pe;
543:
544: if(flag & HEAD) {
545: for (i=sizeof(arbuf.ar_name)-1; i>=0; i--) {
546: if (arbuf.ar_name[i]==' ')
547: continue;
548: else if (arbuf.ar_name[i]=='\0')
549: arbuf.ar_name[i] = ' ';
550: else
551: break;
552: }
553: if (write(fo, (char *)&arbuf, sizeof arbuf) != sizeof arbuf)
554: wrerr();
555: }
556: pe = 0;
557: while(larbuf.lar_size > 0) {
558: i = o = BUFSIZ;
559: if(larbuf.lar_size < i) {
560: i = o = larbuf.lar_size;
561: if(i&1) {
562: buf[i] = '\n';
563: if(flag & IODD)
564: i++;
565: if(flag & OODD)
566: o++;
567: }
568: }
569: if(read(fi, buf, i) != i)
570: pe++;
571: if((flag & SKIP) == 0)
572: if (write(fo, buf, o) != o)
573: wrerr();
574: larbuf.lar_size -= BUFSIZ;
575: }
576: if(pe)
577: phserr();
578: }
579:
580: getdir()
581: {
582: register char *cp;
583: register i;
584:
585: i = read(af, (char *)&arbuf, sizeof arbuf);
586: if(i != sizeof arbuf) {
587: if(tf1nam) {
588: i = tf;
589: tf = tf1;
590: tf1 = i;
591: }
592: return(1);
593: }
594: if (strncmp(arbuf.ar_fmag, ARFMAG, sizeof(arbuf.ar_fmag))) {
595: fprintf(stderr, "ar: malformed archive (at %ld)\n", lseek(af, 0L, 1));
596: done(1);
597: }
598: cp = arbuf.ar_name + sizeof(arbuf.ar_name);
599: while (*--cp==' ')
600: ;
601: *++cp = '\0';
602: strncpy(name, arbuf.ar_name, sizeof(arbuf.ar_name));
603: file = name;
604: strncpy(larbuf.lar_name, name, sizeof(larbuf.lar_name));
605: sscanf(arbuf.ar_date, "%ld", &larbuf.lar_date);
606: sscanf(arbuf.ar_uid, "%hd", &larbuf.lar_uid);
607: sscanf(arbuf.ar_gid, "%hd", &larbuf.lar_gid);
608: sscanf(arbuf.ar_mode, "%ho", &larbuf.lar_mode);
609: sscanf(arbuf.ar_size, "%ld", &larbuf.lar_size);
610: return(0);
611: }
612:
613: match()
614: {
615: register i;
616:
617: for(i=0; i<namc; i++) {
618: if(namv[i] == 0)
619: continue;
620: if(strcmp(trim(namv[i]), file) == 0) {
621: file = namv[i];
622: namv[i] = 0;
623: return(1);
624: }
625: }
626: return(0);
627: }
628:
629: bamatch()
630: {
631: register f;
632:
633: switch(bastate) {
634:
635: case 1:
636: if(strcmp(file, ponam) != 0)
637: return;
638: bastate = 2;
639: if(flg['a'-'a'])
640: return;
641:
642: case 2:
643: bastate = 0;
644: tf1nam = mktemp(tmp1nam);
645: close(creat(tf1nam, 0600));
646: f = open(tf1nam, 2);
647: if(f < 0) {
648: fprintf(stderr, "ar: cannot create second temp\n");
649: return;
650: }
651: tf1 = tf;
652: tf = f;
653: }
654: }
655:
656: phserr()
657: {
658:
659: fprintf(stderr, "ar: phase error on %s\n", file);
660: }
661:
662: mesg(c)
663: {
664:
665: if(flg['v'-'a'])
666: if(c != 'c' || flg['v'-'a'] > 1)
667: printf("%c - %s\n", c, file);
668: }
669:
670: char *
671: trim(s)
672: char *s;
673: {
674: register char *p1, *p2;
675:
676: /* Strip trailing slashes */
677: for(p1 = s; *p1; p1++)
678: ;
679: while(p1 > s) {
680: if(*--p1 != '/')
681: break;
682: *p1 = 0;
683: }
684:
685: /* Find last component of path; do not zap the path */
686: p2 = s;
687: for(p1 = s; *p1; p1++)
688: if(*p1 == '/')
689: p2 = p1+1;
690:
691: /*
692: * Truncate name if too long, only if we are doing an 'add'
693: * type operation. We only allow 15 cause rest of ar
694: * isn't smart enough to deal with non-null terminated
695: * names. Need an exit status convention...
696: * Need yet another new archive format...
697: */
698: if (truncate && strlen(p2) > sizeof(arbuf.ar_name) - 1) {
699: fprintf(stderr, "ar: filename %s truncated to ", p2);
700: *(p2 + sizeof(arbuf.ar_name) - 1) = '\0';
701: fprintf(stderr, "%s\n", p2);
702: }
703: return(p2);
704: }
705:
706: #define IFMT 060000
707: #define ISARG 01000
708: #define LARGE 010000
709: #define SUID 04000
710: #define SGID 02000
711: #define ROWN 0400
712: #define WOWN 0200
713: #define XOWN 0100
714: #define RGRP 040
715: #define WGRP 020
716: #define XGRP 010
717: #define ROTH 04
718: #define WOTH 02
719: #define XOTH 01
720: #define STXT 01000
721:
722: longt()
723: {
724: register char *cp;
725:
726: pmode();
727: printf("%3d/%1d", larbuf.lar_uid, larbuf.lar_gid);
728: printf("%7ld", larbuf.lar_size);
729: cp = ctime(&larbuf.lar_date);
730: printf(" %-12.12s %-4.4s ", cp+4, cp+20);
731: }
732:
733: int m1[] = { 1, ROWN, 'r', '-' };
734: int m2[] = { 1, WOWN, 'w', '-' };
735: int m3[] = { 2, SUID, 's', XOWN, 'x', '-' };
736: int m4[] = { 1, RGRP, 'r', '-' };
737: int m5[] = { 1, WGRP, 'w', '-' };
738: int m6[] = { 2, SGID, 's', XGRP, 'x', '-' };
739: int m7[] = { 1, ROTH, 'r', '-' };
740: int m8[] = { 1, WOTH, 'w', '-' };
741: int m9[] = { 2, STXT, 't', XOTH, 'x', '-' };
742:
743: int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};
744:
745: pmode()
746: {
747: register int **mp;
748:
749: for (mp = &m[0]; mp < &m[9];)
750: select(*mp++);
751: }
752:
753: select(pairp)
754: int *pairp;
755: {
756: register int n, *ap;
757:
758: ap = pairp;
759: n = *ap++;
760: while (--n>=0 && (larbuf.lar_mode&*ap++)==0)
761: ap++;
762: putchar(*ap);
763: }
764:
765: wrerr()
766: {
767: perror("ar write error");
768: done(1);
769: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.