|
|
1.1 root 1: #ifndef lint
2: static char *sccsid = "@(#)tar.c 4.19 (Berkeley) 9/22/83";
3: #endif
4:
5: /*
6: * Tape Archival Program
7: */
8: #include <stdio.h>
9: #include <sys/param.h>
10: #include <sys/stat.h>
11: #include <sys/dir.h>
12: #include <sys/ioctl.h>
13: #include <sys/mtio.h>
14: #include <sys/time.h>
15: #include <signal.h>
16: #include <errno.h>
17:
18: #define TBLOCK 512
19: #define NBLOCK 20
20: #define NAMSIZ 100
21:
22: union hblock {
23: char dummy[TBLOCK];
24: struct header {
25: char name[NAMSIZ];
26: char mode[8];
27: char uid[8];
28: char gid[8];
29: char size[12];
30: char mtime[12];
31: char chksum[8];
32: char linkflag;
33: char linkname[NAMSIZ];
34: } dbuf;
35: };
36:
37: struct linkbuf {
38: ino_t inum;
39: dev_t devnum;
40: int count;
41: char pathname[NAMSIZ];
42: struct linkbuf *nextp;
43: };
44:
45: union hblock dblock;
46: union hblock *tbuf;
47: struct linkbuf *ihead;
48: struct stat stbuf;
49:
50: int rflag;
51: int xflag;
52: int vflag;
53: int tflag;
54: int cflag;
55: int mflag;
56: int fflag;
57: int iflag;
58: int oflag;
59: int pflag;
60: int wflag;
61: int hflag;
62: int Bflag;
63: int Fflag;
64:
65: int mt;
66: int term;
67: int chksum;
68: int recno;
69: int first;
70: int linkerrok;
71: int freemem = 1;
72: int nblock = NBLOCK;
73: int onintr();
74: int onquit();
75: int onhup();
76: int onterm();
77:
78: daddr_t low;
79: daddr_t high;
80: daddr_t bsrch();
81:
82: FILE *tfile;
83: char tname[] = "/tmp/tarXXXXXX";
84: char *usefile;
85: char magtape[] = "/dev/rcy0s";
86: char *malloc();
87: char *sprintf();
88: char *strcat();
89: char *rindex();
90: char *getcwd();
91: char *getwd();
92:
93: main(argc, argv)
94: int argc;
95: char *argv[];
96: {
97: char *cp;
98:
99: if (argc < 2)
100: usage();
101:
102: tfile = NULL;
103: usefile = magtape;
104: argv[argc] = 0;
105: argv++;
106: for (cp = *argv++; *cp; cp++)
107: switch(*cp) {
108:
109: case 'f':
110: if (*argv == 0) {
111: fprintf(stderr,
112: "tar: tapefile must be specified with 'f' option\n");
113: usage();
114: }
115: usefile = *argv++;
116: fflag++;
117: break;
118:
119: case 'c':
120: cflag++;
121: rflag++;
122: break;
123:
124: case 'o':
125: oflag++;
126: break;
127:
128: case 'p':
129: pflag++;
130: break;
131:
132: case 'u':
133: mktemp(tname);
134: if ((tfile = fopen(tname, "w")) == NULL) {
135: fprintf(stderr,
136: "Tar: cannot create temporary file (%s)\n",
137: tname);
138: done(1);
139: }
140: fprintf(tfile, "!!!!!/!/!/!/!/!/!/! 000\n");
141: /*FALL THRU*/
142:
143: case 'r':
144: rflag++;
145: break;
146:
147: case 'v':
148: vflag++;
149: break;
150:
151: case 'w':
152: wflag++;
153: break;
154:
155: case 'x':
156: xflag++;
157: break;
158:
159: case 't':
160: tflag++;
161: break;
162:
163: case 'm':
164: mflag++;
165: break;
166:
167: case '-':
168: break;
169:
170: case '0':
171: case '1':
172: case '4':
173: case '5':
174: case '7':
175: case '8':
176: magtape[8] = *cp;
177: usefile = magtape;
178: break;
179:
180: case 'b':
181: if (*argv == 0) {
182: fprintf(stderr,
183: "tar: blocksize must be specified with 'b' option\n");
184: usage();
185: }
186: nblock = atoi(*argv);
187: if (nblock <= 0) {
188: fprintf(stderr,
189: "tar: invalid blocksize \"%s\"\n", *argv);
190: done(1);
191: }
192: argv++;
193: break;
194:
195: case 'l':
196: linkerrok++;
197: break;
198:
199: case 'h':
200: hflag++;
201: break;
202:
203: case 'i':
204: iflag++;
205: break;
206:
207: case 'B':
208: Bflag++;
209: break;
210:
211: case 'F':
212: Fflag++;
213: break;
214:
215: default:
216: fprintf(stderr, "tar: %c: unknown option\n", *cp);
217: usage();
218: }
219:
220: if (!rflag && !xflag && !tflag)
221: usage();
222: tbuf = (union hblock *)malloc(nblock*TBLOCK);
223: if (tbuf == NULL) {
224: fprintf(stderr, "tar: blocksize %d too big, can't get memory\n",
225: nblock);
226: done(1);
227: }
228: if (rflag) {
229: if (cflag && tfile != NULL)
230: usage();
231: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
232: signal(SIGINT, onintr);
233: if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
234: signal(SIGHUP, onhup);
235: if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
236: signal(SIGQUIT, onquit);
237: #ifdef notdef
238: if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
239: signal(SIGTERM, onterm);
240: #endif
241: if (strcmp(usefile, "-") == 0) {
242: if (cflag == 0) {
243: fprintf(stderr,
244: "tar: can only create standard output archives\n");
245: done(1);
246: }
247: mt = dup(1);
248: nblock = 1;
249: } else if ((mt = open(usefile, 2)) < 0) {
250: if (cflag == 0 || (mt = creat(usefile, 0666)) < 0) {
251: fprintf(stderr,
252: "tar: cannot open %s\n", usefile);
253: done(1);
254: }
255: }
256: dorep(argv);
257: done(0);
258: }
259: if (strcmp(usefile, "-") == 0) {
260: mt = dup(0);
261: nblock = 1;
262: } else if ((mt = open(usefile, 0)) < 0) {
263: fprintf(stderr, "tar: cannot open %s\n", usefile);
264: done(1);
265: }
266: if (xflag)
267: doxtract(argv);
268: else
269: dotable();
270: done(0);
271: }
272:
273: usage()
274: {
275: fprintf(stderr,
276: "tar: usage: tar -{txru}[cvfblmhopwBi] [tapefile] [blocksize] file1 file2...\n");
277: done(1);
278: }
279:
280: dorep(argv)
281: char *argv[];
282: {
283: register char *cp, *cp2;
284: char wdir[MAXPATHLEN], tempdir[MAXPATHLEN], *parent;
285:
286: if (!cflag) {
287: getdir();
288: do {
289: passtape();
290: if (term)
291: done(0);
292: getdir();
293: } while (!endtape());
294: backtape();
295: if (tfile != NULL) {
296: char buf[200];
297:
298: sprintf(buf,
299: "sort +0 -1 +1nr %s -o %s; awk '$1 != prev {print; prev=$1}' %s >%sX; mv %sX %s",
300: tname, tname, tname, tname, tname, tname);
301: fflush(tfile);
302: system(buf);
303: freopen(tname, "r", tfile);
304: fstat(fileno(tfile), &stbuf);
305: high = stbuf.st_size;
306: }
307: }
308:
309: (void) getcwd(wdir);
310: while (*argv && ! term) {
311: cp2 = *argv;
312: if (!strcmp(cp2, "-C") && argv[1]) {
313: argv++;
314: if (chdir(*argv) < 0)
315: perror(*argv);
316: else
317: (void) getcwd(wdir);
318: argv++;
319: continue;
320: }
321: parent = wdir;
322: for (cp = *argv; *cp; cp++)
323: if (*cp == '/')
324: cp2 = cp;
325: /************
326: if (cp2 != *argv) {
327: *************/
328: if(*cp2 == '/') {
329: if (cp2 != *argv) {
330: *cp2 = '\0';
331: if (chdir(*argv) < 0) {
332: perror(*argv);
333: continue;
334: }
335: } else
336: if (chdir("/") < 0) {
337: perror("/");
338: continue;
339: }
340: parent = getcwd(tempdir);
341: *cp2 = '/';
342: cp2++;
343: }
344: putfile(*argv++, cp2, parent);
345: if (chdir(wdir) < 0) {
346: fprintf(stderr, "cannot change back?: ");
347: perror(wdir);
348: }
349: }
350: putempty();
351: putempty();
352: flushtape();
353: if (linkerrok == 0)
354: return;
355: for (; ihead != NULL; ihead = ihead->nextp) {
356: if (ihead->count == 0)
357: continue;
358: fprintf(stderr, "tar: missing links to %s\n", ihead->pathname);
359: }
360: }
361:
362: endtape()
363: {
364: return (dblock.dbuf.name[0] == '\0');
365: }
366:
367: getdir()
368: {
369: register struct stat *sp;
370: int i;
371:
372: top:
373: readtape(dblock.dummy);
374: if (dblock.dbuf.name[0] == '\0')
375: return;
376: sp = &stbuf;
377: sscanf(dblock.dbuf.mode, "%o", &i);
378: sp->st_mode = i;
379: sscanf(dblock.dbuf.uid, "%o", &i);
380: sp->st_uid = i;
381: sscanf(dblock.dbuf.gid, "%o", &i);
382: sp->st_gid = i;
383: sscanf(dblock.dbuf.size, "%lo", &sp->st_size);
384: sscanf(dblock.dbuf.mtime, "%lo", &sp->st_mtime);
385: sscanf(dblock.dbuf.chksum, "%o", &chksum);
386: if (chksum != (i = checksum())) {
387: fprintf(stderr, "tar: directory checksum error (%d != %d)\n",
388: chksum, i);
389: if (iflag)
390: goto top;
391: done(2);
392: }
393: if (tfile != NULL)
394: fprintf(tfile, "%s %s\n", dblock.dbuf.name, dblock.dbuf.mtime);
395: }
396:
397: passtape()
398: {
399: long blocks;
400: char buf[TBLOCK];
401:
402: if (dblock.dbuf.linkflag == '1')
403: return;
404: blocks = stbuf.st_size;
405: blocks += TBLOCK-1;
406: blocks /= TBLOCK;
407:
408: while (blocks-- > 0)
409: readtape(buf);
410: }
411:
412: putfile(longname, shortname, parent)
413: char *longname;
414: char *shortname;
415: char *parent;
416: {
417: int infile = 0;
418: long blocks;
419: char buf[TBLOCK];
420: register char *cp, *cp2;
421: struct direct *dp;
422: DIR *dirp;
423: int i, j;
424: char newparent[NAMSIZ+64];
425: extern int errno;
426:
427: if (!hflag)
428: i = lstat(shortname, &stbuf);
429: else
430: i = stat(shortname, &stbuf);
431: if (i < 0) {
432: switch (errno) {
433: case EACCES:
434: fprintf(stderr, "tar: %s: cannot open file\n", longname);
435: break;
436: case ENOENT:
437: fprintf(stderr, "tar: %s: no such file or directory\n",
438: longname);
439: break;
440: default:
441: fprintf(stderr, "tar: %s: cannot stat file\n", longname);
442: break;
443: }
444: return;
445: }
446: if (tfile != NULL && checkupdate(longname) == 0)
447: return;
448: if (checkw('r', longname) == 0)
449: return;
450: if (Fflag && checkf(shortname, stbuf.st_mode, Fflag) == 0)
451: return;
452:
453: switch (stbuf.st_mode & S_IFMT) {
454: case S_IFDIR:
455: for (i = 0, cp = buf; *cp++ = longname[i++];)
456: ;
457: *--cp = '/';
458: *++cp = 0 ;
459: if (!oflag) {
460: if ((cp - buf) >= NAMSIZ) {
461: fprintf(stderr, "tar: %s: file name too long\n",
462: longname);
463: return;
464: }
465: stbuf.st_size = 0;
466: tomodes(&stbuf);
467: strcpy(dblock.dbuf.name,buf);
468: sprintf(dblock.dbuf.chksum, "%6o", checksum());
469: writetape(dblock.dummy);
470: }
471: sprintf(newparent, "%s/%s", parent, shortname);
472: if (chdir(shortname) < 0) {
473: perror(shortname);
474: return;
475: }
476: if ((dirp = opendir(".")) == NULL) {
477: fprintf(stderr, "tar: %s: directory read error\n",
478: longname);
479: if (chdir(parent) < 0) {
480: fprintf(stderr, "cannot change back?: ");
481: perror(parent);
482: }
483: return;
484: }
485: while ((dp = readdir(dirp)) != NULL && !term) {
486: if (dp->d_ino == 0)
487: continue;
488: if (!strcmp(".", dp->d_name) ||
489: !strcmp("..", dp->d_name))
490: continue;
491: strcpy(cp, dp->d_name);
492: i = telldir(dirp);
493: closedir(dirp);
494: putfile(buf, cp, newparent);
495: dirp = opendir(".");
496: seekdir(dirp, i);
497: }
498: closedir(dirp);
499: if (chdir(parent) < 0) {
500: fprintf(stderr, "cannot change back?: ");
501: perror(parent);
502: }
503: break;
504:
505: case S_IFLNK:
506: tomodes(&stbuf);
507: if (strlen(longname) >= NAMSIZ) {
508: fprintf(stderr, "tar: %s: file name too long\n",
509: longname);
510: return;
511: }
512: strcpy(dblock.dbuf.name, longname);
513: if (stbuf.st_size + 1 >= NAMSIZ) {
514: fprintf(stderr, "tar: %s: symbolic link too long\n",
515: longname);
516: return;
517: }
518: i = readlink(shortname, dblock.dbuf.linkname, NAMSIZ - 1);
519: if (i < 0) {
520: perror(longname);
521: return;
522: }
523: dblock.dbuf.linkname[i] = '\0';
524: dblock.dbuf.linkflag = '2';
525: if (vflag) {
526: fprintf(stderr, "a %s ", longname);
527: fprintf(stderr, "symbolic link to %s\n",
528: dblock.dbuf.linkname);
529: }
530: sprintf(dblock.dbuf.size, "%11lo", 0);
531: sprintf(dblock.dbuf.chksum, "%6o", checksum());
532: writetape(dblock.dummy);
533: break;
534:
535: case S_IFREG:
536: if ((infile = open(shortname, 0)) < 0) {
537: fprintf(stderr, "tar: %s: cannot open file\n", longname);
538: return;
539: }
540: tomodes(&stbuf);
541: if (strlen(longname) >= NAMSIZ) {
542: fprintf(stderr, "tar: %s: file name too long\n",
543: longname);
544: return;
545: }
546: strcpy(dblock.dbuf.name, longname);
547: if (stbuf.st_nlink > 1) {
548: struct linkbuf *lp;
549: int found = 0;
550:
551: for (lp = ihead; lp != NULL; lp = lp->nextp)
552: if (lp->inum == stbuf.st_ino &&
553: lp->devnum == stbuf.st_dev) {
554: found++;
555: break;
556: }
557: if (found) {
558: strcpy(dblock.dbuf.linkname, lp->pathname);
559: dblock.dbuf.linkflag = '1';
560: sprintf(dblock.dbuf.chksum, "%6o", checksum());
561: writetape( dblock.dummy);
562: if (vflag) {
563: fprintf(stderr, "a %s ", longname);
564: fprintf(stderr, "link to %s\n",
565: lp->pathname);
566: }
567: lp->count--;
568: close(infile);
569: return;
570: }
571: lp = (struct linkbuf *) malloc(sizeof(*lp));
572: if (lp == NULL) {
573: if (freemem) {
574: fprintf(stderr,
575: "tar: out of memory, link information lost\n");
576: freemem = 0;
577: }
578: } else {
579: lp->nextp = ihead;
580: ihead = lp;
581: lp->inum = stbuf.st_ino;
582: lp->devnum = stbuf.st_dev;
583: lp->count = stbuf.st_nlink - 1;
584: strcpy(lp->pathname, longname);
585: }
586: }
587: blocks = (stbuf.st_size + (TBLOCK-1)) / TBLOCK;
588: if (vflag) {
589: fprintf(stderr, "a %s ", longname);
590: fprintf(stderr, "%ld blocks\n", blocks);
591: }
592: sprintf(dblock.dbuf.chksum, "%6o", checksum());
593: writetape(dblock.dummy);
594:
595: while ((i = read(infile, buf, TBLOCK)) > 0 && blocks > 0) {
596: writetape(buf);
597: blocks--;
598: }
599: close(infile);
600: if (blocks != 0 || i != 0)
601: fprintf(stderr, "tar: %s: file changed size\n",
602: longname);
603: while (--blocks >= 0)
604: putempty();
605: break;
606:
607: default:
608: fprintf(stderr, "tar: %s is not a file. Not dumped\n",
609: longname);
610: break;
611: }
612: }
613:
614: doxtract(argv)
615: char *argv[];
616: {
617: long blocks, bytes;
618: char buf[TBLOCK];
619: char **cp;
620: int ofile;
621:
622: for (;;) {
623: getdir();
624: if (endtape())
625: break;
626: if (*argv == 0)
627: goto gotit;
628: for (cp = argv; *cp; cp++)
629: if (prefix(*cp, dblock.dbuf.name))
630: goto gotit;
631: passtape();
632: continue;
633:
634: gotit:
635: if (checkw('x', dblock.dbuf.name) == 0) {
636: passtape();
637: continue;
638: }
639: if (Fflag) {
640: char *s;
641:
642: if ((s = rindex(dblock.dbuf.name, '/')) == 0)
643: s = dblock.dbuf.name;
644: else
645: s++;
646: if (checkf(s, stbuf.st_mode, Fflag) == 0) {
647: passtape();
648: continue;
649: }
650: }
651: if (checkdir(dblock.dbuf.name))
652: continue;
653: if (dblock.dbuf.linkflag == '2') {
654: unlink(dblock.dbuf.name);
655: if (symlink(dblock.dbuf.linkname, dblock.dbuf.name)<0) {
656: fprintf(stderr, "tar: %s: symbolic link failed\n",
657: dblock.dbuf.name);
658: continue;
659: }
660: if (vflag)
661: fprintf(stderr, "x %s symbolic link to %s\n",
662: dblock.dbuf.name, dblock.dbuf.linkname);
663: #ifdef notdef
664: /* ignore alien orders */
665: chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid);
666: if (mflag == 0) {
667: struct timeval tv[2];
668:
669: tv[0].tv_sec = time(0);
670: tv[0].tv_usec = 0;
671: tv[1].tv_sec = stbuf.st_mtime;
672: tv[1].tv_usec = 0;
673: utimes(dblock.dbuf.name, tv);
674: }
675: if (pflag)
676: chmod(dblock.dbuf.name, stbuf.st_mode & 07777);
677: #endif
678: continue;
679: }
680: if (dblock.dbuf.linkflag == '1') {
681: unlink(dblock.dbuf.name);
682: if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) {
683: fprintf(stderr, "tar: %s: cannot link\n",
684: dblock.dbuf.name);
685: continue;
686: }
687: if (vflag)
688: fprintf(stderr, "%s linked to %s\n",
689: dblock.dbuf.name, dblock.dbuf.linkname);
690: continue;
691: }
692: if ((ofile = creat(dblock.dbuf.name,stbuf.st_mode&0xfff)) < 0) {
693: fprintf(stderr, "tar: %s - cannot create\n",
694: dblock.dbuf.name);
695: passtape();
696: continue;
697: }
698: chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid);
699: blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK;
700: if (vflag)
701: fprintf(stderr, "x %s, %ld bytes, %ld tape blocks\n",
702: dblock.dbuf.name, bytes, blocks);
703: for (; blocks-- > 0; bytes -= TBLOCK) {
704: readtape(buf);
705: if (bytes > TBLOCK) {
706: if (write(ofile, buf, TBLOCK) < 0) {
707: fprintf(stderr,
708: "tar: %s: HELP - extract write error\n",
709: dblock.dbuf.name);
710: done(2);
711: }
712: continue;
713: }
714: if (write(ofile, buf, (int) bytes) < 0) {
715: fprintf(stderr,
716: "tar: %s: HELP - extract write error\n",
717: dblock.dbuf.name);
718: done(2);
719: }
720: }
721: close(ofile);
722: if (mflag == 0) {
723: struct timeval tv[2];
724:
725: tv[0].tv_sec = time(0);
726: tv[0].tv_usec = 0;
727: tv[1].tv_sec = stbuf.st_mtime;
728: tv[1].tv_usec = 0;
729: utimes(dblock.dbuf.name, tv);
730: }
731: if (pflag)
732: chmod(dblock.dbuf.name, stbuf.st_mode & 07777);
733: }
734: }
735:
736: dotable()
737: {
738: for (;;) {
739: getdir();
740: if (endtape())
741: break;
742: if (vflag)
743: longt(&stbuf);
744: printf("%s", dblock.dbuf.name);
745: if (dblock.dbuf.linkflag == '1')
746: printf(" linked to %s", dblock.dbuf.linkname);
747: if (dblock.dbuf.linkflag == '2')
748: printf(" symbolic link to %s", dblock.dbuf.linkname);
749: printf("\n");
750: passtape();
751: }
752: }
753:
754: putempty()
755: {
756: char buf[TBLOCK];
757:
758: bzero(buf, sizeof (buf));
759: writetape(buf);
760: }
761:
762: longt(st)
763: register struct stat *st;
764: {
765: register char *cp;
766: char *ctime();
767:
768: pmode(st);
769: printf("%3d/%1d", st->st_uid, st->st_gid);
770: printf("%7D", st->st_size);
771: cp = ctime(&st->st_mtime);
772: printf(" %-12.12s %-4.4s ", cp+4, cp+20);
773: }
774:
775: #define SUID 04000
776: #define SGID 02000
777: #define ROWN 0400
778: #define WOWN 0200
779: #define XOWN 0100
780: #define RGRP 040
781: #define WGRP 020
782: #define XGRP 010
783: #define ROTH 04
784: #define WOTH 02
785: #define XOTH 01
786: #define STXT 01000
787: int m1[] = { 1, ROWN, 'r', '-' };
788: int m2[] = { 1, WOWN, 'w', '-' };
789: int m3[] = { 2, SUID, 's', XOWN, 'x', '-' };
790: int m4[] = { 1, RGRP, 'r', '-' };
791: int m5[] = { 1, WGRP, 'w', '-' };
792: int m6[] = { 2, SGID, 's', XGRP, 'x', '-' };
793: int m7[] = { 1, ROTH, 'r', '-' };
794: int m8[] = { 1, WOTH, 'w', '-' };
795: int m9[] = { 2, STXT, 't', XOTH, 'x', '-' };
796:
797: int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};
798:
799: pmode(st)
800: register struct stat *st;
801: {
802: register int **mp;
803:
804: for (mp = &m[0]; mp < &m[9];)
805: select(*mp++, st);
806: }
807:
808: select(pairp, st)
809: int *pairp;
810: struct stat *st;
811: {
812: register int n, *ap;
813:
814: ap = pairp;
815: n = *ap++;
816: while (--n>=0 && (st->st_mode&*ap++)==0)
817: ap++;
818: printf("%c", *ap);
819: }
820:
821: checkdir(name)
822: register char *name;
823: {
824: register char *cp;
825:
826: /*
827: * Quick check for existance of directory.
828: */
829: if ((cp = rindex(name, '/')) == 0)
830: return (0);
831: *cp = '\0';
832: if (access(name, 0) >= 0) {
833: *cp = '/';
834: return (cp[1] == '\0');
835: }
836: *cp = '/';
837:
838: /*
839: * No luck, try to make all directories in path.
840: */
841: for (cp = name; *cp; cp++) {
842: if (*cp != '/')
843: continue;
844: *cp = '\0';
845: if (access(name, 0) < 0) {
846: if (mkdir(name, 0777) < 0) {
847: perror(name);
848: *cp = '/';
849: return (0);
850: }
851: chown(name, stbuf.st_uid, stbuf.st_gid);
852: if (pflag && cp[1] == '\0')
853: chmod(name, stbuf.st_mode & 0777);
854: }
855: *cp = '/';
856: }
857: return (cp[-1]=='/');
858: }
859:
860: onintr()
861: {
862: signal(SIGINT, SIG_IGN);
863: term++;
864: }
865:
866: onquit()
867: {
868: signal(SIGQUIT, SIG_IGN);
869: term++;
870: }
871:
872: onhup()
873: {
874: signal(SIGHUP, SIG_IGN);
875: term++;
876: }
877:
878: onterm()
879: {
880: signal(SIGTERM, SIG_IGN);
881: term++;
882: }
883:
884: tomodes(sp)
885: register struct stat *sp;
886: {
887: register char *cp;
888:
889: for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
890: *cp = '\0';
891: sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777);
892: sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid);
893: sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid);
894: sprintf(dblock.dbuf.size, "%11lo ", sp->st_size);
895: sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime);
896: }
897:
898: checksum()
899: {
900: register int i;
901: register char *cp;
902:
903: for (cp = dblock.dbuf.chksum;
904: cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++)
905: *cp = ' ';
906: i = 0;
907: for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
908: i += *cp;
909: return (i);
910: }
911:
912: checkw(c, name)
913: char *name;
914: {
915: if (!wflag)
916: return (1);
917: printf("%c ", c);
918: if (vflag)
919: longt(&stbuf);
920: printf("%s: ", name);
921: return (response() == 'y');
922: }
923:
924: response()
925: {
926: char c;
927:
928: c = getchar();
929: if (c != '\n')
930: while (getchar() != '\n')
931: ;
932: else
933: c = 'n';
934: return (c);
935: }
936:
937: checkf(name, mode, howmuch)
938: char *name;
939: int mode, howmuch;
940: {
941: int l;
942:
943: if ((mode & S_IFMT) == S_IFDIR)
944: return (strcmp(name, "SCCS") != 0);
945: if ((l = strlen(name)) < 3)
946: return (1);
947: if (howmuch > 1 && name[l-2] == '.' && name[l-1] == 'o')
948: return (0);
949: if (strcmp(name, "core") == 0 ||
950: strcmp(name, "errs") == 0 ||
951: (howmuch > 1 && strcmp(name, "a.out") == 0))
952: return (0);
953: /* SHOULD CHECK IF IT IS EXECUTABLE */
954: return (1);
955: }
956:
957: checkupdate(arg)
958: char *arg;
959: {
960: char name[100];
961: long mtime;
962: daddr_t seekp;
963: daddr_t lookup();
964:
965: rewind(tfile);
966: for (;;) {
967: if ((seekp = lookup(arg)) < 0)
968: return (1);
969: fseek(tfile, seekp, 0);
970: fscanf(tfile, "%s %lo", name, &mtime);
971: return (stbuf.st_mtime > mtime);
972: }
973: }
974:
975: done(n)
976: {
977: unlink(tname);
978: exit(n);
979: }
980:
981: prefix(s1, s2)
982: register char *s1, *s2;
983: {
984: while (*s1)
985: if (*s1++ != *s2++)
986: return (0);
987: if (*s2)
988: return (*s2 == '/');
989: return (1);
990: }
991:
992: #define N 200
993: int njab;
994:
995: daddr_t
996: lookup(s)
997: char *s;
998: {
999: register int i;
1000: daddr_t a;
1001:
1002: for(i=0; s[i]; i++)
1003: if (s[i] == ' ')
1004: break;
1005: a = bsrch(s, i, low, high);
1006: return (a);
1007: }
1008:
1009: daddr_t
1010: bsrch(s, n, l, h)
1011: daddr_t l, h;
1012: char *s;
1013: {
1014: register int i, j;
1015: char b[N];
1016: daddr_t m, m1;
1017:
1018: njab = 0;
1019:
1020: loop:
1021: if (l >= h)
1022: return (-1L);
1023: m = l + (h-l)/2 - N/2;
1024: if (m < l)
1025: m = l;
1026: fseek(tfile, m, 0);
1027: fread(b, 1, N, tfile);
1028: njab++;
1029: for(i=0; i<N; i++) {
1030: if (b[i] == '\n')
1031: break;
1032: m++;
1033: }
1034: if (m >= h)
1035: return (-1L);
1036: m1 = m;
1037: j = i;
1038: for(i++; i<N; i++) {
1039: m1++;
1040: if (b[i] == '\n')
1041: break;
1042: }
1043: i = cmp(b+j, s, n);
1044: if (i < 0) {
1045: h = m;
1046: goto loop;
1047: }
1048: if (i > 0) {
1049: l = m1;
1050: goto loop;
1051: }
1052: return (m);
1053: }
1054:
1055: cmp(b, s, n)
1056: char *b, *s;
1057: {
1058: register int i;
1059:
1060: if (b[0] != '\n')
1061: exit(2);
1062: for(i=0; i<n; i++) {
1063: if (b[i+1] > s[i])
1064: return (-1);
1065: if (b[i+1] < s[i])
1066: return (1);
1067: }
1068: return (b[i+1] == ' '? 0 : -1);
1069: }
1070:
1071: readtape(buffer)
1072: char *buffer;
1073: {
1074: register int i;
1075:
1076: if (recno >= nblock || first == 0) {
1077: if ((i = bread(mt, tbuf, TBLOCK*nblock)) < 0) {
1078: fprintf(stderr, "tar: tape read error\n");
1079: done(3);
1080: }
1081: if (first == 0) {
1082: if ((i % TBLOCK) != 0) {
1083: fprintf(stderr, "tar: tape blocksize error\n");
1084: done(3);
1085: }
1086: i /= TBLOCK;
1087: if (i != nblock) {
1088: fprintf(stderr, "tar: blocksize = %d\n", i);
1089: nblock = i;
1090: }
1091: }
1092: recno = 0;
1093: }
1094: first = 1;
1095: bcopy(tbuf[recno++].dummy, buffer, TBLOCK);
1096: return (TBLOCK);
1097: }
1098:
1099: writetape(buffer)
1100: char *buffer;
1101: {
1102: first = 1;
1103: if (recno >= nblock) {
1104: if (write(mt, tbuf[0].dummy, TBLOCK*nblock) < 0) {
1105: fprintf(stderr, "tar: tape write error\n");
1106: done(2);
1107: }
1108: recno = 0;
1109: }
1110: bcopy(buffer, tbuf[recno++].dummy, TBLOCK);
1111: if (recno >= nblock) {
1112: if (write(mt, tbuf[0].dummy, TBLOCK*nblock) < 0) {
1113: fprintf(stderr, "tar: tape write error\n");
1114: done(2);
1115: }
1116: recno = 0;
1117: }
1118: return (TBLOCK);
1119: }
1120:
1121: backtape()
1122: {
1123: static int mtdev = 1;
1124: static struct mtop mtop = {MTBSR, 1};
1125: struct mtget mtget;
1126:
1127: if (mtdev == 1)
1128: mtdev = ioctl(mt, MTIOCGET, &mtget);
1129: if (mtdev == 0) {
1130: if (ioctl(mt, MTIOCTOP, &mtop) < 0) {
1131: fprintf(stderr, "tar: tape backspace error\n");
1132: done(4);
1133: }
1134: } else
1135: lseek(mt, (long) -TBLOCK*nblock, 1);
1136: recno--;
1137: }
1138:
1139: flushtape()
1140: {
1141: write(mt, tbuf[0].dummy, TBLOCK*nblock);
1142: }
1143:
1144: bread(fd, buf, size)
1145: int fd;
1146: char *buf;
1147: int size;
1148: {
1149: int count;
1150: static int lastread = 0;
1151:
1152: if (!Bflag)
1153: return (read(fd, buf, size));
1154: for (count = 0; count < size; count += lastread) {
1155: if (lastread < 0) {
1156: if (count > 0)
1157: return (count);
1158: return (lastread);
1159: }
1160: lastread = read(fd, buf, size - count);
1161: buf += lastread;
1162: }
1163: return (count);
1164: }
1165:
1166: char *
1167: getcwd(buf)
1168: char *buf;
1169: {
1170:
1171: if (getwd(buf) == NULL) {
1172: fprintf(stderr, "tar: %s\n", buf);
1173: exit(1);
1174: }
1175: return (buf);
1176: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.