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