+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+#include <signal.h>
+
+char *sprintf();
+char *strcat();
+daddr_t bsrch();
+#define TBLOCK 512
+#define NBLOCK 20
+#define NAMSIZ 100
+union hblock {
+ char dummy[TBLOCK];
+ struct header {
+ char name[NAMSIZ];
+ char mode[8];
+ char uid[8];
+ char gid[8];
+ char size[12];
+ char mtime[12];
+ char chksum[8];
+ char linkflag;
+ char linkname[NAMSIZ];
+ } dbuf;
+} dblock, tbuf[NBLOCK];
+
+struct linkbuf {
+ ino_t inum;
+ dev_t devnum;
+ int count;
+ char pathname[NAMSIZ];
+ struct linkbuf *nextp;
+} *ihead;
+
+struct stat stbuf;
+
+int rflag, xflag, vflag, tflag, mt, cflag, mflag, fflag;
+int term, chksum, wflag, recno, first, linkerrok;
+int freemem = 1;
+int nblock = 1;
+
+daddr_t low;
+daddr_t high;
+
+FILE *tfile;
+char tname[] = "/tmp/tarXXXXXX";
+
+
+char *usefile;
+char magtape[] = "/dev/mt1";
+
+char *malloc();
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ char *cp;
+ int onintr(), onquit(), onhup(), onterm();
+
+ if (argc < 2)
+ usage();
+
+ tfile = NULL;
+ usefile = magtape;
+ argv[argc] = 0;
+ argv++;
+ for (cp = *argv++; *cp; cp++)
+ switch(*cp) {
+ case 'f':
+ usefile = *argv++;
+ fflag++;
+ if (nblock == 1)
+ nblock = 0;
+ break;
+ case 'c':
+ cflag++;
+ rflag++;
+ break;
+ case 'u':
+ mktemp(tname);
+ if ((tfile = fopen(tname, "w")) == NULL) {
+ fprintf(stderr, "Tar: cannot create temporary file (%s)\n", tname);
+ done(1);
+ }
+ fprintf(tfile, "!!!!!/!/!/!/!/!/!/! 000\n");
+ /* FALL THROUGH */
+ case 'r':
+ rflag++;
+noupdate:
+ if (nblock != 1 && cflag == 0) {
+ fprintf(stderr, "Tar: Blocked tapes cannot be updated (yet)\n");
+ done(1);
+ }
+ break;
+ case 'v':
+ vflag++;
+ break;
+ case 'w':
+ wflag++;
+ break;
+ case 'x':
+ xflag++;
+ break;
+ case 't':
+ tflag++;
+ break;
+ case 'm':
+ mflag++;
+ break;
+ case '-':
+ break;
+ case '0':
+ case '1':
+ case '4':
+ case '5':
+ case '7':
+ case '8':
+ magtape[7] = *cp;
+ usefile = magtape;
+ break;
+ case 'b':
+ nblock = atoi(*argv++);
+ if (nblock > NBLOCK || nblock <= 0) {
+ fprintf(stderr, "Invalid blocksize. (Max %d)\n", NBLOCK);
+ done(1);
+ }
+ if (rflag && !cflag)
+ goto noupdate;
+ break;
+ case 'l':
+ linkerrok++;
+ break;
+ default:
+ fprintf(stderr, "tar: %c: unknown option\n", *cp);
+ usage();
+ }
+
+ if (rflag) {
+ if (cflag && tfile != NULL) {
+ usage();
+ done(1);
+ }
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+ signal(SIGINT, onintr);
+ if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
+ signal(SIGHUP, onhup);
+ if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
+ signal(SIGQUIT, onquit);
+/*
+ if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
+ signal(SIGTERM, onterm);
+*/
+ if (strcmp(usefile, "-") == 0) {
+ if (cflag == 0) {
+ fprintf(stderr, "Can only create standard output archives\n");
+ done(1);
+ }
+ mt = dup(1);
+ nblock = 1;
+ }
+ else if ((mt = open(usefile, 2)) < 0) {
+ if (cflag == 0 || (mt = creat(usefile, 0666)) < 0) {
+ fprintf(stderr, "tar: cannot open %s\n", usefile);
+ done(1);
+ }
+ }
+ if (cflag == 0 && nblock == 0)
+ nblock = 1;
+ dorep(argv);
+ }
+ else if (xflag) {
+ if (strcmp(usefile, "-") == 0) {
+ mt = dup(0);
+ nblock = 1;
+ }
+ else if ((mt = open(usefile, 0)) < 0) {
+ fprintf(stderr, "tar: cannot open %s\n", usefile);
+ done(1);
+ }
+ doxtract(argv);
+ }
+ else if (tflag) {
+ if (strcmp(usefile, "-") == 0) {
+ mt = dup(0);
+ nblock = 1;
+ }
+ else if ((mt = open(usefile, 0)) < 0) {
+ fprintf(stderr, "tar: cannot open %s\n", usefile);
+ done(1);
+ }
+ dotable();
+ }
+ else
+ usage();
+ done(0);
+}
+
+usage()
+{
+ fprintf(stderr, "tar: usage tar -{txru}[cvfblm] [tapefile] [blocksize] file1 file2...\n");
+ done(1);
+}
+
+dorep(argv)
+char *argv[];
+{
+ register char *cp, *cp2;
+ char wdir[60];
+
+ if (!cflag) {
+ getdir();
+ do {
+ passtape();
+ if (term)
+ done(0);
+ getdir();
+ } while (!endtape());
+ if (tfile != NULL) {
+ char buf[200];
+
+ strcat(buf, "sort +0 -1 +1nr ");
+ strcat(buf, tname);
+ strcat(buf, " -o ");
+ strcat(buf, tname);
+ sprintf(buf, "sort +0 -1 +1nr %s -o %s; awk '$1 != prev {print; prev=$1}' %s >%sX;mv %sX %s",
+ tname, tname, tname, tname, tname, tname);
+ fflush(tfile);
+ system(buf);
+ freopen(tname, "r", tfile);
+ fstat(fileno(tfile), &stbuf);
+ high = stbuf.st_size;
+ }
+ }
+
+ getwdir(wdir);
+ while (*argv && ! term) {
+ cp2 = *argv;
+ if (!strcmp(cp2, "-C") && argv[1]) {
+ argv++;
+ if (chdir(*argv) < 0)
+ perror(*argv);
+ else
+ getwdir(wdir);
+ argv++;
+ continue;
+ }
+ for (cp = *argv; *cp; cp++)
+ if (*cp == '/')
+ cp2 = cp;
+ if (cp2 != *argv) {
+ *cp2 = '\0';
+ chdir(*argv);
+ *cp2 = '/';
+ cp2++;
+ }
+ putfile(*argv++, cp2);
+ chdir(wdir);
+ }
+ putempty();
+ putempty();
+ flushtape();
+ if (linkerrok == 1)
+ for (; ihead != NULL; ihead = ihead->nextp)
+ if (ihead->count != 0)
+ fprintf(stderr, "Missing links to %s\n", ihead->pathname);
+}
+
+endtape()
+{
+ if (dblock.dbuf.name[0] == '\0') {
+ backtape();
+ return(1);
+ }
+ else
+ return(0);
+}
+
+getdir()
+{
+ register struct stat *sp;
+ int i;
+
+ readtape( (char *) &dblock);
+ if (dblock.dbuf.name[0] == '\0')
+ return;
+ sp = &stbuf;
+ sscanf(dblock.dbuf.mode, "%o", &i);
+ sp->st_mode = i;
+ sscanf(dblock.dbuf.uid, "%o", &i);
+ sp->st_uid = i;
+ sscanf(dblock.dbuf.gid, "%o", &i);
+ sp->st_gid = i;
+ sscanf(dblock.dbuf.size, "%lo", &sp->st_size);
+ sscanf(dblock.dbuf.mtime, "%lo", &sp->st_mtime);
+ sscanf(dblock.dbuf.chksum, "%o", &chksum);
+ if (chksum != checksum()) {
+ fprintf(stderr, "directory checksum error\n");
+ done(2);
+ }
+ if (tfile != NULL)
+ fprintf(tfile, "%s %s\n", dblock.dbuf.name, dblock.dbuf.mtime);
+}
+
+passtape()
+{
+ long blocks;
+ char buf[TBLOCK];
+
+ if (dblock.dbuf.linkflag == '1')
+ return;
+ blocks = stbuf.st_size;
+ blocks += TBLOCK-1;
+ blocks /= TBLOCK;
+
+ while (blocks-- > 0)
+ readtape(buf);
+}
+
+putfile(longname, shortname)
+char *longname;
+char *shortname;
+{
+ int infile;
+ long blocks;
+ char buf[TBLOCK];
+ register char *cp, *cp2;
+ struct direct dbuf;
+ int i, j;
+
+ infile = open(shortname, 0);
+ if (infile < 0) {
+ fprintf(stderr, "tar: %s: cannot open file\n", longname);
+ return;
+ }
+
+ fstat(infile, &stbuf);
+
+ if (tfile != NULL && checkupdate(longname) == 0) {
+ close(infile);
+ return;
+ }
+ if (checkw('r', longname) == 0) {
+ close(infile);
+ return;
+ }
+
+ if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
+ for (i = 0, cp = buf; *cp++ = longname[i++];);
+ *--cp = '/';
+ cp++;
+ i = 0;
+ chdir(shortname);
+ while (read(infile, (char *)&dbuf, sizeof(dbuf)) > 0 && !term) {
+ if (dbuf.d_ino == 0) {
+ i++;
+ continue;
+ }
+ if (strcmp(".", dbuf.d_name) == 0 || strcmp("..", dbuf.d_name) == 0) {
+ i++;
+ continue;
+ }
+ cp2 = cp;
+ for (j=0; j < DIRSIZ; j++)
+ *cp2++ = dbuf.d_name[j];
+ *cp2 = '\0';
+ close(infile);
+ putfile(buf, cp);
+ infile = open(".", 0);
+ i++;
+ lseek(infile, (long) (sizeof(dbuf) * i), 0);
+ }
+ close(infile);
+ chdir("..");
+ return;
+ }
+ if ((stbuf.st_mode & S_IFMT) != S_IFREG) {
+ fprintf(stderr, "tar: %s is not a file. Not dumped\n", longname);
+ return;
+ }
+
+ tomodes(&stbuf);
+
+ cp2 = longname;
+ for (cp = dblock.dbuf.name, i=0; (*cp++ = *cp2++) && i < NAMSIZ; i++);
+ if (i >= NAMSIZ) {
+ fprintf(stderr, "%s: file name too long\n", longname);
+ close(infile);
+ return;
+ }
+
+ if (stbuf.st_nlink > 1) {
+ struct linkbuf *lp;
+ int found = 0;
+
+ for (lp = ihead; lp != NULL; lp = lp->nextp) {
+ if (lp->inum == stbuf.st_ino && lp->devnum == stbuf.st_dev) {
+ found++;
+ break;
+ }
+ }
+ if (found) {
+ strcpy(dblock.dbuf.linkname, lp->pathname);
+ dblock.dbuf.linkflag = '1';
+ sprintf(dblock.dbuf.chksum, "%6o", checksum());
+ writetape( (char *) &dblock);
+ if (vflag) {
+ fprintf(stderr, "a %s ", longname);
+ fprintf(stderr, "link to %s\n", lp->pathname);
+ }
+ lp->count--;
+ close(infile);
+ return;
+ }
+ else {
+ lp = (struct linkbuf *) malloc(sizeof(*lp));
+ if (lp == NULL) {
+ if (freemem) {
+ fprintf(stderr, "Out of memory. Link information lost\n");
+ freemem = 0;
+ }
+ }
+ else {
+ lp->nextp = ihead;
+ ihead = lp;
+ lp->inum = stbuf.st_ino;
+ lp->devnum = stbuf.st_dev;
+ lp->count = stbuf.st_nlink - 1;
+ strcpy(lp->pathname, longname);
+ }
+ }
+ }
+
+ blocks = (stbuf.st_size + (TBLOCK-1)) / TBLOCK;
+ if (vflag) {
+ fprintf(stderr, "a %s ", longname);
+ fprintf(stderr, "%ld blocks\n", blocks);
+ }
+ sprintf(dblock.dbuf.chksum, "%6o", checksum());
+ writetape( (char *) &dblock);
+
+ while ((i = read(infile, buf, TBLOCK)) > 0 && blocks > 0) {
+ writetape(buf);
+ blocks--;
+ }
+ close(infile);
+ if (blocks != 0 || i != 0)
+ fprintf(stderr, "%s: file changed size\n", longname);
+ while (blocks-- > 0)
+ putempty();
+}
+
+
+
+doxtract(argv)
+char *argv[];
+{
+ long blocks, bytes;
+ char buf[TBLOCK];
+ char **cp;
+ int ofile;
+
+ for (;;) {
+ getdir();
+ if (endtape())
+ break;
+
+ if (*argv == 0)
+ goto gotit;
+
+ for (cp = argv; *cp; cp++)
+ if (prefix(*cp, dblock.dbuf.name))
+ goto gotit;
+ passtape();
+ continue;
+
+gotit:
+ if (checkw('x', dblock.dbuf.name) == 0) {
+ passtape();
+ continue;
+ }
+
+ checkdir(dblock.dbuf.name);
+
+ if (dblock.dbuf.linkflag == '1') {
+ unlink(dblock.dbuf.name);
+ if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) {
+ fprintf(stderr, "%s: cannot link\n", dblock.dbuf.name);
+ continue;
+ }
+ if (vflag)
+ fprintf(stderr, "%s linked to %s\n", dblock.dbuf.name, dblock.dbuf.linkname);
+ continue;
+ }
+ if ((ofile = creat(dblock.dbuf.name, stbuf.st_mode & 07777)) < 0) {
+ fprintf(stderr, "tar: %s - cannot create\n", dblock.dbuf.name);
+ passtape();
+ continue;
+ }
+
+ chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid);
+
+ blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK;
+ if (vflag)
+ fprintf(stderr, "x %s, %ld bytes, %ld tape blocks\n", dblock.dbuf.name, bytes, blocks);
+ while (blocks-- > 0) {
+ readtape(buf);
+ if (bytes > TBLOCK) {
+ if (write(ofile, buf, TBLOCK) < 0) {
+ fprintf(stderr, "tar: %s: HELP - extract write error\n", dblock.dbuf.name);
+ done(2);
+ }
+ } else
+ if (write(ofile, buf, (int) bytes) < 0) {
+ fprintf(stderr, "tar: %s: HELP - extract write error\n", dblock.dbuf.name);
+ done(2);
+ }
+ bytes -= TBLOCK;
+ }
+ close(ofile);
+ if (mflag == 0) {
+ time_t timep[2];
+
+ timep[0] = time(NULL);
+ timep[1] = stbuf.st_mtime;
+ utime(dblock.dbuf.name, timep);
+ }
+ }
+}
+
+dotable()
+{
+ for (;;) {
+ getdir();
+ if (endtape())
+ break;
+ if (vflag)
+ longt(&stbuf);
+ printf("%s", dblock.dbuf.name);
+ if (dblock.dbuf.linkflag == '1')
+ printf(" linked to %s", dblock.dbuf.linkname);
+ printf("\n");
+ passtape();
+ }
+}
+
+putempty()
+{
+ char buf[TBLOCK];
+ char *cp;
+
+ for (cp = buf; cp < &buf[TBLOCK]; )
+ *cp++ = '\0';
+ writetape(buf);
+}
+
+longt(st)
+register struct stat *st;
+{
+ register char *cp;
+ char *ctime();
+
+ pmode(st);
+ printf("%3d/%1d", st->st_uid, st->st_gid);
+ printf("%7D", st->st_size);
+ cp = ctime(&st->st_mtime);
+ printf(" %-12.12s %-4.4s ", cp+4, cp+20);
+}
+
+#define SUID 04000
+#define SGID 02000
+#define ROWN 0400
+#define WOWN 0200
+#define XOWN 0100
+#define RGRP 040
+#define WGRP 020
+#define XGRP 010
+#define ROTH 04
+#define WOTH 02
+#define XOTH 01
+#define STXT 01000
+int m1[] = { 1, ROWN, 'r', '-' };
+int m2[] = { 1, WOWN, 'w', '-' };
+int m3[] = { 2, SUID, 's', XOWN, 'x', '-' };
+int m4[] = { 1, RGRP, 'r', '-' };
+int m5[] = { 1, WGRP, 'w', '-' };
+int m6[] = { 2, SGID, 's', XGRP, 'x', '-' };
+int m7[] = { 1, ROTH, 'r', '-' };
+int m8[] = { 1, WOTH, 'w', '-' };
+int m9[] = { 2, STXT, 't', XOTH, 'x', '-' };
+
+int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};
+
+pmode(st)
+register struct stat *st;
+{
+ register int **mp;
+
+ for (mp = &m[0]; mp < &m[9];)
+ select(*mp++, st);
+}
+
+select(pairp, st)
+int *pairp;
+struct stat *st;
+{
+ register int n, *ap;
+
+ ap = pairp;
+ n = *ap++;
+ while (--n>=0 && (st->st_mode&*ap++)==0)
+ ap++;
+ printf("%c", *ap);
+}
+
+checkdir(name)
+register char *name;
+{
+ register char *cp;
+ int i;
+ for (cp = name; *cp; cp++) {
+ if (*cp == '/') {
+ *cp = '\0';
+ if (access(name, 01) < 0) {
+ register int pid, rp;
+
+ if ((pid = fork()) == 0) {
+ execl("/bin/mkdir", "mkdir", name, 0);
+ execl("/usr/bin/mkdir", "mkdir", name, 0);
+ fprintf(stderr, "tar: cannot find mkdir!\n");
+ done(0);
+ }
+ while ((rp = wait(&i)) >= 0 && rp != pid)
+ ;
+ chown(name, stbuf.st_uid, stbuf.st_gid);
+ }
+ *cp = '/';
+ }
+ }
+}
+
+onintr()
+{
+ signal(SIGINT, SIG_IGN);
+ term++;
+}
+
+onquit()
+{
+ signal(SIGQUIT, SIG_IGN);
+ term++;
+}
+
+onhup()
+{
+ signal(SIGHUP, SIG_IGN);
+ term++;
+}
+
+onterm()
+{
+ signal(SIGTERM, SIG_IGN);
+ term++;
+}
+
+tomodes(sp)
+register struct stat *sp;
+{
+ register char *cp;
+
+ for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
+ *cp = '\0';
+ sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777);
+ sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid);
+ sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid);
+ sprintf(dblock.dbuf.size, "%11lo ", sp->st_size);
+ sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime);
+}
+
+checksum()
+{
+ register i;
+ register char *cp;
+
+ for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++)
+ *cp = ' ';
+ i = 0;
+ for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
+ i += *cp;
+ return(i);
+}
+
+checkw(c, name)
+char *name;
+{
+ if (wflag) {
+ printf("%c ", c);
+ if (vflag)
+ longt(&stbuf);
+ printf("%s: ", name);
+ if (response() == 'y'){
+ return(1);
+ }
+ return(0);
+ }
+ return(1);
+}
+
+response()
+{
+ char c;
+
+ c = getchar();
+ if (c != '\n')
+ while (getchar() != '\n');
+ else c = 'n';
+ return(c);
+}
+
+checkupdate(arg)
+char *arg;
+{
+ char name[100];
+ long mtime;
+ daddr_t seekp;
+ daddr_t lookup();
+
+ rewind(tfile);
+ for (;;) {
+ if ((seekp = lookup(arg)) < 0)
+ return(1);
+ fseek(tfile, seekp, 0);
+ fscanf(tfile, "%s %lo", name, &mtime);
+ if (stbuf.st_mtime > mtime)
+ return(1);
+ else
+ return(0);
+ }
+}
+
+done(n)
+{
+ unlink(tname);
+ exit(n);
+}
+
+prefix(s1, s2)
+register char *s1, *s2;
+{
+ while (*s1)
+ if (*s1++ != *s2++)
+ return(0);
+ if (*s2)
+ return(*s2 == '/');
+ return(1);
+}
+
+getwdir(s)
+char *s;
+{
+ int i;
+ int pipdes[2];
+
+ pipe(pipdes);
+ if ((i = fork()) == 0) {
+ close(1);
+ dup(pipdes[1]);
+ execl("/bin/pwd", "pwd", 0);
+ execl("/usr/bin/pwd", "pwd", 0);
+ fprintf(stderr, "pwd failed!\n");
+ printf("/\n");
+ exit(1);
+ }
+ while (wait((int *)NULL) != -1)
+ ;
+ read(pipdes[0], s, 50);
+ while(*s != '\n')
+ s++;
+ *s = '\0';
+ close(pipdes[0]);
+ close(pipdes[1]);
+}
+
+#define N 200
+int njab;
+daddr_t
+lookup(s)
+char *s;
+{
+ register i;
+ daddr_t a;
+
+ for(i=0; s[i]; i++)
+ if(s[i] == ' ')
+ break;
+ a = bsrch(s, i, low, high);
+ return(a);
+}
+
+daddr_t
+bsrch(s, n, l, h)
+daddr_t l, h;
+char *s;
+{
+ register i, j;
+ char b[N];
+ daddr_t m, m1;
+
+ njab = 0;
+
+loop:
+ if(l >= h)
+ return(-1L);
+ m = l + (h-l)/2 - N/2;
+ if(m < l)
+ m = l;
+ fseek(tfile, m, 0);
+ fread(b, 1, N, tfile);
+ njab++;
+ for(i=0; i<N; i++) {
+ if(b[i] == '\n')
+ break;
+ m++;
+ }
+ if(m >= h)
+ return(-1L);
+ m1 = m;
+ j = i;
+ for(i++; i<N; i++) {
+ m1++;
+ if(b[i] == '\n')
+ break;
+ }
+ i = cmp(b+j, s, n);
+ if(i < 0) {
+ h = m;
+ goto loop;
+ }
+ if(i > 0) {
+ l = m1;
+ goto loop;
+ }
+ return(m);
+}
+
+cmp(b, s, n)
+char *b, *s;
+{
+ register i;
+
+ if(b[0] != '\n')
+ exit(2);
+ for(i=0; i<n; i++) {
+ if(b[i+1] > s[i])
+ return(-1);
+ if(b[i+1] < s[i])
+ return(1);
+ }
+ return(b[i+1] == ' '? 0 : -1);
+}
+
+readtape(buffer)
+char *buffer;
+{
+ int i, j;
+
+ if (recno >= nblock || first == 0) {
+ if (first == 0 && nblock == 0)
+ j = fflag ? NBLOCK : 1; /* orignally, NBLOCK; */
+ else
+ j = nblock;
+ if ((i = read(mt, tbuf, TBLOCK*j)) < 0) {
+ fprintf(stderr, "Tar: tape read error\n");
+ done(3);
+ }
+ if (first == 0) {
+ if ((i % TBLOCK) != 0) {
+ fprintf(stderr, "Tar: tape blocksize error\n");
+ done(3);
+ }
+ i /= TBLOCK;
+ if (rflag && i != 1) {
+ fprintf(stderr, "Tar: Cannot update blocked tapes (yet)\n");
+ done(4);
+ }
+ if (i != nblock && (i != 1 || nblock == 0)) {
+ fprintf(stderr, "Tar: blocksize = %d\n", i);
+ nblock = i;
+ }
+ }
+ recno = 0;
+ }
+ first = 1;
+ copy(buffer, &tbuf[recno++]);
+ return(TBLOCK);
+}
+
+writetape(buffer)
+char *buffer;
+{
+ first = 1;
+ if (nblock == 0)
+ nblock = 1;
+ if (recno >= nblock) {
+ if (write(mt, tbuf, TBLOCK*nblock) < 0) {
+ fprintf(stderr, "Tar: tape write error\n");
+ done(2);
+ }
+ recno = 0;
+ }
+ copy(&tbuf[recno++], buffer);
+ if (recno >= nblock) {
+ if (write(mt, tbuf, TBLOCK*nblock) < 0) {
+ fprintf(stderr, "Tar: tape write error\n");
+ done(2);
+ }
+ recno = 0;
+ }
+ return(TBLOCK);
+}
+
+backtape()
+{
+ lseek(mt, (long) -TBLOCK, 1);
+ if (recno >= nblock) {
+ recno = nblock - 1;
+ if (read(mt, tbuf, TBLOCK*nblock) < 0) {
+ fprintf(stderr, "Tar: tape read error after seek\n");
+ done(4);
+ }
+ lseek(mt, (long) -TBLOCK, 1);
+ }
+}
+
+flushtape()
+{
+ write(mt, tbuf, TBLOCK*nblock);
+}
+
+copy(to, from)
+register char *to, *from;
+{
+ register i;
+
+ i = TBLOCK;
+ do {
+ *to++ = *from++;
+ } while (--i);
+}