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