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