diff options
Diffstat (limited to 'sbin/restore/tape.c')
-rw-r--r-- | sbin/restore/tape.c | 277 |
1 files changed, 117 insertions, 160 deletions
diff --git a/sbin/restore/tape.c b/sbin/restore/tape.c index c40c7a9..2b2ab91 100644 --- a/sbin/restore/tape.c +++ b/sbin/restore/tape.c @@ -74,20 +74,19 @@ static int numtrec; static char *tapebuf; static union u_spcl endoftapemark; static long blksread; /* blocks read since last header */ -static long tapeaddr = 0; /* current TP_BSIZE tape record */ +static int64_t tapeaddr = 0; /* current TP_BSIZE tape record */ static long tapesread; static jmp_buf restart; static int gettingfile = 0; /* restart has a valid frame */ static char *host = NULL; +static int readmapflag; static int ofile; static char *map; static char lnkbuf[MAXPATHLEN + 1]; static int pathlen; -int oldinofmt; /* old inode format conversion required */ -int Bcvt; /* Swap Bytes (for CCI or sun) */ -static int Qcvt; /* Swap quads (for sun) */ +int Bcvt; /* Swap Bytes */ #define FLUSHTAPEBUF() blkcnt = ntrec + 1 @@ -109,8 +108,6 @@ static void xtrmap(char *, long); static void xtrmapskip(char *, long); static void xtrskip(char *, long); -static int readmapflag; - /* * Set up an input source */ @@ -207,17 +204,11 @@ setup(void) if (!pipein && !bflag) findtapeblksize(); if (gethead(&spcl) == FAIL) { - blkcnt--; /* push back this block */ - blksread--; - cvtflag++; - if (gethead(&spcl) == FAIL) { - fprintf(stderr, "Tape is not a dump tape\n"); - done(1); - } - fprintf(stderr, "Converting to new filesystem format.\n"); + fprintf(stderr, "Tape is not a dump tape\n"); + done(1); } if (pipein) { - endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : NFS_MAGIC; + endoftapemark.s_spcl.c_magic = FS_UFS2_MAGIC; endoftapemark.s_spcl.c_type = TS_END; ip = (int *)&endoftapemark; j = sizeof(union u_spcl) / sizeof(int); @@ -229,8 +220,8 @@ setup(void) } if (vflag || command == 't') printdumpinfo(); - dumptime = _time32_to_time(spcl.c_ddate); - dumpdate = _time32_to_time(spcl.c_date); + dumptime = _time64_to_time(spcl.c_ddate); + dumpdate = _time64_to_time(spcl.c_date); if (stat(".", &stbuf) < 0) { fprintf(stderr, "cannot stat .: %s\n", strerror(errno)); done(1); @@ -279,8 +270,7 @@ setup(void) * whiteout inode exists, so that the whiteout entries can be * extracted. */ - if (oldinofmt == 0) - SETINO(WINO, dumpmap); + SETINO(WINO, dumpmap); /* 'r' restores don't call getvol() for tape 1, so mark it as read. */ if (command == 'r') tapesread = 1; @@ -296,7 +286,8 @@ setup(void) void getvol(long nextvol) { - long newvol, prevtapea, savecnt, i; + int64_t prevtapea; + long i, newvol, savecnt; union u_spcl tmpspcl; # define tmpbuf tmpspcl.s_spcl char buf[TP_BSIZE]; @@ -403,9 +394,9 @@ gethdr: volno = 0; goto again; } - if (_time32_to_time(tmpbuf.c_date) != dumpdate || - _time32_to_time(tmpbuf.c_ddate) != dumptime) { - time_t t = _time32_to_time(tmpbuf.c_date); + if (_time64_to_time(tmpbuf.c_date) != dumpdate || + _time64_to_time(tmpbuf.c_ddate) != dumptime) { + time_t t = _time64_to_time(tmpbuf.c_date); fprintf(stderr, "Wrong dump date\n\tgot: %s", ctime(&t)); fprintf(stderr, "\twanted: %s", ctime(&dumpdate)); volno = 0; @@ -420,9 +411,9 @@ gethdr: * If coming to this volume at random, skip to the beginning * of the next record. */ - dprintf(stdout, "last rec %ld, tape starts with %ld\n", prevtapea, + dprintf(stdout, "last rec %qd, tape starts with %qd\n", prevtapea, tmpbuf.c_tapea); - if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) { + if (tmpbuf.c_type == TS_TAPE) { if (curfile.action != USING) { /* * XXX Dump incorrectly sets c_count to 1 in the @@ -475,7 +466,7 @@ terminateinput(void) } curfile.name = "<name unknown>"; curfile.action = UNKNOWN; - curfile.dip = NULL; + curfile.mode = 0; curfile.ino = maxino; if (gettingfile) { gettingfile = 0; @@ -513,9 +504,9 @@ void printdumpinfo(void) { time_t t; - t = _time32_to_time(spcl.c_date); + t = _time64_to_time(spcl.c_date); fprintf(stdout, "Dump date: %s", ctime(&t)); - t = _time32_to_time(spcl.c_ddate); + t = _time64_to_time(spcl.c_ddate); fprintf(stdout, "Dumped from: %s", (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&t)); if (spcl.c_host[0] == '\0') @@ -529,22 +520,18 @@ int extractfile(char *name) { int flags; - uid_t uid; - gid_t gid; mode_t mode; struct timeval timep[2]; struct entry *ep; curfile.name = name; curfile.action = USING; - timep[0].tv_sec = curfile.dip->di_atime; - timep[0].tv_usec = curfile.dip->di_atimensec / 1000; - timep[1].tv_sec = curfile.dip->di_mtime; - timep[1].tv_usec = curfile.dip->di_mtimensec / 1000; - uid = curfile.dip->di_uid; - gid = curfile.dip->di_gid; - mode = curfile.dip->di_mode; - flags = curfile.dip->di_flags; + timep[0].tv_sec = curfile.atime_sec; + timep[0].tv_usec = curfile.atime_nsec / 1000; + timep[1].tv_sec = curfile.mtime_sec; + timep[1].tv_usec = curfile.mtime_nsec / 1000; + mode = curfile.mode; + flags = curfile.file_flags; switch (mode & IFMT) { default: @@ -578,7 +565,7 @@ extractfile(char *name) return (GOOD); } if (linkit(lnkbuf, name, SYMLINK) == GOOD) { - (void) lchown(name, uid, gid); + (void) lchown(name, curfile.uid, curfile.gid); (void) lchmod(name, mode); (void) lutimes(name, timep); return (GOOD); @@ -599,7 +586,7 @@ extractfile(char *name) skipfile(); return (FAIL); } - (void) chown(name, uid, gid); + (void) chown(name, curfile.uid, curfile.gid); (void) chmod(name, mode); (void) utimes(name, timep); (void) chflags(name, flags); @@ -615,13 +602,13 @@ extractfile(char *name) } if (uflag) (void)unlink(name); - if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) { + if (mknod(name, mode, (int)curfile.rdev) < 0) { fprintf(stderr, "%s: cannot create special file: %s\n", name, strerror(errno)); skipfile(); return (FAIL); } - (void) chown(name, uid, gid); + (void) chown(name, curfile.uid, curfile.gid); (void) chmod(name, mode); (void) utimes(name, timep); (void) chflags(name, flags); @@ -643,7 +630,7 @@ extractfile(char *name) skipfile(); return (FAIL); } - (void) fchown(ofile, uid, gid); + (void) fchown(ofile, curfile.uid, curfile.gid); (void) fchmod(ofile, mode); getfile(xtrfile, xtrskip); (void) close(ofile); @@ -687,14 +674,14 @@ getfile(void (*fill)(char *, long), void (*skip)(char *, long)) { int i; int curblk = 0; - quad_t size = spcl.c_dinode.di_size; + quad_t size = spcl.c_size; static char clearedbuf[MAXBSIZE]; char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE]; char junk[TP_BSIZE]; if (spcl.c_type == TS_END) panic("ran off end of tape\n"); - if (spcl.c_magic != NFS_MAGIC) + if (spcl.c_magic != FS_UFS2_MAGIC) panic("not at beginning of a file\n"); if (!gettingfile && setjmp(restart) != 0) return; @@ -1000,106 +987,43 @@ closemt(void) /* * Read the next block from the tape. - * Check to see if it is one of several vintage headers. - * If it is an old style header, convert it to a new style header. * If it is not any valid header, return an error. */ static int gethead(struct s_spcl *buf) { long i; - union { - quad_t qval; - int32_t val[2]; - } qcvt; - union u_ospcl { - char dummy[TP_BSIZE]; - struct s_ospcl { - int32_t c_type; - int32_t c_date; - int32_t c_ddate; - int32_t c_volume; - int32_t c_tapea; - u_short c_inumber; - int32_t c_magic; - int32_t c_checksum; - struct odinode { - unsigned short odi_mode; - u_short odi_nlink; - u_short odi_uid; - u_short odi_gid; - int32_t odi_size; - int32_t odi_rdev; - char odi_addr[36]; - int32_t odi_atime; - int32_t odi_mtime; - int32_t odi_ctime; - } c_dinode; - int32_t c_count; - char c_addr[256]; - } s_ospcl; - } u_ospcl; - - if (!cvtflag) { - readtape((char *)buf); - if (buf->c_magic != NFS_MAGIC) { - if (swabl(buf->c_magic) != NFS_MAGIC) - return (FAIL); - if (!Bcvt) { - vprintf(stdout, "Note: Doing Byte swapping\n"); - Bcvt = 1; - } + + readtape((char *)buf); + if (buf->c_magic != FS_UFS2_MAGIC && buf->c_magic != NFS_MAGIC) { + if (buf->c_magic == OFS_MAGIC) { + fprintf(stderr, + "Format of dump tape is too old. Must use\n"); + fprintf(stderr, + "a version of restore from before 2002.\n"); + return (FAIL); } - if (checksum((int *)buf) == FAIL) + if (swabl(buf->c_magic) != FS_UFS2_MAGIC && + buf->c_magic != NFS_MAGIC) { + if (buf->c_magic == OFS_MAGIC) { + fprintf(stderr, + "Format of dump tape is too old. Must use\n"); + fprintf(stderr, + "a version of restore from before 2002.\n"); + } return (FAIL); - if (Bcvt) { - swabst((u_char *)"8l4s31l", (u_char *)buf); - swabst((u_char *)"l",(u_char *) &buf->c_level); - swabst((u_char *)"2l",(u_char *) &buf->c_flags); } - goto good; - } - readtape((char *)(&u_ospcl.s_ospcl)); - memset(buf, 0, (long)TP_BSIZE); - buf->c_type = u_ospcl.s_ospcl.c_type; - buf->c_date = u_ospcl.s_ospcl.c_date; - buf->c_ddate = u_ospcl.s_ospcl.c_ddate; - buf->c_volume = u_ospcl.s_ospcl.c_volume; - buf->c_tapea = u_ospcl.s_ospcl.c_tapea; - buf->c_inumber = u_ospcl.s_ospcl.c_inumber; - buf->c_checksum = u_ospcl.s_ospcl.c_checksum; - buf->c_magic = u_ospcl.s_ospcl.c_magic; - buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode; - buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink; - buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid; - buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid; - buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size; - buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev; - buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime; - buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime; - buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime; - buf->c_count = u_ospcl.s_ospcl.c_count; - memmove(buf->c_addr, u_ospcl.s_ospcl.c_addr, (long)256); - if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC || - checksum((int *)(&u_ospcl.s_ospcl)) == FAIL) - return(FAIL); - buf->c_magic = NFS_MAGIC; - -good: - if ((buf->c_dinode.di_size == 0 || buf->c_dinode.di_size > 0xfffffff) && - (buf->c_dinode.di_mode & IFMT) == IFDIR && Qcvt == 0) { - qcvt.qval = buf->c_dinode.di_size; - if (qcvt.val[0] || qcvt.val[1]) { - printf("Note: Doing Quad swapping\n"); - Qcvt = 1; + if (!Bcvt) { + vprintf(stdout, "Note: Doing Byte swapping\n"); + Bcvt = 1; } } - if (Qcvt) { - qcvt.qval = buf->c_dinode.di_size; - i = qcvt.val[1]; - qcvt.val[1] = qcvt.val[0]; - qcvt.val[0] = i; - buf->c_dinode.di_size = qcvt.qval; + if (checksum((int *)buf) == FAIL) + return (FAIL); + if (Bcvt) { + swabst((u_char *)"8l4s1q8l2q17l", (u_char *)buf); + swabst((u_char *)"l",(u_char *) &buf->c_level); + swabst((u_char *)"2l4q",(u_char *) &buf->c_flags); } readmapflag = 0; @@ -1111,7 +1035,7 @@ good: * Have to patch up missing information in bit map headers */ buf->c_inumber = 0; - buf->c_dinode.di_size = buf->c_count * TP_BSIZE; + buf->c_size = buf->c_count * TP_BSIZE; if (buf->c_count > TP_NINDIR) readmapflag = 1; else @@ -1120,14 +1044,25 @@ good: break; case TS_TAPE: - if ((buf->c_flags & DR_NEWINODEFMT) == 0) - oldinofmt = 1; - /* fall through */ case TS_END: buf->c_inumber = 0; break; case TS_INODE: + /* + * For old dump tapes, have to copy up old fields to + * new locations. + */ + if (buf->c_magic == NFS_MAGIC) { + buf->c_tapea = buf->c_old_tapea; + buf->c_firstrec = buf->c_old_firstrec; + buf->c_date = _time32_to_time(buf->c_old_date); + buf->c_ddate = _time32_to_time(buf->c_old_ddate); + buf->c_atime = _time32_to_time(buf->c_old_atime); + buf->c_mtime = _time32_to_time(buf->c_old_mtime); + } + break; + case TS_ADDR: break; @@ -1135,14 +1070,7 @@ good: panic("gethead: unknown inode type %d\n", buf->c_type); break; } - /* - * If we are restoring a filesystem with old format inodes, - * copy the uid/gid to the new location. - */ - if (oldinofmt) { - buf->c_dinode.di_uid = buf->c_dinode.di_ouid; - buf->c_dinode.di_gid = buf->c_dinode.di_ogid; - } + buf->c_magic = FS_UFS2_MAGIC; tapeaddr = buf->c_tapea; if (dflag) accthdr(buf); @@ -1161,10 +1089,9 @@ accthdr(struct s_spcl *header) long blks, i; if (header->c_type == TS_TAPE) { - fprintf(stderr, "Volume header (%s inode format) ", - oldinofmt ? "old" : "new"); + fprintf(stderr, "Volume header "); if (header->c_firstrec) - fprintf(stderr, "begins with record %ld", + fprintf(stderr, "begins with record %qd", header->c_firstrec); fprintf(stderr, "\n"); previno = 0x7fffffff; @@ -1219,15 +1146,9 @@ findinode(struct s_spcl *header) curfile.name = "<name unknown>"; curfile.action = UNKNOWN; - curfile.dip = NULL; + curfile.mode = 0; curfile.ino = 0; do { - if (header->c_magic != NFS_MAGIC) { - skipcnt++; - while (gethead(header) == FAIL || - _time32_to_time(header->c_date) != dumpdate) - skipcnt++; - } htype = header->c_type; switch (htype) { @@ -1239,12 +1160,21 @@ findinode(struct s_spcl *header) if (header->c_addr[i]) readtape(buf); while (gethead(header) == FAIL || - _time32_to_time(header->c_date) != dumpdate) + _time64_to_time(header->c_date) != dumpdate) skipcnt++; break; case TS_INODE: - curfile.dip = &header->c_dinode; + curfile.mode = header->c_mode; + curfile.uid = header->c_uid; + curfile.gid = header->c_gid; + curfile.file_flags = header->c_file_flags; + curfile.rdev = header->c_rdev; + curfile.atime_sec = header->c_atime; + curfile.atime_nsec = header->c_atimensec; + curfile.mtime_sec = header->c_mtime; + curfile.mtime_nsec = header->c_mtimensec; + curfile.size = header->c_size; curfile.ino = header->c_inumber; break; @@ -1288,7 +1218,7 @@ checksum(int *buf) j = sizeof(union u_spcl) / sizeof(int); i = 0; - if(!Bcvt) { + if (!Bcvt) { do i += *buf++; while (--j); @@ -1346,6 +1276,21 @@ swablong(u_char *sp, int n) return (sp); } +static u_char * +swabquad(u_char *sp, int n) +{ + char c; + + while (--n >= 0) { + c = sp[0]; sp[0] = sp[7]; sp[7] = c; + c = sp[1]; sp[1] = sp[6]; sp[6] = c; + c = sp[2]; sp[2] = sp[5]; sp[5] = c; + c = sp[3]; sp[3] = sp[4]; sp[4] = c; + sp += 8; + } + return (sp); +} + void swabst(u_char *cp, u_char *sp) { @@ -1370,11 +1315,23 @@ swabst(u_char *cp, u_char *sp) sp = swablong(sp, n); break; - default: /* Any other character, like 'b' counts as byte. */ + case 'q': + if (n == 0) + n = 1; + sp = swabquad(sp, n); + break; + + case 'b': if (n == 0) n = 1; sp += n; break; + + default: + fprintf(stderr, "Unknown conversion character: %c\n", + *cp); + done(0); + break; } cp++; n = 0; |