summaryrefslogtreecommitdiffstats
path: root/sbin/restore/tape.c
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2002-06-21 06:18:05 +0000
committermckusick <mckusick@FreeBSD.org>2002-06-21 06:18:05 +0000
commit88d85c15ef183c06524d6ca695f62c0c0672b00c (patch)
treef1364dbfb9835934a3879b5904f7ff9a1495744c /sbin/restore/tape.c
parenteacb69b0197a8553d5004aa99532cabad8778e36 (diff)
downloadFreeBSD-src-88d85c15ef183c06524d6ca695f62c0c0672b00c.zip
FreeBSD-src-88d85c15ef183c06524d6ca695f62c0c0672b00c.tar.gz
This commit adds basic support for the UFS2 filesystem. The UFS2
filesystem expands the inode to 256 bytes to make space for 64-bit block pointers. It also adds a file-creation time field, an ability to use jumbo blocks per inode to allow extent like pointer density, and space for extended attributes (up to twice the filesystem block size worth of attributes, e.g., on a 16K filesystem, there is space for 32K of attributes). UFS2 fully supports and runs existing UFS1 filesystems. New filesystems built using newfs can be built in either UFS1 or UFS2 format using the -O option. In this commit UFS1 is the default format, so if you want to build UFS2 format filesystems, you must specify -O 2. This default will be changed to UFS2 when UFS2 proves itself to be stable. In this commit the boot code for reading UFS2 filesystems is not compiled (see /sys/boot/common/ufsread.c) as there is insufficient space in the boot block. Once the size of the boot block is increased, this code can be defined. Things to note: the definition of SBSIZE has changed to SBLOCKSIZE. The header file <ufs/ufs/dinode.h> must be included before <ufs/ffs/fs.h> so as to get the definitions of ufs2_daddr_t and ufs_lbn_t. Still TODO: Verify that the first level bootstraps work for all the architectures. Convert the utility ffsinfo to understand UFS2 and test growfs. Add support for the extended attribute storage. Update soft updates to ensure integrity of extended attribute storage. Switch the current extended attribute interfaces to use the extended attribute storage. Add the extent like functionality (framework is there, but is currently never used). Sponsored by: DARPA & NAI Labs. Reviewed by: Poul-Henning Kamp <phk@freebsd.org>
Diffstat (limited to 'sbin/restore/tape.c')
-rw-r--r--sbin/restore/tape.c277
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;
OpenPOWER on IntegriCloud