freebsd-skq/sbin/restore/tape.c

1753 lines
40 KiB
C
Raw Normal View History

/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
#if 0
static char sccsid[] = "@(#)tape.c 8.9 (Berkeley) 5/1/95";
#endif
#endif /* not lint */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/file.h>
#include <sys/mtio.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/extattr.h>
#include <sys/acl.h>
#include <ufs/ufs/extattr.h>
#include <ufs/ufs/dinode.h>
#include <protocols/dumprestore.h>
#include <errno.h>
#include <limits.h>
#include <paths.h>
#include <setjmp.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <timeconv.h>
#include <unistd.h>
#include "restore.h"
#include "extern.h"
static long fssize = MAXBSIZE;
static int mt = -1;
static int pipein = 0;
static int pipecmdin = 0;
static FILE *popenfp = NULL;
static char *magtape;
static int blkcnt;
static int numtrec;
static char *tapebuf;
static union u_spcl endoftapemark;
static long byteslide = 0;
static long blksread; /* blocks read since last header */
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>
2002-06-21 06:18:05 +00:00
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;
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>
2002-06-21 06:18:05 +00:00
static int readmapflag;
static int ofile;
static char *map;
static char lnkbuf[MAXPATHLEN + 1];
static int pathlen;
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>
2002-06-21 06:18:05 +00:00
int Bcvt; /* Swap Bytes */
int oldinofmt; /* FreeBSD 1 inode format needs cvt */
#define FLUSHTAPEBUF() blkcnt = ntrec + 1
char *namespace_names[] = EXTATTR_NAMESPACE_NAMES;
static void accthdr(struct s_spcl *);
static int checksum(int *);
static void findinode(struct s_spcl *);
static void findtapeblksize(void);
static char *setupextattr(int);
static void xtrattr(char *, long);
static void set_extattr_link(char *, void *, int);
static void set_extattr_fd(int, char *, void *, int);
static int gethead(struct s_spcl *);
static void readtape(char *);
static void setdumpnum(void);
static u_long swabl(u_long);
static u_char *swablong(u_char *, int);
static u_char *swabshort(u_char *, int);
static void terminateinput(void);
static void xtrfile(char *, long);
static void xtrlnkfile(char *, long);
static void xtrlnkskip(char *, long);
static void xtrmap(char *, long);
static void xtrmapskip(char *, long);
static void xtrskip(char *, long);
/*
* Set up an input source
*/
void
setinput(char *source, int ispipecommand)
{
FLUSHTAPEBUF();
if (bflag)
newtapebuf(ntrec);
else
newtapebuf(NTREC > HIGHDENSITYTREC ? NTREC : HIGHDENSITYTREC);
terminal = stdin;
if (ispipecommand)
pipecmdin++;
else
#ifdef RRESTORE
if (strchr(source, ':')) {
host = source;
source = strchr(host, ':');
*source++ = '\0';
if (rmthost(host) == 0)
done(1);
} else
#endif
if (strcmp(source, "-") == 0) {
/*
* Since input is coming from a pipe we must establish
* our own connection to the terminal.
*/
terminal = fopen(_PATH_TTY, "r");
if (terminal == NULL) {
(void)fprintf(stderr, "cannot open %s: %s\n",
_PATH_TTY, strerror(errno));
terminal = fopen(_PATH_DEVNULL, "r");
if (terminal == NULL) {
(void)fprintf(stderr, "cannot open %s: %s\n",
_PATH_DEVNULL, strerror(errno));
done(1);
}
}
pipein++;
}
/* no longer need or want root privileges */
if (setuid(getuid()) != 0) {
fprintf(stderr, "setuid failed\n");
done(1);
}
magtape = strdup(source);
if (magtape == NULL) {
fprintf(stderr, "Cannot allocate space for magtape buffer\n");
done(1);
}
}
void
newtapebuf(long size)
{
static int tapebufsize = -1;
ntrec = size;
if (size <= tapebufsize)
return;
if (tapebuf != NULL)
free(tapebuf - TP_BSIZE);
tapebuf = malloc((size+1) * TP_BSIZE);
if (tapebuf == NULL) {
fprintf(stderr, "Cannot allocate space for tape buffer\n");
done(1);
}
tapebuf += TP_BSIZE;
tapebufsize = size;
}
/*
* Verify that the tape drive can be accessed and
* that it actually is a dump tape.
*/
void
setup(void)
{
int i, j, *ip;
struct stat stbuf;
vprintf(stdout, "Verify tape and initialize maps\n");
if (pipecmdin) {
if (setenv("RESTORE_VOLUME", "1", 1) == -1) {
fprintf(stderr, "Cannot set $RESTORE_VOLUME: %s\n",
strerror(errno));
done(1);
}
popenfp = popen(magtape, "r");
mt = popenfp ? fileno(popenfp) : -1;
} else
#ifdef RRESTORE
if (host)
mt = rmtopen(magtape, 0);
else
#endif
if (pipein)
mt = 0;
else
mt = open(magtape, O_RDONLY, 0);
if (mt < 0) {
fprintf(stderr, "%s: %s\n", magtape, strerror(errno));
done(1);
}
volno = 1;
setdumpnum();
FLUSHTAPEBUF();
if (!pipein && !pipecmdin && !bflag)
findtapeblksize();
if (gethead(&spcl) == FAIL) {
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>
2002-06-21 06:18:05 +00:00
fprintf(stderr, "Tape is not a dump tape\n");
done(1);
}
if (pipein) {
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>
2002-06-21 06:18:05 +00:00
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);
i = 0;
do
i += *ip++;
while (--j);
endoftapemark.s_spcl.c_checksum = CHECKSUM - i;
}
if (vflag || command == 't')
printdumpinfo();
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>
2002-06-21 06:18:05 +00:00
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);
}
if (stbuf.st_blksize > 0 && stbuf.st_blksize < TP_BSIZE )
fssize = TP_BSIZE;
if (stbuf.st_blksize >= TP_BSIZE && stbuf.st_blksize <= MAXBSIZE)
fssize = stbuf.st_blksize;
if (((fssize - 1) & fssize) != 0) {
fprintf(stderr, "bad block size %ld\n", fssize);
done(1);
}
if (spcl.c_volume != 1) {
fprintf(stderr, "Tape is not volume 1 of the dump\n");
done(1);
}
if (gethead(&spcl) == FAIL) {
dprintf(stdout, "header read failed at %ld blocks\n", blksread);
panic("no header after volume mark!\n");
}
findinode(&spcl);
if (spcl.c_type != TS_CLRI) {
fprintf(stderr, "Cannot find file removal list\n");
done(1);
}
maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1;
dprintf(stdout, "maxino = %ju\n", (uintmax_t)maxino);
map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
if (map == NULL)
panic("no memory for active inode map\n");
usedinomap = map;
curfile.action = USING;
getfile(xtrmap, xtrmapskip, xtrmapskip);
if (spcl.c_type != TS_BITS) {
fprintf(stderr, "Cannot find file dump list\n");
done(1);
}
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, xtrmapskip);
/*
* If there may be whiteout entries on the tape, pretend that the
* whiteout inode exists, so that the whiteout entries can be
* extracted.
*/
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>
2002-06-21 06:18:05 +00:00
SETINO(WINO, dumpmap);
/* 'r' restores don't call getvol() for tape 1, so mark it as read. */
if (command == 'r')
tapesread = 1;
}
/*
* Prompt user to load a new dump volume.
* "Nextvol" is the next suggested volume to use.
* This suggested volume is enforced when doing full
* or incremental restores, but can be overridden by
* the user when only extracting a subset of the files.
*/
void
getvol(long nextvol)
{
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>
2002-06-21 06:18:05 +00:00
int64_t prevtapea;
long i, newvol, savecnt;
union u_spcl tmpspcl;
# define tmpbuf tmpspcl.s_spcl
char buf[TP_BSIZE];
if (nextvol == 1) {
tapesread = 0;
gettingfile = 0;
}
prevtapea = tapeaddr;
savecnt = blksread;
if (pipein) {
if (nextvol != 1) {
panic("Changing volumes on pipe input?\n");
/* Avoid looping if we couldn't ask the user. */
if (yflag || ferror(terminal) || feof(terminal))
done(1);
}
if (volno == 1)
return;
goto gethdr;
}
again:
if (pipein)
done(1); /* pipes do not get a second chance */
2002-02-13 12:06:58 +00:00
if (command == 'R' || command == 'r' || curfile.action != SKIP)
newvol = nextvol;
2002-02-13 12:06:58 +00:00
else
newvol = 0;
while (newvol <= 0) {
if (tapesread == 0) {
fprintf(stderr, "%s%s%s%s%s%s%s",
"You have not read any tapes yet.\n",
"If you are extracting just a few files,",
" start with the last volume\n",
"and work towards the first; restore",
" can quickly skip tapes that\n",
"have no further files to extract.",
" Otherwise, begin with volume 1.\n");
} else {
fprintf(stderr, "You have read volumes");
strcpy(buf, ": ");
for (i = 0; i < 32; i++)
if (tapesread & (1 << i)) {
fprintf(stderr, "%s%ld", buf, i + 1);
strcpy(buf, ", ");
}
fprintf(stderr, "\n");
}
do {
fprintf(stderr, "Specify next volume #: ");
(void) fflush(stderr);
if (fgets(buf, BUFSIZ, terminal) == NULL)
done(1);
} while (buf[0] == '\n');
newvol = atoi(buf);
if (newvol <= 0) {
fprintf(stderr,
"Volume numbers are positive numerics\n");
}
}
if (newvol == volno) {
tapesread |= 1 << (volno - 1);
return;
}
closemt();
fprintf(stderr, "Mount tape volume %ld\n", newvol);
fprintf(stderr, "Enter ``none'' if there are no more tapes\n");
fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape);
(void) fflush(stderr);
if (fgets(buf, BUFSIZ, terminal) == NULL)
done(1);
if (!strcmp(buf, "none\n")) {
terminateinput();
return;
}
if (buf[0] != '\n') {
(void) strcpy(magtape, buf);
magtape[strlen(magtape) - 1] = '\0';
}
if (pipecmdin) {
char volno[sizeof("2147483647")];
(void)sprintf(volno, "%ld", newvol);
if (setenv("RESTORE_VOLUME", volno, 1) == -1) {
fprintf(stderr, "Cannot set $RESTORE_VOLUME: %s\n",
strerror(errno));
done(1);
}
popenfp = popen(magtape, "r");
mt = popenfp ? fileno(popenfp) : -1;
} else
#ifdef RRESTORE
if (host)
mt = rmtopen(magtape, 0);
else
#endif
mt = open(magtape, O_RDONLY, 0);
if (mt == -1) {
fprintf(stderr, "Cannot open %s\n", magtape);
volno = -1;
goto again;
}
gethdr:
volno = newvol;
setdumpnum();
FLUSHTAPEBUF();
if (gethead(&tmpbuf) == FAIL) {
dprintf(stdout, "header read failed at %ld blocks\n", blksread);
fprintf(stderr, "tape is not dump tape\n");
volno = 0;
goto again;
}
if (tmpbuf.c_volume != volno) {
fprintf(stderr, "Wrong volume (%jd)\n",
(intmax_t)tmpbuf.c_volume);
volno = 0;
goto again;
}
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>
2002-06-21 06:18:05 +00:00
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;
goto again;
}
tapesread |= 1 << (volno - 1);
blksread = savecnt;
/*
* If continuing from the previous volume, skip over any
* blocks read already at the end of the previous volume.
*
* If coming to this volume at random, skip to the beginning
* of the next record.
*/
dprintf(stdout, "last rec %jd, tape starts with %jd\n",
(intmax_t)prevtapea, (intmax_t)tmpbuf.c_tapea);
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>
2002-06-21 06:18:05 +00:00
if (tmpbuf.c_type == TS_TAPE) {
2002-02-13 12:06:58 +00:00
if (curfile.action != USING) {
/*
* XXX Dump incorrectly sets c_count to 1 in the
* volume header of the first tape, so ignore
* c_count when volno == 1.
*/
if (volno != 1)
for (i = tmpbuf.c_count; i > 0; i--)
readtape(buf);
} else if (tmpbuf.c_tapea <= prevtapea) {
/*
* Normally the value of c_tapea in the volume
* header is the record number of the header itself.
* However in the volume header following an EOT-
* terminated tape, it is the record number of the
* first continuation data block (dump bug?).
*
* The next record we want is `prevtapea + 1'.
*/
i = prevtapea + 1 - tmpbuf.c_tapea;
dprintf(stderr, "Skipping %ld duplicate record%s.\n",
i, i > 1 ? "s" : "");
while (--i >= 0)
readtape(buf);
}
}
2002-02-13 12:06:58 +00:00
if (curfile.action == USING) {
if (volno == 1)
panic("active file into volume 1\n");
return;
}
(void) gethead(&spcl);
findinode(&spcl);
if (gettingfile) {
gettingfile = 0;
longjmp(restart, 1);
}
}
/*
* Handle unexpected EOF.
*/
static void
terminateinput(void)
{
if (gettingfile && curfile.action == USING) {
printf("Warning: %s %s\n",
"End-of-input encountered while extracting", curfile.name);
}
curfile.name = "<name unknown>";
curfile.action = UNKNOWN;
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>
2002-06-21 06:18:05 +00:00
curfile.mode = 0;
curfile.ino = maxino;
if (gettingfile) {
gettingfile = 0;
longjmp(restart, 1);
}
}
/*
* handle multiple dumps per tape by skipping forward to the
* appropriate one.
*/
static void
setdumpnum(void)
{
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 RRESTORE
if (host)
rmtioctl(MTFSF, dumpnum - 1);
1995-05-30 06:12:45 +00:00
else
#endif
if (!pipecmdin && ioctl(mt, MTIOCTOP, (char *)&tcom) < 0)
fprintf(stderr, "ioctl MTFSF: %s\n", strerror(errno));
}
void
printdumpinfo(void)
{
time_t t;
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>
2002-06-21 06:18:05 +00:00
t = _time64_to_time(spcl.c_date);
fprintf(stdout, "Dump date: %s", ctime(&t));
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>
2002-06-21 06:18:05 +00:00
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')
return;
fprintf(stderr, "Level %jd dump of %s on %s:%s\n",
(intmax_t)spcl.c_level, spcl.c_filesys, spcl.c_host, spcl.c_dev);
fprintf(stderr, "Label: %s\n", spcl.c_label);
}
int
extractfile(char *name)
{
int flags;
uid_t uid;
gid_t gid;
mode_t mode;
int extsize;
struct timeval mtimep[2], ctimep[2];
struct entry *ep;
char *buf;
curfile.name = name;
curfile.action = USING;
mtimep[0].tv_sec = curfile.atime_sec;
mtimep[0].tv_usec = curfile.atime_nsec / 1000;
mtimep[1].tv_sec = curfile.mtime_sec;
mtimep[1].tv_usec = curfile.mtime_nsec / 1000;
ctimep[0].tv_sec = curfile.atime_sec;
ctimep[0].tv_usec = curfile.atime_nsec / 1000;
ctimep[1].tv_sec = curfile.birthtime_sec;
ctimep[1].tv_usec = curfile.birthtime_nsec / 1000;
extsize = curfile.extsize;
uid = getuid();
if (uid == 0)
uid = curfile.uid;
gid = curfile.gid;
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>
2002-06-21 06:18:05 +00:00
mode = curfile.mode;
flags = curfile.file_flags;
switch (mode & IFMT) {
default:
fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode);
skipfile();
return (FAIL);
case IFSOCK:
vprintf(stdout, "skipped socket %s\n", name);
skipfile();
return (GOOD);
case IFDIR:
if (mflag) {
ep = lookupname(name);
if (ep == NULL || ep->e_flags & EXTRACT)
panic("unextracted directory %s\n", name);
skipfile();
return (GOOD);
}
vprintf(stdout, "extract file %s\n", name);
return (genliteraldir(name, curfile.ino));
case IFLNK:
lnkbuf[0] = '\0';
pathlen = 0;
buf = setupextattr(extsize);
getfile(xtrlnkfile, xtrattr, xtrlnkskip);
if (pathlen == 0) {
vprintf(stdout,
"%s: zero length symbolic link (ignored)\n", name);
return (GOOD);
}
if (linkit(lnkbuf, name, SYMLINK) == GOOD) {
if (extsize > 0)
set_extattr_link(name, buf, extsize);
(void) lchown(name, uid, gid);
(void) lchmod(name, mode);
(void) lutimes(name, ctimep);
(void) lutimes(name, mtimep);
(void) lchflags(name, flags);
return (GOOD);
}
return (FAIL);
1995-02-10 21:57:02 +00:00
case IFIFO:
vprintf(stdout, "extract fifo %s\n", name);
if (Nflag) {
skipfile();
return (GOOD);
}
if (uflag)
(void) unlink(name);
if (mkfifo(name, 0600) < 0) {
fprintf(stderr, "%s: cannot create fifo: %s\n",
name, strerror(errno));
1995-02-10 21:57:02 +00:00
skipfile();
return (FAIL);
}
if (extsize == 0) {
skipfile();
} else {
buf = setupextattr(extsize);
getfile(xtrnull, xtrattr, xtrnull);
set_extattr_file(name, buf, extsize);
}
(void) chown(name, uid, gid);
1995-02-10 21:57:02 +00:00
(void) chmod(name, mode);
(void) utimes(name, ctimep);
(void) utimes(name, mtimep);
(void) chflags(name, flags);
1995-02-10 21:57:02 +00:00
return (GOOD);
case IFCHR:
case IFBLK:
vprintf(stdout, "extract special file %s\n", name);
if (Nflag) {
skipfile();
return (GOOD);
}
if (uflag)
(void) unlink(name);
if (mknod(name, (mode & (IFCHR | IFBLK)) | 0600,
2006-08-25 09:14:23 +00:00
(int)curfile.rdev) < 0) {
fprintf(stderr, "%s: cannot create special file: %s\n",
name, strerror(errno));
skipfile();
return (FAIL);
}
if (extsize == 0) {
skipfile();
} else {
buf = setupextattr(extsize);
getfile(xtrnull, xtrattr, xtrnull);
set_extattr_file(name, buf, extsize);
}
(void) chown(name, uid, gid);
(void) chmod(name, mode);
(void) utimes(name, ctimep);
(void) utimes(name, mtimep);
(void) chflags(name, flags);
return (GOOD);
case IFREG:
vprintf(stdout, "extract file %s\n", name);
if (Nflag) {
skipfile();
return (GOOD);
}
if (uflag)
(void) unlink(name);
if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC,
0600)) < 0) {
fprintf(stderr, "%s: cannot create file: %s\n",
name, strerror(errno));
skipfile();
return (FAIL);
}
buf = setupextattr(extsize);
getfile(xtrfile, xtrattr, xtrskip);
if (extsize > 0)
set_extattr_fd(ofile, name, buf, extsize);
(void) fchown(ofile, uid, gid);
(void) fchmod(ofile, mode);
(void) futimes(ofile, ctimep);
(void) futimes(ofile, mtimep);
(void) fchflags(ofile, flags);
(void) close(ofile);
return (GOOD);
}
/* NOTREACHED */
}
/*
* Set attributes for a file.
*/
void
set_extattr_file(char *name, void *buf, int size)
{
struct extattr *eap, *eaend;
vprintf(stdout, "Set attributes for %s:", name);
eaend = buf + size;
for (eap = buf; eap < eaend; eap = EXTATTR_NEXT(eap)) {
/*
* Make sure this entry is complete.
*/
if (EXTATTR_NEXT(eap) > eaend || eap->ea_length <= 0) {
dprintf(stdout, "\n\t%scorrupted",
eap == buf ? "" : "remainder ");
break;
}
if (eap->ea_namespace == EXTATTR_NAMESPACE_EMPTY)
continue;
vprintf(stdout, "\n\t%s, (%d bytes), %*s",
namespace_names[eap->ea_namespace], eap->ea_length,
eap->ea_namelength, eap->ea_name);
/*
* First we try the general attribute setting interface.
* However, some attributes can only be set by root or
* by using special interfaces (for example, ACLs).
*/
if (extattr_set_file(name, eap->ea_namespace, eap->ea_name,
EXTATTR_CONTENT(eap), EXTATTR_CONTENT_SIZE(eap)) != -1) {
dprintf(stdout, " (set using extattr_set_file)");
continue;
}
/*
* If the general interface refuses to set the attribute,
* then we try all the specialized interfaces that we
* know about.
*/
if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
!strcmp(eap->ea_name, POSIX1E_ACL_ACCESS_EXTATTR_NAME)) {
if (acl_set_file(name, ACL_TYPE_ACCESS,
EXTATTR_CONTENT(eap)) != -1) {
dprintf(stdout, " (set using acl_set_file)");
continue;
}
}
if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
!strcmp(eap->ea_name, POSIX1E_ACL_DEFAULT_EXTATTR_NAME)) {
if (acl_set_file(name, ACL_TYPE_DEFAULT,
EXTATTR_CONTENT(eap)) != -1) {
dprintf(stdout, " (set using acl_set_file)");
continue;
}
}
vprintf(stdout, " (unable to set)");
}
vprintf(stdout, "\n");
}
/*
* Set attributes for a symbolic link.
*/
static void
set_extattr_link(char *name, void *buf, int size)
{
struct extattr *eap, *eaend;
vprintf(stdout, "Set attributes for %s:", name);
eaend = buf + size;
for (eap = buf; eap < eaend; eap = EXTATTR_NEXT(eap)) {
/*
* Make sure this entry is complete.
*/
if (EXTATTR_NEXT(eap) > eaend || eap->ea_length <= 0) {
dprintf(stdout, "\n\t%scorrupted",
eap == buf ? "" : "remainder ");
break;
}
if (eap->ea_namespace == EXTATTR_NAMESPACE_EMPTY)
continue;
vprintf(stdout, "\n\t%s, (%d bytes), %*s",
namespace_names[eap->ea_namespace], eap->ea_length,
eap->ea_namelength, eap->ea_name);
/*
* First we try the general attribute setting interface.
* However, some attributes can only be set by root or
* by using special interfaces (for example, ACLs).
*/
if (extattr_set_link(name, eap->ea_namespace, eap->ea_name,
EXTATTR_CONTENT(eap), EXTATTR_CONTENT_SIZE(eap)) != -1) {
dprintf(stdout, " (set using extattr_set_link)");
continue;
}
/*
* If the general interface refuses to set the attribute,
* then we try all the specialized interfaces that we
* know about.
*/
if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
!strcmp(eap->ea_name, POSIX1E_ACL_ACCESS_EXTATTR_NAME)) {
if (acl_set_link_np(name, ACL_TYPE_ACCESS,
EXTATTR_CONTENT(eap)) != -1) {
dprintf(stdout, " (set using acl_set_link_np)");
continue;
}
}
if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
!strcmp(eap->ea_name, POSIX1E_ACL_DEFAULT_EXTATTR_NAME)) {
if (acl_set_link_np(name, ACL_TYPE_DEFAULT,
EXTATTR_CONTENT(eap)) != -1) {
dprintf(stdout, " (set using acl_set_link_np)");
continue;
}
}
vprintf(stdout, " (unable to set)");
}
vprintf(stdout, "\n");
}
/*
* Set attributes on a file descriptor.
*/
static void
set_extattr_fd(int fd, char *name, void *buf, int size)
{
struct extattr *eap, *eaend;
vprintf(stdout, "Set attributes for %s:", name);
eaend = buf + size;
for (eap = buf; eap < eaend; eap = EXTATTR_NEXT(eap)) {
/*
* Make sure this entry is complete.
*/
if (EXTATTR_NEXT(eap) > eaend || eap->ea_length <= 0) {
dprintf(stdout, "\n\t%scorrupted",
eap == buf ? "" : "remainder ");
break;
}
if (eap->ea_namespace == EXTATTR_NAMESPACE_EMPTY)
continue;
vprintf(stdout, "\n\t%s, (%d bytes), %*s",
namespace_names[eap->ea_namespace], eap->ea_length,
eap->ea_namelength, eap->ea_name);
/*
* First we try the general attribute setting interface.
* However, some attributes can only be set by root or
* by using special interfaces (for example, ACLs).
*/
if (extattr_set_fd(fd, eap->ea_namespace, eap->ea_name,
EXTATTR_CONTENT(eap), EXTATTR_CONTENT_SIZE(eap)) != -1) {
dprintf(stdout, " (set using extattr_set_fd)");
continue;
}
/*
* If the general interface refuses to set the attribute,
* then we try all the specialized interfaces that we
* know about.
*/
if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
!strcmp(eap->ea_name, POSIX1E_ACL_ACCESS_EXTATTR_NAME)) {
if (acl_set_fd(fd, EXTATTR_CONTENT(eap)) != -1) {
dprintf(stdout, " (set using acl_set_fd)");
continue;
}
}
if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
!strcmp(eap->ea_name, POSIX1E_ACL_DEFAULT_EXTATTR_NAME)) {
if (acl_set_file(name, ACL_TYPE_DEFAULT,
EXTATTR_CONTENT(eap)) != -1) {
dprintf(stdout, " (set using acl_set_file)");
continue;
}
}
vprintf(stdout, " (unable to set)");
}
vprintf(stdout, "\n");
}
/*
* skip over bit maps on the tape
*/
void
skipmaps(void)
{
while (spcl.c_type == TS_BITS || spcl.c_type == TS_CLRI)
skipfile();
}
/*
* skip over a file on the tape
*/
void
skipfile(void)
{
curfile.action = SKIP;
getfile(xtrnull, xtrnull, xtrnull);
}
/*
* Extract a file from the tape.
* When an allocated block is found it is passed to the fill function;
* when an unallocated block (hole) is found, a zeroed buffer is passed
* to the skip function.
*/
void
getfile(void (*datafill)(char *, long), void (*attrfill)(char *, long),
void (*skip)(char *, long))
{
int i;
off_t size;
int curblk, attrsize;
void (*fillit)(char *, long);
static char clearedbuf[MAXBSIZE];
char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
char junk[TP_BSIZE];
curblk = 0;
size = spcl.c_size;
attrsize = spcl.c_extsize;
if (spcl.c_type == TS_END)
panic("ran off end of tape\n");
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>
2002-06-21 06:18:05 +00:00
if (spcl.c_magic != FS_UFS2_MAGIC)
panic("not at beginning of a file\n");
if (!gettingfile && setjmp(restart) != 0)
return;
gettingfile++;
fillit = datafill;
if (size == 0 && attrsize > 0) {
fillit = attrfill;
size = attrsize;
attrsize = 0;
}
loop:
for (i = 0; i < spcl.c_count; i++) {
if (!readmapflag && i > TP_NINDIR) {
if (Dflag) {
fprintf(stderr, "spcl.c_count = %jd\n",
(intmax_t)spcl.c_count);
break;
} else
panic("spcl.c_count = %jd\n",
(intmax_t)spcl.c_count);
}
if (readmapflag || spcl.c_addr[i]) {
readtape(&buf[curblk++][0]);
if (curblk == fssize / TP_BSIZE) {
(*fillit)((char *)buf, (long)(size > TP_BSIZE ?
fssize : (curblk - 1) * TP_BSIZE + size));
curblk = 0;
}
} else {
if (curblk > 0) {
(*fillit)((char *)buf, (long)(size > TP_BSIZE ?
curblk * TP_BSIZE :
(curblk - 1) * TP_BSIZE + size));
curblk = 0;
}
(*skip)(clearedbuf, (long)(size > TP_BSIZE ?
TP_BSIZE : size));
}
if ((size -= TP_BSIZE) <= 0) {
if (size > -TP_BSIZE && curblk > 0) {
(*fillit)((char *)buf,
(long)((curblk * TP_BSIZE) + size));
curblk = 0;
}
if (attrsize > 0) {
fillit = attrfill;
size = attrsize;
attrsize = 0;
continue;
}
if (spcl.c_count - i > 1)
dprintf(stdout, "skipping %d junk block(s)\n",
spcl.c_count - i - 1);
for (i++; i < spcl.c_count; i++) {
if (!readmapflag && i > TP_NINDIR) {
if (Dflag) {
fprintf(stderr,
"spcl.c_count = %jd\n",
(intmax_t)spcl.c_count);
break;
} else
panic("spcl.c_count = %jd\n",
(intmax_t)spcl.c_count);
}
if (readmapflag || spcl.c_addr[i])
readtape(junk);
}
break;
}
}
if (gethead(&spcl) == GOOD && size > 0) {
if (spcl.c_type == TS_ADDR)
goto loop;
dprintf(stdout,
"Missing address (header) block for %s at %ld blocks\n",
curfile.name, blksread);
}
if (curblk > 0)
panic("getfile: lost data\n");
findinode(&spcl);
gettingfile = 0;
}
/*
* These variables are shared between the next two functions.
*/
static int extbufsize = 0;
static char *extbuf;
static int extloc;
/*
* Allocate a buffer into which to extract extended attributes.
*/
static char *
setupextattr(int extsize)
{
extloc = 0;
if (extsize <= extbufsize)
return (extbuf);
if (extbufsize > 0)
free(extbuf);
if ((extbuf = malloc(extsize)) != NULL) {
extbufsize = extsize;
return (extbuf);
}
extbufsize = 0;
extbuf = NULL;
fprintf(stderr, "Cannot extract %d bytes %s for inode %ju, name %s\n",
extsize, "of extended attributes", (uintmax_t)curfile.ino,
curfile.name);
return (NULL);
}
/*
* Extract the next block of extended attributes.
*/
static void
xtrattr(char *buf, long size)
{
if (extloc + size > extbufsize)
panic("overrun attribute buffer\n");
memmove(&extbuf[extloc], buf, size);
extloc += size;
}
/*
* Write out the next block of a file.
*/
static void
xtrfile(char *buf, long size)
{
if (Nflag)
return;
if (write(ofile, buf, (int) size) == -1) {
fprintf(stderr,
"write error extracting inode %ju, name %s\nwrite: %s\n",
(uintmax_t)curfile.ino, curfile.name, strerror(errno));
}
}
/*
* Skip over a hole in a file.
*/
/* ARGSUSED */
static void
xtrskip(char *buf, long size)
{
if (lseek(ofile, size, SEEK_CUR) == -1) {
fprintf(stderr,
"seek error extracting inode %ju, name %s\nlseek: %s\n",
(uintmax_t)curfile.ino, curfile.name, strerror(errno));
done(1);
}
}
/*
* Collect the next block of a symbolic link.
*/
static void
xtrlnkfile(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 void
xtrlnkskip(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 void
xtrmap(char *buf, long size)
{
memmove(map, buf, size);
map += size;
}
/*
* Skip over a hole in a bit map (should never happen).
*/
/* ARGSUSED */
static void
xtrmapskip(char *buf, long size)
{
panic("hole in map\n");
map += size;
}
/*
* Noop, when an extraction function is not needed.
*/
/* ARGSUSED */
void
xtrnull(char *buf, long size)
{
return;
}
/*
* Read TP_BSIZE blocks from the input.
* Handle read errors, and end of media.
*/
static void
readtape(char *buf)
{
long rd, newvol, i, oldnumtrec;
int cnt, seek_failed;
if (blkcnt + (byteslide > 0) < numtrec) {
memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE) + byteslide], (long)TP_BSIZE);
blksread++;
tapeaddr++;
return;
}
if (numtrec > 0)
memmove(&tapebuf[-TP_BSIZE],
&tapebuf[(numtrec-1) * TP_BSIZE], (long)TP_BSIZE);
oldnumtrec = numtrec;
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 && !pipecmdin && numtrec < ntrec && i > 0) {
dprintf(stdout, "mid-media short read error.\n");
numtrec = ntrec;
}
/*
* Handle partial block read.
*/
if ((pipein || pipecmdin) && i == 0 && rd > 0)
i = rd;
else if (i > 0 && i != ntrec * TP_BSIZE) {
if (pipein || pipecmdin) {
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: %ld should be %ld\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 %ju\n",
(uintmax_t)curfile.ino);
break;
}
if (!yflag && !reply("continue"))
done(1);
i = ntrec * TP_BSIZE;
memset(tapebuf, 0, 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: %ld should be %ld\n",
rd, ntrec * TP_BSIZE);
terminateinput();
memmove(&tapebuf[rd], &endoftapemark, (long)TP_BSIZE);
}
if (oldnumtrec == 0)
blkcnt = 0;
else
blkcnt -= oldnumtrec;
memmove(buf,
&tapebuf[(blkcnt++ * TP_BSIZE) + byteslide], (long)TP_BSIZE);
blksread++;
tapeaddr++;
}
static void
findtapeblksize(void)
{
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 (%ld) %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 %ld\n", ntrec);
}
void
closemt(void)
{
if (mt < 0)
return;
if (pipecmdin) {
pclose(popenfp);
popenfp = NULL;
} else
#ifdef RRESTORE
if (host)
rmtclose();
else
#endif
(void) close(mt);
}
/*
* Read the next block from the tape.
* If it is not any valid header, return an error.
*/
static int
gethead(struct s_spcl *buf)
{
long i;
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>
2002-06-21 06:18:05 +00:00
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);
}
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>
2002-06-21 06:18:05 +00:00
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);
}
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>
2002-06-21 06:18:05 +00:00
if (!Bcvt) {
vprintf(stdout, "Note: Doing Byte swapping\n");
Bcvt = 1;
}
}
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>
2002-06-21 06:18:05 +00:00
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;
switch (buf->c_type) {
case TS_CLRI:
case TS_BITS:
/*
* Have to patch up missing information in bit map headers
*/
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>
2002-06-21 06:18:05 +00:00
buf->c_size = buf->c_count * TP_BSIZE;
if (buf->c_count > TP_NINDIR)
readmapflag = 1;
else
for (i = 0; i < buf->c_count; i++)
buf->c_addr[i]++;
/* FALL THROUGH */
case TS_TAPE:
if (buf->c_magic == NFS_MAGIC &&
(buf->c_flags & NFS_DR_NEWINODEFMT) == 0)
oldinofmt = 1;
/* FALL THROUGH */
case TS_END:
buf->c_inumber = 0;
/* FALL THROUGH */
case TS_ADDR:
case TS_INODE:
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>
2002-06-21 06:18:05 +00:00
/*
* 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);
buf->c_birthtime = 0;
buf->c_birthtimensec = 0;
buf->c_extsize = 0;
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>
2002-06-21 06:18:05 +00:00
}
break;
default:
panic("gethead: unknown inode type %d\n", buf->c_type);
break;
}
if (dumpdate != 0 && _time64_to_time(buf->c_date) != dumpdate)
fprintf(stderr, "Header with wrong dumpdate.\n");
/*
* If we're restoring a filesystem with the old (FreeBSD 1)
* format inodes, copy the uid/gid to the new location
*/
if (oldinofmt) {
buf->c_uid = buf->c_spare1[1];
buf->c_gid = buf->c_spare1[2];
}
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>
2002-06-21 06:18:05 +00:00
buf->c_magic = FS_UFS2_MAGIC;
tapeaddr = buf->c_tapea;
if (dflag)
accthdr(buf);
return(GOOD);
}
/*
* Check that a header is where it belongs and predict the next header
*/
static void
accthdr(struct s_spcl *header)
{
static ino_t previno = 0x7fffffff;
static int prevtype;
static long predict;
long blks, i;
if (header->c_type == TS_TAPE) {
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>
2002-06-21 06:18:05 +00:00
fprintf(stderr, "Volume header ");
if (header->c_firstrec)
fprintf(stderr, "begins with record %jd",
(intmax_t)header->c_firstrec);
fprintf(stderr, "\n");
previno = 0x7fffffff;
return;
}
if (previno == 0x7fffffff)
goto newcalc;
switch (prevtype) {
case TS_BITS:
fprintf(stderr, "Dumped inodes map header");
break;
case TS_CLRI:
fprintf(stderr, "Used inodes map header");
break;
case TS_INODE:
fprintf(stderr, "File header, ino %ju", (uintmax_t)previno);
break;
case TS_ADDR:
fprintf(stderr, "File continuation header, ino %ju",
(uintmax_t)previno);
break;
case TS_END:
fprintf(stderr, "End of tape header");
break;
}
if (predict != blksread - 1)
fprintf(stderr, "; predicted %ld blocks, got %ld 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 (readmapflag || 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.
*/
static void
findinode(struct s_spcl *header)
{
static long skipcnt = 0;
long i;
char buf[TP_BSIZE];
2002-02-13 12:06:58 +00:00
int htype;
curfile.name = "<name unknown>";
curfile.action = UNKNOWN;
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>
2002-06-21 06:18:05 +00:00
curfile.mode = 0;
curfile.ino = 0;
do {
2002-02-13 12:06:58 +00:00
htype = header->c_type;
switch (htype) {
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 ||
_time64_to_time(header->c_date) != dumpdate) {
skipcnt++;
if (Dflag) {
byteslide++;
if (byteslide < TP_BSIZE) {
blkcnt--;
blksread--;
} else
byteslide = 0;
}
}
break;
case TS_INODE:
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>
2002-06-21 06:18:05 +00:00
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.birthtime_sec = header->c_birthtime;
curfile.birthtime_nsec = header->c_birthtimensec;
curfile.extsize = header->c_extsize;
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>
2002-06-21 06:18:05 +00:00
curfile.size = header->c_size;
curfile.ino = header->c_inumber;
break;
case TS_END:
/* If we missed some tapes, get another volume. */
if (tapesread & (tapesread + 1)) {
getvol(0);
continue;
}
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:
if (Dflag)
fprintf(stderr, "unexpected tape header\n");
else
panic("unexpected tape header\n");
default:
if (Dflag)
fprintf(stderr, "unknown tape header type %d\n",
spcl.c_type);
else
panic("unknown tape header type %d\n",
spcl.c_type);
while (gethead(header) == FAIL ||
_time64_to_time(header->c_date) != dumpdate) {
skipcnt++;
if (Dflag) {
byteslide++;
if (byteslide < TP_BSIZE) {
blkcnt--;
blksread--;
} else
byteslide = 0;
}
}
}
2002-02-13 12:06:58 +00:00
} while (htype == TS_ADDR);
if (skipcnt > 0)
fprintf(stderr, "resync restore, skipped %ld %s\n",
skipcnt, Dflag ? "bytes" : "blocks");
skipcnt = 0;
}
static int
checksum(int *buf)
{
int i, j;
j = sizeof(union u_spcl) / sizeof(int);
i = 0;
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>
2002-06-21 06:18:05 +00:00
if (!Bcvt) {
do
i += *buf++;
while (--j);
} else {
/* What happens if we want to read restore tapes
for a 16bit int machine??? */
1995-05-30 06:12:45 +00:00
do
i += swabl(*buf++);
while (--j);
}
1995-05-30 06:12:45 +00:00
if (i != CHECKSUM) {
fprintf(stderr, "Checksum error %o, inode %ju file %s\n", i,
(uintmax_t)curfile.ino, curfile.name);
return(FAIL);
}
return(GOOD);
}
#ifdef RRESTORE
#include <stdarg.h>
void
msg(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
(void)vfprintf(stderr, fmt, ap);
va_end(ap);
}
#endif /* RRESTORE */
static u_char *
swabshort(u_char *sp, 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(u_char *sp, 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);
}
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>
2002-06-21 06:18:05 +00:00
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)
{
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;
1995-05-30 06:12:45 +00:00
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;
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>
2002-06-21 06:18:05 +00:00
case 'q':
if (n == 0)
n = 1;
sp = swabquad(sp, n);
break;
case 'b':
if (n == 0)
n = 1;
sp += n;
break;
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>
2002-06-21 06:18:05 +00:00
default:
fprintf(stderr, "Unknown conversion character: %c\n",
*cp);
done(0);
break;
}
cp++;
n = 0;
}
}
static u_long
swabl(u_long x)
{
swabst((u_char *)"l", (u_char *)&x);
return (x);
}