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