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