X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/2cb5dabb2224b14ce8750c443bb39f0821b0615e..c9e0e8d3983dcc8039d47f0dd1e148cc350e6033:/usr/src/sbin/restore/tape.c diff --git a/usr/src/sbin/restore/tape.c b/usr/src/sbin/restore/tape.c index 20b25c1f3e..8615f6eac6 100644 --- a/usr/src/sbin/restore/tape.c +++ b/usr/src/sbin/restore/tape.c @@ -1,7 +1,7 @@ /* Copyright (c) 1983 Regents of the University of California */ #ifndef lint -static char sccsid[] = "@(#)tape.c 3.2 (Berkeley) 83/02/26"; +static char sccsid[] = "@(#)tape.c 3.15 (Berkeley) 83/05/06"; #endif #include "restore.h" @@ -16,7 +16,6 @@ static long fssize; static int mt = -1; static int pipein = 0; static char *magtape; -static int insetup = 0; static int bct = NTREC+1; static char tbf[NTREC*TP_BSIZE]; static union u_spcl endoftapemark; @@ -43,7 +42,7 @@ setinput(source) magtape = index(host, ':'); if (magtape == 0) { nohost: - msg("need keyletter ``f'' and device ``host:tape''"); + msg("need keyletter ``f'' and device ``host:tape''\n"); done(1); } *magtape++ = '\0'; @@ -51,9 +50,19 @@ nohost: done(1); setuid(getuid()); /* no longer need or want root privileges */ #else - if (strcmp(source, "-") == 0) { + if (strcmp(source, "-") != 0) { + terminal = stdin; + } else { + /* + * Since input is coming from a pipe we must establish + * our own connection to the terminal. + */ + terminal = fopen("/dev/tty", "r"); + if (terminal == NULL) { + perror("open(\"/dev/tty\")"); + done(1); + } pipein++; - yflag++; } magtape = source; #endif RRESTOR @@ -66,13 +75,11 @@ nohost: setup() { int i, j, *ip; - struct mtop tcom; struct stat stbuf; extern char *ctime(); extern int xtrmap(), xtrmapskip(); vprintf(stdout, "Verify tape and initialize maps\n"); - insetup = 1; #ifdef RRESTOR if ((mt = rmtopen(magtape, 0)) < 0) #else @@ -84,26 +91,13 @@ setup() fprintf(stderr, "%s: cannot open tape\n", magtape); done(1); } - if (dumpnum != 1) { - if (pipein) { - fprintf(stderr, - "Cannot have multiple dumps on pipe input\n"); - done(1); - } - tcom.mt_op = MTFSF; - tcom.mt_count = dumpnum - 1; -#ifdef RRESTOR - rmtioctl(MTFSF, dumpnum - 1); -#else - if (ioctl(mt, MTIOCTOP, &tcom) < 0) - perror("ioctl MTFSF"); -#endif - } + volno = 1; + setdumpnum(); flsht(); - if (readhdr(&spcl) == FAIL) { + if (gethead(&spcl) == FAIL) { bct--; /* push back this block */ cvtflag++; - if (readhdr(&spcl) == FAIL) { + if (gethead(&spcl) == FAIL) { fprintf(stderr, "Tape is not a dump tape\n"); done(1); } @@ -120,8 +114,10 @@ setup() while (--j); endoftapemark.s_spcl.c_checksum = CHECKSUM - i; } - vprintf(stdout, "Dump date: %s", ctime(&spcl.c_date)); - vprintf(stdout, "Dumped from: %s", ctime(&spcl.c_ddate)); + if (vflag || command == 't') { + fprintf(stdout, "Dump date: %s", ctime(&spcl.c_date)); + fprintf(stdout, "Dumped from: %s", ctime(&spcl.c_ddate)); + } dumptime = spcl.c_ddate; dumpdate = spcl.c_date; if (stat(".", &stbuf) < 0) { @@ -145,24 +141,23 @@ setup() done(1); } maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1; - dprintf(stderr, "maxino = %d\n", maxino); - map = (char *)calloc(1, (int)howmany(maxino, NBBY)); + dprintf(stdout, "maxino = %d\n", maxino); + map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); if (map == (char *)NIL) panic("no memory for file removal list\n"); + clrimap = map; curfile.action = USING; getfile(xtrmap, xtrmapskip); - clrimap = map; if (checktype(&spcl, TS_BITS) == FAIL) { fprintf(stderr, "Cannot find file dump list\n"); done(1); } - map = (char *)calloc(1, (int)howmany(maxino, NBBY)); + map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); if (map == (char *)NULL) panic("no memory for file dump list\n"); + dumpmap = map; curfile.action = USING; getfile(xtrmap, xtrmapskip); - dumpmap = map; - insetup = 0; } getvol(nextvol) @@ -173,31 +168,29 @@ getvol(nextvol) union u_spcl tmpspcl; # define tmpbuf tmpspcl.s_spcl - if (dumpnum > 1) { - /* - * if this is a multi-dump tape we always start with - * volume 1, so as to avoid accidentally restoring - * from a different dump! - */ - if (volno != 1) - panic("multiple dump at volno %d\n", volno); - dumpnum = 1; - } if (pipein) { - if (volno != 1 || newvol != 1) + if (nextvol != 1) panic("Changing volumes on pipe input?\n"); - return; + if (volno == 1) + return; + goto gethdr; } savecnt = blksread; again: + if (pipein) + done(1); /* pipes do not get a second chance */ if (command == 'R' || command == 'r' || curfile.action != SKIP) newvol = nextvol; else newvol = 0; while (newvol <= 0) { - fprintf(stderr, "Specify volume #: "); - if (gets(tbf) == NULL) - continue; + do { + fprintf(stderr, "Specify next volume #: "); + (void) fflush(stderr); + (void) fgets(tbf, BUFSIZ, terminal); + } while (!feof(terminal) && tbf[0] == '\n'); + if (feof(terminal)) + done(1); newvol = atoi(tbf); if (newvol <= 0) { fprintf(stderr, @@ -207,8 +200,9 @@ again: if (newvol == volno) return; closemt(); - fprintf(stderr, "Mount tape volume %d then type return: ", newvol); - while (getchar() != '\n') + fprintf(stderr, "Mount tape volume %d then type return ", newvol); + (void) fflush(stderr); + while (getc(terminal) != '\n') ; #ifdef RRESTOR if ((mt = rmtopen(magtape, 0)) == -1) @@ -219,7 +213,9 @@ again: fprintf(stderr, "Cannot open tape!\n"); goto again; } +gethdr: volno = newvol; + setdumpnum(); flsht(); if (readhdr(&tmpbuf) == FAIL) { fprintf(stderr, "tape is not dump tape\n"); @@ -232,16 +228,19 @@ again: goto again; } if (tmpbuf.c_date != dumpdate || tmpbuf.c_ddate != dumptime) { - fprintf(stderr, "Wrong dump date (%s)\n", ctime(tmpbuf.c_date)); + fprintf(stderr, "Wrong dump date\n\tgot: %s", + ctime(&tmpbuf.c_date)); + fprintf(stderr, "\twanted: %s", ctime(&dumpdate)); volno = 0; goto again; } + blksread = savecnt; if (curfile.action == USING) { if (volno == 1) panic("active file into volume 1\n"); - blksread = savecnt; return; } + (void) gethead(&spcl); findinode(&spcl, curfile.action == UNKNOWN ? 1 : 0); if (gettingfile) { gettingfile = 0; @@ -249,6 +248,30 @@ again: } } +/* + * handle multiple dumps per tape by skipping forward to the + * appropriate one. + */ +setdumpnum() +{ + struct mtop tcom; + + if (dumpnum == 1 || volno != 1) + return; + if (pipein) { + fprintf(stderr, "Cannot have multiple dumps on pipe input\n"); + done(1); + } + tcom.mt_op = MTFSF; + tcom.mt_count = dumpnum - 1; +#ifdef RRESTOR + rmtioctl(MTFSF, dumpnum - 1); +#else + if (ioctl(mt, (int)MTIOCTOP, (char *)&tcom) < 0) + perror("ioctl MTFSF"); +#endif +} + extractfile(name) char *name; { @@ -305,8 +328,8 @@ extractfile(name) skipfile(); return (FAIL); } - chown(name, curfile.dip->di_uid, curfile.dip->di_gid); - chmod(name, mode); + (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid); + (void) chmod(name, mode); skipfile(); utime(name, timep); return (GOOD); @@ -318,16 +341,30 @@ extractfile(name) skipfile(); return (FAIL); } - fchown(ofile, curfile.dip->di_uid, curfile.dip->di_gid); - fchmod(ofile, mode); + (void) fchown(ofile, curfile.dip->di_uid, curfile.dip->di_gid); + (void) fchmod(ofile, mode); getfile(xtrfile, xtrskip); - close(ofile); + (void) close(ofile); utime(name, timep); return (GOOD); } /* NOTREACHED */ } +/* + * skip over bit maps on the tape + */ +skipmaps() +{ + + while (checktype(&spcl, TS_CLRI) == GOOD || + checktype(&spcl, TS_BITS) == GOOD) + skipfile(); +} + +/* + * skip over a file on the tape + */ skipfile() { extern int null(); @@ -351,9 +388,9 @@ getfile(f1, f2) if (checktype(&spcl, TS_END) == GOOD) panic("ran off end of tape\n"); - if (!insetup && checktype(&spcl, TS_INODE) == FAIL) + if (ishead(&spcl) == FAIL) panic("not at beginning of a file\n"); - if (setjmp(restart) != 0) + if (!gettingfile && setjmp(restart) != 0) return; gettingfile++; loop: @@ -376,21 +413,17 @@ loop: (*f2)(clearedbuf, size > TP_BSIZE ? (long) TP_BSIZE : size); } - if ((size -= TP_BSIZE) <= 0) { - gethead(&spcl); - goto out; - } + if ((size -= TP_BSIZE) <= 0) + break; } - if (gethead(&spcl) == FAIL || checktype(&spcl, TS_ADDR) == FAIL) { - fprintf(stderr, "Missing address (header) block for %s\n", + if (readhdr(&spcl) == GOOD && size > 0) { + if (checktype(&spcl, TS_ADDR) == GOOD) + goto loop; + dprintf(stdout, "Missing address (header) block for %s\n", curfile.name); - goto out; } - goto loop; -out: - if (curblk > 0) { + if (curblk > 0) (*f1)(buf, (curblk * TP_BSIZE) + size); - } findinode(&spcl, 1); gettingfile = 0; } @@ -439,7 +472,7 @@ xtrlnkfile(buf, size) curfile.name, lnkbuf, buf, pathlen); done(1); } - strcat(lnkbuf, buf); + (void) strcat(lnkbuf, buf); } xtrlnkskip(buf, size) @@ -461,6 +494,7 @@ xtrmap(buf, size) { bcopy(buf, map, size); + map += size; } xtrmapskip(buf, size) @@ -470,9 +504,9 @@ xtrmapskip(buf, size) #ifdef lint buf = buf; - size = size; #endif panic("hole in map\n"); + map += size; } null() {;} @@ -485,20 +519,37 @@ readtape(b) char *b; { register long i; - long newvol; + long rd, newvol; + int cnt; if (bct >= NTREC) { for (i = 0; i < NTREC; i++) ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0; bct = 0; + cnt = NTREC*TP_BSIZE; + rd = 0; + getmore: #ifdef RRESTOR - if ((i = rmtread(tbf, NTREC*TP_BSIZE)) < 0) + i = rmtread(&tbf[rd], cnt); #else - if ((i = read(mt, tbf, NTREC*TP_BSIZE)) < 0) + i = read(mt, &tbf[rd], cnt); #endif - { + if (i > 0 && i != NTREC*TP_BSIZE) { + if (!pipein) + panic("partial block read: %d should be %d\n", + i, NTREC*TP_BSIZE); + rd += i; + cnt -= i; + if (cnt > 0) + goto getmore; + i = rd; + } + if (i < 0) { fprintf(stderr, "Tape read error while "); switch (curfile.action) { + default: + fprintf(stderr, "trying to set up tape\n"); + break; case UNKNOWN: fprintf(stderr, "trying to resyncronize\n"); break; @@ -555,7 +606,7 @@ closemt() #ifdef RRESTOR rmtclose(); #else - close(mt); + (void) close(mt); #endif } @@ -573,8 +624,10 @@ readhdr(b) struct s_spcl *b; { - if (gethead(b) == FAIL) + if (gethead(b) == FAIL) { + dprintf(stdout, "readhdr fails at %d blocks\n", blksread); return(FAIL); + } return(GOOD); } @@ -585,6 +638,7 @@ readhdr(b) gethead(buf) struct s_spcl *buf; { + long i; union u_ospcl { char dummy[TP_BSIZE]; struct s_ospcl { @@ -593,14 +647,14 @@ gethead(buf) long c_ddate; long c_volume; long c_tapea; - short c_inumber; + u_short c_inumber; long c_magic; long c_checksum; struct odinode { unsigned short odi_mode; - short odi_nlink; - short odi_uid; - short odi_gid; + u_short odi_nlink; + u_short odi_uid; + u_short odi_gid; long odi_size; long odi_rdev; char odi_addr[36]; @@ -615,14 +669,9 @@ gethead(buf) if (!cvtflag) { readtape((char *)buf); - if (buf->c_magic != NFS_MAGIC || checksum((int *)buf) == FAIL) { - dprintf(stderr, "gethead fails at %d blocks\n", - blksread); + if (buf->c_magic != NFS_MAGIC || checksum((int *)buf) == FAIL) return(FAIL); - } - if (dflag) - accthdr(buf); - return(GOOD); + goto good; } readtape((char *)(&u_ospcl.s_ospcl)); bzero((char *)buf, (long)TP_BSIZE); @@ -646,11 +695,37 @@ gethead(buf) buf->c_count = u_ospcl.s_ospcl.c_count; bcopy(u_ospcl.s_ospcl.c_addr, buf->c_addr, (long)256); if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC || - checksum((int *)(&u_ospcl.s_ospcl)) == FAIL) { - dprintf(stderr, "gethead fails at %d blocks\n", blksread); + checksum((int *)(&u_ospcl.s_ospcl)) == FAIL) return(FAIL); - } buf->c_magic = NFS_MAGIC; + +good: + switch (buf->c_type) { + + case TS_CLRI: + case TS_BITS: + /* + * Have to patch up missing information in bit map headers + */ + buf->c_inumber = 0; + buf->c_dinode.di_size = buf->c_count * TP_BSIZE; + for (i = 0; i < buf->c_count; i++) + buf->c_addr[i]++; + break; + + case TS_TAPE: + case TS_END: + buf->c_inumber = 0; + break; + + case TS_INODE: + case TS_ADDR: + break; + + default: + panic("gethead: unknown inode type %d\n", buf->c_type); + break; + } if (dflag) accthdr(buf); return(GOOD); @@ -662,41 +737,41 @@ gethead(buf) accthdr(header) struct s_spcl *header; { - static ino_t previno = 0; + static ino_t previno = 0x7fffffff; static int prevtype; static long predict; long blks, i; - if (previno == 0) + if (header->c_type == TS_TAPE) { + fprintf(stderr, "Volume header\n"); + return; + } + if (previno == 0x7fffffff) goto newcalc; switch (prevtype) { - case TS_TAPE: - fprintf(stderr, "Volume"); - break; case TS_BITS: - fprintf(stderr, "Dump mask"); + fprintf(stderr, "Dump mask header"); break; case TS_CLRI: - fprintf(stderr, "Remove mask"); + fprintf(stderr, "Remove mask header"); break; case TS_INODE: - fprintf(stderr, "File"); + fprintf(stderr, "File header, ino %d", previno); break; case TS_ADDR: - fprintf(stderr, "File continuation"); + fprintf(stderr, "File continuation header, ino %d", previno); break; case TS_END: - fprintf(stderr, "End of tape"); + fprintf(stderr, "End of tape header"); break; } - fprintf(stderr, " header, ino %d", previno); if (predict != blksread - 1) fprintf(stderr, "; predicted %d blocks, got %d blocks", predict, blksread - 1); fprintf(stderr, "\n"); newcalc: blks = 0; - if (header->c_type != TS_TAPE && header->c_type != TS_END) + if (header->c_type != TS_END) for (i = 0; i < header->c_count; i++) if (header->c_addr[i] != 0) blks++; @@ -715,7 +790,6 @@ findinode(header, complain) int complain; { static long skipcnt = 0; - long i; curfile.name = ""; curfile.action = UNKNOWN; @@ -738,27 +812,17 @@ findinode(header, complain) } if (checktype(header, TS_CLRI) == GOOD) { curfile.name = ""; - header->c_dinode.di_size = header->c_count * TP_BSIZE; - for (i = 0; i < header->c_count; i++) - header->c_addr[i]++; - if (insetup) - break; - skipfile(); + break; } if (checktype(header, TS_BITS) == GOOD) { curfile.name = ""; - header->c_dinode.di_size = header->c_count * TP_BSIZE; - for (i = 0; i < header->c_count; i++) - header->c_addr[i]++; - if (insetup) - break; - skipfile(); + break; } while (gethead(header) == FAIL) skipcnt++; } if (skipcnt > 0 && complain) - fprintf(stderr, "resync restor, skipped %d blocks\n", skipcnt); + fprintf(stderr, "resync restore, skipped %d blocks\n", skipcnt); skipcnt = 0; } @@ -803,6 +867,7 @@ checksum(b) } #ifdef RRESTOR +/* VARARGS1 */ msg(cp, a1, a2, a3) char *cp; {