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