📄 tape.c
字号:
/* * Write out the next block of a file. */static voidxtrfile(buf, size) char *buf; long size;{ if (Nflag) return; if (write(ofile, buf, (int) size) == -1) { fprintf(stderr, "write error extracting inode %d, name %s\nwrite: %s\n", curfile.ino, curfile.name, strerror(errno)); done(1); }}/* * Skip over a hole in a file. *//* ARGSUSED */static voidxtrskip(buf, size) char *buf; long size;{ if (lseek(ofile, size, SEEK_CUR) == -1) { fprintf(stderr, "seek error extracting inode %d, name %s\nlseek: %s\n", curfile.ino, curfile.name, strerror(errno)); done(1); }}/* * Collect the next block of a symbolic link. */static voidxtrlnkfile(buf, size) char *buf; long size;{ pathlen += size; if (pathlen > MAXPATHLEN) { fprintf(stderr, "symbolic link name: %s->%s%s; too long %d\n", curfile.name, lnkbuf, buf, pathlen); done(1); } (void) strcat(lnkbuf, buf);}/* * Skip over a hole in a symbolic link (should never happen). *//* ARGSUSED */static voidxtrlnkskip(buf, size) char *buf; long size;{ fprintf(stderr, "unallocated block in symbolic link %s\n", curfile.name); done(1);}/* * Collect the next block of a bit map. */static voidxtrmap(buf, size) char *buf; long size;{ bcopy(buf, map, size); map += size;}/* * Skip over a hole in a bit map (should never happen). *//* ARGSUSED */static voidxtrmapskip(buf, size) char *buf; long size;{ panic("hole in map\n"); map += size;}/* * Noop, when an extraction function is not needed. *//* ARGSUSED */voidxtrnull(buf, size) char *buf; long size;{ return;}/* * Read TP_BSIZE blocks from the input. * Handle read errors, and end of media. */static voidreadtape(buf) char *buf;{ long rd, newvol, i; int cnt, seek_failed; if (blkcnt < numtrec) { bcopy(&tapebuf[(blkcnt++ * TP_BSIZE)], buf, (long)TP_BSIZE); blksread++; tpblksread++; return; } for (i = 0; i < ntrec; i++) ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; if (numtrec == 0) numtrec = ntrec; cnt = ntrec * TP_BSIZE; rd = 0;getmore:#ifdef RRESTORE if (host) i = rmtread(&tapebuf[rd], cnt); else#endif i = read(mt, &tapebuf[rd], cnt); /* * Check for mid-tape short read error. * If found, skip rest of buffer and start with the next. */ if (!pipein && numtrec < ntrec && i > 0) { dprintf(stdout, "mid-media short read error.\n"); numtrec = ntrec; } /* * Handle partial block read. */ if (pipein && i == 0 && rd > 0) i = rd; else if (i > 0 && i != ntrec * TP_BSIZE) { if (pipein) { rd += i; cnt -= i; if (cnt > 0) goto getmore; i = rd; } else { /* * Short read. Process the blocks read. */ if (i % TP_BSIZE != 0) vprintf(stdout, "partial block read: %d should be %d\n", i, ntrec * TP_BSIZE); numtrec = i / TP_BSIZE; } } /* * Handle read error. */ 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 resynchronize\n"); break; case USING: fprintf(stderr, "restoring %s\n", curfile.name); break; case SKIP: fprintf(stderr, "skipping over inode %d\n", curfile.ino); break; } if (!yflag && !reply("continue")) done(1); i = ntrec * TP_BSIZE; bzero(tapebuf, i);#ifdef RRESTORE if (host) seek_failed = (rmtseek(i, 1) < 0); else#endif seek_failed = (lseek(mt, i, SEEK_CUR) == (off_t)-1); if (seek_failed) { fprintf(stderr, "continuation failed: %s\n", strerror(errno)); done(1); } } /* * Handle end of tape. */ if (i == 0) { vprintf(stdout, "End-of-tape encountered\n"); if (!pipein) { newvol = volno + 1; volno = 0; numtrec = 0; getvol(newvol); readtape(buf); return; } if (rd % TP_BSIZE != 0) panic("partial block read: %d should be %d\n", rd, ntrec * TP_BSIZE); terminateinput(); bcopy((char *)&endoftapemark, &tapebuf[rd], (long)TP_BSIZE); } blkcnt = 0; bcopy(&tapebuf[(blkcnt++ * TP_BSIZE)], buf, (long)TP_BSIZE); blksread++; tpblksread++;}static voidfindtapeblksize(){ register long i; for (i = 0; i < ntrec; i++) ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; blkcnt = 0;#ifdef RRESTORE if (host) i = rmtread(tapebuf, ntrec * TP_BSIZE); else#endif i = read(mt, tapebuf, ntrec * TP_BSIZE); if (i <= 0) { fprintf(stderr, "tape read error: %s\n", strerror(errno)); done(1); } if (i % TP_BSIZE != 0) { fprintf(stderr, "Tape block size (%d) %s (%d)\n", i, "is not a multiple of dump block size", TP_BSIZE); done(1); } ntrec = i / TP_BSIZE; numtrec = ntrec; vprintf(stdout, "Tape block size is %d\n", ntrec);}voidclosemt(){ if (mt < 0) return;#ifdef RRESTORE if (host) rmtclose(); else#endif (void) close(mt);}/* * 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 intgethead(buf) struct s_spcl *buf;{ long i; union { quad_t qval; long val[2]; } qcvt; union u_ospcl { char dummy[TP_BSIZE]; struct s_ospcl { long c_type; long c_date; long c_ddate; long c_volume; long c_tapea; u_short c_inumber; long c_magic; long c_checksum; struct odinode { unsigned short odi_mode; u_short odi_nlink; u_short odi_uid; u_short odi_gid; long odi_size; long odi_rdev; char odi_addr[36]; long odi_atime; long odi_mtime; long odi_ctime; } c_dinode; long 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; } } if (checksum((int *)buf) == FAIL) return (FAIL); if (Bcvt) swabst((u_char *)"8l4s31l", (u_char *)buf); goto good; } readtape((char *)(&u_ospcl.s_ospcl)); bzero((char *)buf, (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.ts_sec = u_ospcl.s_ospcl.c_dinode.odi_atime; buf->c_dinode.di_mtime.ts_sec = u_ospcl.s_ospcl.c_dinode.odi_mtime; buf->c_dinode.di_ctime.ts_sec = u_ospcl.s_ospcl.c_dinode.odi_ctime; 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) 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 (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; } 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: if ((buf->c_flags & DR_NEWINODEFMT) == 0) oldinofmt = 1; /* fall through */ 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 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; } if (dflag) accthdr(buf); return(GOOD);}/* * Check that a header is where it belongs and predict the next header */static voidaccthdr(header) struct s_spcl *header;{ static ino_t previno = 0x7fffffff; static int prevtype; static long predict; long blks, i; if (header->c_type == TS_TAPE) { fprintf(stderr, "Volume header (%s inode format) ", oldinofmt ? "old" : "new"); if (header->c_firstrec) fprintf(stderr, "begins with record %d", header->c_firstrec); fprintf(stderr, "\n"); previno = 0x7fffffff; return; } if (previno == 0x7fffffff) goto newcalc; switch (prevtype) { case TS_BITS: fprintf(stderr, "Dump mask header"); break; case TS_CLRI: fprintf(stderr, "Remove mask header"); break; case TS_INODE: fprintf(stderr, "File header, ino %d", previno); break; case TS_ADDR: fprintf(stderr, "File continuation header, ino %d", previno); break; case TS_END: fprintf(stderr, "End of tape header"); break; } 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_END) for (i = 0; i < header->c_count; i++) if (header->c_addr[i] != 0) blks++; predict = blks; blksread = 0; prevtype = header->c_type; previno = header->c_inumber;}/* * Find an inode header. * Complain if had to skip, and complain is set. */static voidfindinode(header) struct s_spcl *header;{ static long skipcnt = 0; long i; char buf[TP_BSIZE]; curfile.name = "<name unknown>"; curfile.action = UNKNOWN; curfile.dip = NULL; curfile.ino = 0; do { if (header->c_magic != NFS_MAGIC) { skipcnt++; while (gethead(header) == FAIL || header->c_date != dumpdate) skipcnt++; } switch (header->c_type) { case TS_ADDR: /* * Skip up to the beginning of the next record */ for (i = 0; i < header->c_count; i++) if (header->c_addr[i]) readtape(buf); while (gethead(header) == FAIL || header->c_date != dumpdate) skipcnt++; break; case TS_INODE: curfile.dip = &header->c_dinode; curfile.ino = header->c_inumber; break; case TS_END: curfile.ino = maxino; break; case TS_CLRI: curfile.name = "<file removal list>"; break; case TS_BITS: curfile.name = "<file dump list>"; break; case TS_TAPE: panic("unexpected tape header\n"); /* NOTREACHED */ default: panic("unknown tape header type %d\n", spcl.c_type); /* NOTREACHED */ } } while (header->c_type == TS_ADDR); if (skipcnt > 0) fprintf(stderr, "resync restore, skipped %d blocks\n", skipcnt); skipcnt = 0;}static intchecksum(buf) register int *buf;{ register int i, j; j = sizeof(union u_spcl) / sizeof(int); i = 0; if(!Bcvt) { do i += *buf++; while (--j); } else { /* What happens if we want to read restore tapes for a 16bit int machine??? */ do i += swabl(*buf++); while (--j); } if (i != CHECKSUM) { fprintf(stderr, "Checksum error %o, inode %d file %s\n", i, curfile.ino, curfile.name); return(FAIL); } return(GOOD);}#ifdef RRESTORE#if __STDC__#include <stdarg.h>#else#include <varargs.h>#endifvoid#if __STDC__msg(const char *fmt, ...)#elsemsg(fmt, va_alist) char *fmt; va_dcl#endif{ va_list ap;#if __STDC__ va_start(ap, fmt);#else va_start(ap);#endif (void)vfprintf(stderr, fmt, ap); va_end(ap);}#endif /* RRESTORE */static u_char *swabshort(sp, n) register u_char *sp; register int n;{ char c; while (--n >= 0) { c = sp[0]; sp[0] = sp[1]; sp[1] = c; sp += 2; } return (sp);}static u_char *swablong(sp, n) register u_char *sp; register int n;{ char c; while (--n >= 0) { c = sp[0]; sp[0] = sp[3]; sp[3] = c; c = sp[2]; sp[2] = sp[1]; sp[1] = c; sp += 4; } return (sp);}voidswabst(cp, sp) register u_char *cp, *sp;{ int n = 0; while (*cp) { switch (*cp) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = (n * 10) + (*cp++ - '0'); continue; case 's': case 'w': case 'h': if (n == 0) n = 1; sp = swabshort(sp, n); break; case 'l': if (n == 0) n = 1; sp = swablong(sp, n); break; default: /* Any other character, like 'b' counts as byte. */ if (n == 0) n = 1; sp += n; break; } cp++; n = 0; }}static u_longswabl(x) u_long x;{ swabst((u_char *)"l", (u_char *)&x); return (x);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -