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