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