|
|
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/rmt8";
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: if (cp2 != *argv) {
326: *cp2 = '\0';
327: if (chdir(*argv) < 0) {
328: perror(*argv);
329: continue;
330: }
331: parent = getcwd(tempdir);
332: *cp2 = '/';
333: cp2++;
334: }
335: putfile(*argv++, cp2, parent);
336: if (chdir(wdir) < 0) {
337: fprintf(stderr, "cannot change back?: ");
338: perror(wdir);
339: }
340: }
341: putempty();
342: putempty();
343: flushtape();
344: if (linkerrok == 0)
345: return;
346: for (; ihead != NULL; ihead = ihead->nextp) {
347: if (ihead->count == 0)
348: continue;
349: fprintf(stderr, "tar: missing links to %s\n", ihead->pathname);
350: }
351: }
352:
353: endtape()
354: {
355: return (dblock.dbuf.name[0] == '\0');
356: }
357:
358: getdir()
359: {
360: register struct stat *sp;
361: int i;
362:
363: top:
364: readtape((char *)&dblock);
365: if (dblock.dbuf.name[0] == '\0')
366: return;
367: sp = &stbuf;
368: sscanf(dblock.dbuf.mode, "%o", &i);
369: sp->st_mode = i;
370: sscanf(dblock.dbuf.uid, "%o", &i);
371: sp->st_uid = i;
372: sscanf(dblock.dbuf.gid, "%o", &i);
373: sp->st_gid = i;
374: sscanf(dblock.dbuf.size, "%lo", &sp->st_size);
375: sscanf(dblock.dbuf.mtime, "%lo", &sp->st_mtime);
376: sscanf(dblock.dbuf.chksum, "%o", &chksum);
377: if (chksum != (i = checksum())) {
378: fprintf(stderr, "tar: directory checksum error (%d != %d)\n",
379: chksum, i);
380: if (iflag)
381: goto top;
382: done(2);
383: }
384: if (tfile != NULL)
385: fprintf(tfile, "%s %s\n", dblock.dbuf.name, dblock.dbuf.mtime);
386: }
387:
388: passtape()
389: {
390: long blocks;
391: char buf[TBLOCK];
392:
393: if (dblock.dbuf.linkflag == '1')
394: return;
395: blocks = stbuf.st_size;
396: blocks += TBLOCK-1;
397: blocks /= TBLOCK;
398:
399: while (blocks-- > 0)
400: readtape(buf);
401: }
402:
403: putfile(longname, shortname, parent)
404: char *longname;
405: char *shortname;
406: char *parent;
407: {
408: int infile = 0;
409: long blocks;
410: char buf[TBLOCK];
411: register char *cp, *cp2;
412: struct direct *dp;
413: DIR *dirp;
414: int i, j;
415: char newparent[NAMSIZ+64];
416: extern int errno;
417:
418: if (!hflag)
419: i = lstat(shortname, &stbuf);
420: else
421: i = stat(shortname, &stbuf);
422: if (i < 0) {
423: switch (errno) {
424: case EACCES:
425: fprintf(stderr, "tar: %s: cannot open file\n", longname);
426: break;
427: case ENOENT:
428: fprintf(stderr, "tar: %s: no such file or directory\n",
429: longname);
430: break;
431: default:
432: fprintf(stderr, "tar: %s: cannot stat file\n", longname);
433: break;
434: }
435: return;
436: }
437: if (tfile != NULL && checkupdate(longname) == 0)
438: return;
439: if (checkw('r', longname) == 0)
440: return;
441: if (Fflag && checkf(shortname, stbuf.st_mode, Fflag) == 0)
442: return;
443:
444: switch (stbuf.st_mode & S_IFMT) {
445: case S_IFDIR:
446: for (i = 0, cp = buf; *cp++ = longname[i++];)
447: ;
448: *--cp = '/';
449: *++cp = 0 ;
450: if (!oflag) {
451: if ((cp - buf) >= NAMSIZ) {
452: fprintf(stderr, "tar: %s: file name too long\n",
453: longname);
454: return;
455: }
456: stbuf.st_size = 0;
457: tomodes(&stbuf);
458: strcpy(dblock.dbuf.name,buf);
459: sprintf(dblock.dbuf.chksum, "%6o", checksum());
460: writetape((char *)&dblock);
461: }
462: sprintf(newparent, "%s/%s", parent, shortname);
463: if (chdir(shortname) < 0) {
464: perror(shortname);
465: return;
466: }
467: if ((dirp = opendir(".")) == NULL) {
468: fprintf(stderr, "tar: %s: directory read error\n",
469: longname);
470: if (chdir(parent) < 0) {
471: fprintf(stderr, "cannot change back?: ");
472: perror(parent);
473: }
474: return;
475: }
476: while ((dp = readdir(dirp)) != NULL && !term) {
477: if (dp->d_ino == 0)
478: continue;
479: if (!strcmp(".", dp->d_name) ||
480: !strcmp("..", dp->d_name))
481: continue;
482: strcpy(cp, dp->d_name);
483: i = telldir(dirp);
484: closedir(dirp);
485: putfile(buf, cp, newparent);
486: dirp = opendir(".");
487: seekdir(dirp, i);
488: }
489: closedir(dirp);
490: if (chdir(parent) < 0) {
491: fprintf(stderr, "cannot change back?: ");
492: perror(parent);
493: }
494: break;
495:
496: case S_IFLNK:
497: tomodes(&stbuf);
498: if (strlen(longname) >= NAMSIZ) {
499: fprintf(stderr, "tar: %s: file name too long\n",
500: longname);
501: return;
502: }
503: strcpy(dblock.dbuf.name, longname);
504: if (stbuf.st_size + 1 >= NAMSIZ) {
505: fprintf(stderr, "tar: %s: symbolic link too long\n",
506: longname);
507: return;
508: }
509: i = readlink(shortname, dblock.dbuf.linkname, NAMSIZ - 1);
510: if (i < 0) {
511: perror(longname);
512: return;
513: }
514: dblock.dbuf.linkname[i] = '\0';
515: dblock.dbuf.linkflag = '2';
516: if (vflag) {
517: fprintf(stderr, "a %s ", longname);
518: fprintf(stderr, "symbolic link to %s\n",
519: dblock.dbuf.linkname);
520: }
521: sprintf(dblock.dbuf.size, "%11lo", 0);
522: sprintf(dblock.dbuf.chksum, "%6o", checksum());
523: writetape((char *)&dblock);
524: break;
525:
526: case S_IFREG:
527: if ((infile = open(shortname, 0)) < 0) {
528: fprintf(stderr, "tar: %s: cannot open file\n", longname);
529: return;
530: }
531: tomodes(&stbuf);
532: if (strlen(longname) >= NAMSIZ) {
533: fprintf(stderr, "tar: %s: file name too long\n",
534: longname);
535: return;
536: }
537: strcpy(dblock.dbuf.name, longname);
538: if (stbuf.st_nlink > 1) {
539: struct linkbuf *lp;
540: int found = 0;
541:
542: for (lp = ihead; lp != NULL; lp = lp->nextp)
543: if (lp->inum == stbuf.st_ino &&
544: lp->devnum == stbuf.st_dev) {
545: found++;
546: break;
547: }
548: if (found) {
549: strcpy(dblock.dbuf.linkname, lp->pathname);
550: dblock.dbuf.linkflag = '1';
551: sprintf(dblock.dbuf.chksum, "%6o", checksum());
552: writetape( (char *) &dblock);
553: if (vflag) {
554: fprintf(stderr, "a %s ", longname);
555: fprintf(stderr, "link to %s\n",
556: lp->pathname);
557: }
558: lp->count--;
559: close(infile);
560: return;
561: }
562: lp = (struct linkbuf *) malloc(sizeof(*lp));
563: if (lp == NULL) {
564: if (freemem) {
565: fprintf(stderr,
566: "tar: out of memory, link information lost\n");
567: freemem = 0;
568: }
569: } else {
570: lp->nextp = ihead;
571: ihead = lp;
572: lp->inum = stbuf.st_ino;
573: lp->devnum = stbuf.st_dev;
574: lp->count = stbuf.st_nlink - 1;
575: strcpy(lp->pathname, longname);
576: }
577: }
578: blocks = (stbuf.st_size + (TBLOCK-1)) / TBLOCK;
579: if (vflag) {
580: fprintf(stderr, "a %s ", longname);
581: fprintf(stderr, "%ld blocks\n", blocks);
582: }
583: sprintf(dblock.dbuf.chksum, "%6o", checksum());
584: writetape((char *)&dblock);
585:
586: while ((i = read(infile, buf, TBLOCK)) > 0 && blocks > 0) {
587: writetape(buf);
588: blocks--;
589: }
590: close(infile);
591: if (blocks != 0 || i != 0)
592: fprintf(stderr, "tar: %s: file changed size\n",
593: longname);
594: while (--blocks >= 0)
595: putempty();
596: break;
597:
598: default:
599: fprintf(stderr, "tar: %s is not a file. Not dumped\n",
600: longname);
601: break;
602: }
603: }
604:
605: doxtract(argv)
606: char *argv[];
607: {
608: long blocks, bytes;
609: char buf[TBLOCK];
610: char **cp;
611: int ofile;
612:
613: for (;;) {
614: getdir();
615: if (endtape())
616: break;
617: if (*argv == 0)
618: goto gotit;
619: for (cp = argv; *cp; cp++)
620: if (prefix(*cp, dblock.dbuf.name))
621: goto gotit;
622: passtape();
623: continue;
624:
625: gotit:
626: if (checkw('x', dblock.dbuf.name) == 0) {
627: passtape();
628: continue;
629: }
630: if (Fflag) {
631: char *s;
632:
633: if ((s = rindex(dblock.dbuf.name, '/')) == 0)
634: s = dblock.dbuf.name;
635: else
636: s++;
637: if (checkf(s, stbuf.st_mode, Fflag) == 0) {
638: passtape();
639: continue;
640: }
641: }
642: if (checkdir(dblock.dbuf.name))
643: continue;
644: if (dblock.dbuf.linkflag == '2') {
645: unlink(dblock.dbuf.name);
646: if (symlink(dblock.dbuf.linkname, dblock.dbuf.name)<0) {
647: fprintf(stderr, "tar: %s: symbolic link failed\n",
648: dblock.dbuf.name);
649: continue;
650: }
651: if (vflag)
652: fprintf(stderr, "x %s symbolic link to %s\n",
653: dblock.dbuf.name, dblock.dbuf.linkname);
654: #ifdef notdef
655: /* ignore alien orders */
656: chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid);
657: if (mflag == 0) {
658: struct timeval tv[2];
659:
660: tv[0].tv_sec = time(0);
661: tv[0].tv_usec = 0;
662: tv[1].tv_sec = stbuf.st_mtime;
663: tv[1].tv_usec = 0;
664: utimes(dblock.dbuf.name, tv);
665: }
666: if (pflag)
667: chmod(dblock.dbuf.name, stbuf.st_mode & 07777);
668: #endif
669: continue;
670: }
671: if (dblock.dbuf.linkflag == '1') {
672: unlink(dblock.dbuf.name);
673: if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) {
674: fprintf(stderr, "tar: %s: cannot link\n",
675: dblock.dbuf.name);
676: continue;
677: }
678: if (vflag)
679: fprintf(stderr, "%s linked to %s\n",
680: dblock.dbuf.name, dblock.dbuf.linkname);
681: continue;
682: }
683: if ((ofile = creat(dblock.dbuf.name,stbuf.st_mode&0xfff)) < 0) {
684: fprintf(stderr, "tar: %s - cannot create\n",
685: dblock.dbuf.name);
686: passtape();
687: continue;
688: }
689: chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid);
690: blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK;
691: if (vflag)
692: fprintf(stderr, "x %s, %ld bytes, %ld tape blocks\n",
693: dblock.dbuf.name, bytes, blocks);
694: for (; blocks-- > 0; bytes -= TBLOCK) {
695: readtape(buf);
696: if (bytes > TBLOCK) {
697: if (write(ofile, buf, TBLOCK) < 0) {
698: fprintf(stderr,
699: "tar: %s: HELP - extract write error\n",
700: dblock.dbuf.name);
701: done(2);
702: }
703: continue;
704: }
705: if (write(ofile, buf, (int) bytes) < 0) {
706: fprintf(stderr,
707: "tar: %s: HELP - extract write error\n",
708: dblock.dbuf.name);
709: done(2);
710: }
711: }
712: close(ofile);
713: if (mflag == 0) {
714: struct timeval tv[2];
715:
716: tv[0].tv_sec = time(0);
717: tv[0].tv_usec = 0;
718: tv[1].tv_sec = stbuf.st_mtime;
719: tv[1].tv_usec = 0;
720: utimes(dblock.dbuf.name, tv);
721: }
722: if (pflag)
723: chmod(dblock.dbuf.name, stbuf.st_mode & 07777);
724: }
725: }
726:
727: dotable()
728: {
729: for (;;) {
730: getdir();
731: if (endtape())
732: break;
733: if (vflag)
734: longt(&stbuf);
735: printf("%s", dblock.dbuf.name);
736: if (dblock.dbuf.linkflag == '1')
737: printf(" linked to %s", dblock.dbuf.linkname);
738: if (dblock.dbuf.linkflag == '2')
739: printf(" symbolic link to %s", dblock.dbuf.linkname);
740: printf("\n");
741: passtape();
742: }
743: }
744:
745: putempty()
746: {
747: char buf[TBLOCK];
748:
749: bzero(buf, sizeof (buf));
750: writetape(buf);
751: }
752:
753: longt(st)
754: register struct stat *st;
755: {
756: register char *cp;
757: char *ctime();
758:
759: pmode(st);
760: printf("%3d/%1d", st->st_uid, st->st_gid);
761: printf("%7D", st->st_size);
762: cp = ctime(&st->st_mtime);
763: printf(" %-12.12s %-4.4s ", cp+4, cp+20);
764: }
765:
766: #define SUID 04000
767: #define SGID 02000
768: #define ROWN 0400
769: #define WOWN 0200
770: #define XOWN 0100
771: #define RGRP 040
772: #define WGRP 020
773: #define XGRP 010
774: #define ROTH 04
775: #define WOTH 02
776: #define XOTH 01
777: #define STXT 01000
778: int m1[] = { 1, ROWN, 'r', '-' };
779: int m2[] = { 1, WOWN, 'w', '-' };
780: int m3[] = { 2, SUID, 's', XOWN, 'x', '-' };
781: int m4[] = { 1, RGRP, 'r', '-' };
782: int m5[] = { 1, WGRP, 'w', '-' };
783: int m6[] = { 2, SGID, 's', XGRP, 'x', '-' };
784: int m7[] = { 1, ROTH, 'r', '-' };
785: int m8[] = { 1, WOTH, 'w', '-' };
786: int m9[] = { 2, STXT, 't', XOTH, 'x', '-' };
787:
788: int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};
789:
790: pmode(st)
791: register struct stat *st;
792: {
793: register int **mp;
794:
795: for (mp = &m[0]; mp < &m[9];)
796: select(*mp++, st);
797: }
798:
799: select(pairp, st)
800: int *pairp;
801: struct stat *st;
802: {
803: register int n, *ap;
804:
805: ap = pairp;
806: n = *ap++;
807: while (--n>=0 && (st->st_mode&*ap++)==0)
808: ap++;
809: printf("%c", *ap);
810: }
811:
812: checkdir(name)
813: register char *name;
814: {
815: register char *cp;
816:
817: /*
818: * Quick check for existance of directory.
819: */
820: if ((cp = rindex(name, '/')) == 0)
821: return (0);
822: *cp = '\0';
823: if (access(name, 0) >= 0) {
824: *cp = '/';
825: return (cp[1] == '\0');
826: }
827: *cp = '/';
828:
829: /*
830: * No luck, try to make all directories in path.
831: */
832: for (cp = name; *cp; cp++) {
833: if (*cp != '/')
834: continue;
835: *cp = '\0';
836: if (access(name, 0) < 0) {
837: if (mkdir(name, 0777) < 0) {
838: perror(name);
839: *cp = '/';
840: return (0);
841: }
842: chown(name, stbuf.st_uid, stbuf.st_gid);
843: if (pflag && cp[1] == '\0')
844: chmod(name, stbuf.st_mode & 0777);
845: }
846: *cp = '/';
847: }
848: return (cp[-1]=='/');
849: }
850:
851: onintr()
852: {
853: signal(SIGINT, SIG_IGN);
854: term++;
855: }
856:
857: onquit()
858: {
859: signal(SIGQUIT, SIG_IGN);
860: term++;
861: }
862:
863: onhup()
864: {
865: signal(SIGHUP, SIG_IGN);
866: term++;
867: }
868:
869: onterm()
870: {
871: signal(SIGTERM, SIG_IGN);
872: term++;
873: }
874:
875: tomodes(sp)
876: register struct stat *sp;
877: {
878: register char *cp;
879:
880: for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
881: *cp = '\0';
882: sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777);
883: sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid);
884: sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid);
885: sprintf(dblock.dbuf.size, "%11lo ", sp->st_size);
886: sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime);
887: }
888:
889: checksum()
890: {
891: register i;
892: register char *cp;
893:
894: for (cp = dblock.dbuf.chksum;
895: cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++)
896: *cp = ' ';
897: i = 0;
898: for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
899: i += *cp;
900: return (i);
901: }
902:
903: checkw(c, name)
904: char *name;
905: {
906: if (!wflag)
907: return (1);
908: printf("%c ", c);
909: if (vflag)
910: longt(&stbuf);
911: printf("%s: ", name);
912: return (response() == 'y');
913: }
914:
915: response()
916: {
917: char c;
918:
919: c = getchar();
920: if (c != '\n')
921: while (getchar() != '\n')
922: ;
923: else
924: c = 'n';
925: return (c);
926: }
927:
928: checkf(name, mode, howmuch)
929: char *name;
930: int mode, howmuch;
931: {
932: int l;
933:
934: if ((mode & S_IFMT) == S_IFDIR)
935: return (strcmp(name, "SCCS") != 0);
936: if ((l = strlen(name)) < 3)
937: return (1);
938: if (howmuch > 1 && name[l-2] == '.' && name[l-1] == 'o')
939: return (0);
940: if (strcmp(name, "core") == 0 ||
941: strcmp(name, "errs") == 0 ||
942: (howmuch > 1 && strcmp(name, "a.out") == 0))
943: return (0);
944: /* SHOULD CHECK IF IT IS EXECUTABLE */
945: return (1);
946: }
947:
948: checkupdate(arg)
949: char *arg;
950: {
951: char name[100];
952: long mtime;
953: daddr_t seekp;
954: daddr_t lookup();
955:
956: rewind(tfile);
957: for (;;) {
958: if ((seekp = lookup(arg)) < 0)
959: return (1);
960: fseek(tfile, seekp, 0);
961: fscanf(tfile, "%s %lo", name, &mtime);
962: return (stbuf.st_mtime > mtime);
963: }
964: }
965:
966: done(n)
967: {
968: unlink(tname);
969: exit(n);
970: }
971:
972: prefix(s1, s2)
973: register char *s1, *s2;
974: {
975: while (*s1)
976: if (*s1++ != *s2++)
977: return (0);
978: if (*s2)
979: return (*s2 == '/');
980: return (1);
981: }
982:
983: #define N 200
984: int njab;
985:
986: daddr_t
987: lookup(s)
988: char *s;
989: {
990: register i;
991: daddr_t a;
992:
993: for(i=0; s[i]; i++)
994: if (s[i] == ' ')
995: break;
996: a = bsrch(s, i, low, high);
997: return (a);
998: }
999:
1000: daddr_t
1001: bsrch(s, n, l, h)
1002: daddr_t l, h;
1003: char *s;
1004: {
1005: register i, j;
1006: char b[N];
1007: daddr_t m, m1;
1008:
1009: njab = 0;
1010:
1011: loop:
1012: if (l >= h)
1013: return (-1L);
1014: m = l + (h-l)/2 - N/2;
1015: if (m < l)
1016: m = l;
1017: fseek(tfile, m, 0);
1018: fread(b, 1, N, tfile);
1019: njab++;
1020: for(i=0; i<N; i++) {
1021: if (b[i] == '\n')
1022: break;
1023: m++;
1024: }
1025: if (m >= h)
1026: return (-1L);
1027: m1 = m;
1028: j = i;
1029: for(i++; i<N; i++) {
1030: m1++;
1031: if (b[i] == '\n')
1032: break;
1033: }
1034: i = cmp(b+j, s, n);
1035: if (i < 0) {
1036: h = m;
1037: goto loop;
1038: }
1039: if (i > 0) {
1040: l = m1;
1041: goto loop;
1042: }
1043: return (m);
1044: }
1045:
1046: cmp(b, s, n)
1047: char *b, *s;
1048: {
1049: register i;
1050:
1051: if (b[0] != '\n')
1052: exit(2);
1053: for(i=0; i<n; i++) {
1054: if (b[i+1] > s[i])
1055: return (-1);
1056: if (b[i+1] < s[i])
1057: return (1);
1058: }
1059: return (b[i+1] == ' '? 0 : -1);
1060: }
1061:
1062: readtape(buffer)
1063: char *buffer;
1064: {
1065: register int i;
1066:
1067: if (recno >= nblock || first == 0) {
1068: if ((i = bread(mt, tbuf, TBLOCK*nblock)) < 0) {
1069: fprintf(stderr, "tar: tape read error\n");
1070: done(3);
1071: }
1072: if (first == 0) {
1073: if ((i % TBLOCK) != 0) {
1074: fprintf(stderr, "tar: tape blocksize error\n");
1075: done(3);
1076: }
1077: i /= TBLOCK;
1078: if (i != nblock) {
1079: fprintf(stderr, "tar: blocksize = %d\n", i);
1080: nblock = i;
1081: }
1082: }
1083: recno = 0;
1084: }
1085: first = 1;
1086: bcopy((char *)&tbuf[recno++], buffer, TBLOCK);
1087: return (TBLOCK);
1088: }
1089:
1090: writetape(buffer)
1091: char *buffer;
1092: {
1093: first = 1;
1094: if (recno >= nblock) {
1095: if (write(mt, tbuf, TBLOCK*nblock) < 0) {
1096: fprintf(stderr, "tar: tape write error\n");
1097: done(2);
1098: }
1099: recno = 0;
1100: }
1101: bcopy(buffer, (char *)&tbuf[recno++], TBLOCK);
1102: if (recno >= nblock) {
1103: if (write(mt, tbuf, TBLOCK*nblock) < 0) {
1104: fprintf(stderr, "tar: tape write error\n");
1105: done(2);
1106: }
1107: recno = 0;
1108: }
1109: return (TBLOCK);
1110: }
1111:
1112: backtape()
1113: {
1114: static int mtdev = 1;
1115: static struct mtop mtop = {MTBSR, 1};
1116: struct mtget mtget;
1117:
1118: if (mtdev == 1)
1119: mtdev = ioctl(mt, MTIOCGET, &mtget);
1120: if (mtdev == 0) {
1121: if (ioctl(mt, MTIOCTOP, &mtop) < 0) {
1122: fprintf(stderr, "tar: tape backspace error\n");
1123: done(4);
1124: }
1125: } else
1126: lseek(mt, (long) -TBLOCK*nblock, 1);
1127: recno--;
1128: }
1129:
1130: flushtape()
1131: {
1132: write(mt, tbuf, TBLOCK*nblock);
1133: }
1134:
1135: bread(fd, buf, size)
1136: int fd;
1137: char *buf;
1138: int size;
1139: {
1140: int count;
1141: static int lastread = 0;
1142:
1143: if (!Bflag)
1144: return (read(fd, buf, size));
1145: for (count = 0; count < size; count += lastread) {
1146: if (lastread < 0) {
1147: if (count > 0)
1148: return (count);
1149: return (lastread);
1150: }
1151: lastread = read(fd, buf, size - count);
1152: buf += lastread;
1153: }
1154: return (count);
1155: }
1156:
1157: char *
1158: getcwd(buf)
1159: char *buf;
1160: {
1161:
1162: if (getwd(buf) == NULL) {
1163: fprintf(stderr, "tar: %s\n", buf);
1164: exit(1);
1165: }
1166: return (buf);
1167: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.