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