-Q on remote tape/files.
-$Id: CHANGES,v 1.157 2002/01/22 11:12:28 stelian Exp $
+$Id: CHANGES,v 1.158 2002/01/25 14:59:53 stelian Exp $
Changes between versions 0.4b26 and 0.4b27 (released ???????????????)
=====================================================================
restores in -i or -x mode (automatically walks through the
multiple dump volumes).
-5. Extended the QFA mode to work with local files. This way,
- restore can know in advance the tape number and the offset
- for the inodes to extract and can minimize the extraction
- time by seeking directly to the good tape/offset.
+5. Extended the QFA mode to work with local files and/or
+ remote tapes and files. This way, restore can know in advance
+ the tape number and the offset for the inodes to extract and
+ can minimize the extraction time by seeking directly to the
+ good tape/offset.
+
+6. Added the -A <archive> option to both dump and restore,
+ which makes dump to archive a dump table-of-contents in
+ the specified file to be used by restore to determine
+ whether a file is in the dump file that is being restored.
+ (the archive file syntax is also compatible with the
+ Solaris ufsdump generated one).
Changes between versions 0.4b25 and 0.4b26 (released January 7, 2002)
=====================================================================
-$Id: THANKS,v 1.52 2002/01/16 09:32:14 stelian Exp $
+$Id: THANKS,v 1.53 2002/01/25 14:59:53 stelian Exp $
Dump and restore were written by the people of the CSRG at the University
of California, Berkeley.
Ian Gordon iangordon@users.sourceforge.net
Andreas Hasenack andreas@conectiva.com.br
Christian Haul haul@informatik.tu-darmstadt.de
+Kjetil Torgrim Homme kjetilho@ifi.uio.no
Jean-Paul van der Jagt jeanpaul@dutepp0.et.tudelft.nl
Helmut Jarausch jarausch@igpm.rwth-aachen.de
Eric Jergensen eric@dvns.com
-$Id: TODO,v 1.23 2001/08/16 15:24:21 stelian Exp $
+$Id: TODO,v 1.24 2002/01/25 14:59:53 stelian Exp $
Need to verify:
---------------
5. Make a bootable dump tape? I don't know if it is possible...
-6. From Kjetil Torgrim Homme <kjetilho@ifi.uio.no>:
- a archive_file
- Archive file. Archive a dump table-of-contents in
- the specified archive_file to be used by
- ufsrestore(1M) to determine whether a file is in
- the dump file that is being restored.
-
-7. EA/ACL support in dump (requested by Michael Ju. Tokarev
+6. EA/ACL support in dump (requested by Michael Ju. Tokarev
<mjt@tls.msk.ru>.
-8. Better readline completition in restore (escape spaces etc).
-
-9. Dump compiled with RedHat's 7.0 gcc seems to hang for some
- people. When compiled with kgcc all the problems disappear.
- Will the RedHat's 7.1 gcc resolve this ?
+7. Better readline completition in restore (escape spaces etc).
* Stelian Pop <stelian@popies.net>, 1999-2000
* Stelian Pop <stelian@popies.net> - Alcôve <www.alcove.com>, 2000-2002
*
- * $Id: dumprestore.h,v 1.15 2002/01/16 09:32:14 stelian Exp $
+ * $Id: dumprestore.h,v 1.16 2002/01/25 14:59:53 stelian Exp $
*/
/*
#define NTREC 10
#define HIGHDENSITYTREC 32
#define TP_NINDIR (TP_BSIZE/2)
+#define TP_NINOS (TP_NINDIR / sizeof (int32_t))
#define LBLSIZE 16
#define NAMELEN 64
typedef u_int32_t dump_ino_t;
+union u_data {
+ char s_addrs[TP_NINDIR]; /* 1 => data; 0 => hole in inode */
+ int32_t s_inos[TP_NINOS]; /* table of first inode on each volume */
+} u_data;
+
union u_spcl {
char dummy[TP_BSIZE];
struct s_spcl {
struct dinode c_dinode; /* ownership and mode of inode */
#endif
int32_t c_count; /* number of valid c_addr entries */
- char c_addr[TP_NINDIR]; /* 1 => data; 0 => hole in inode */
+ union u_data c_data; /* see above */
char c_label[LBLSIZE]; /* dump label */
int32_t c_level; /* level of this dump */
char c_filesys[NAMELEN]; /* name of dumpped file system */
} s_spcl;
} u_spcl;
#define spcl u_spcl.s_spcl
+#define c_addr c_data.s_addrs
+#define c_inos c_data.s_inos
+
/*
* special record types
*/
#define DR_NEWHEADER 0x0001 /* new format tape header */
#define DR_NEWINODEFMT 0x0002 /* new format inodes on tape */
#define DR_COMPRESSED 0x0080 /* dump tape is compressed */
+#define DR_INODEINFO 0x0002 /* TS_END header contains c_inos information */
+
/*
* compression flags for the tapebuf header.
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $Id: dump.8.in,v 1.36 2002/01/22 11:12:28 stelian Exp $
+.\" $Id: dump.8.in,v 1.37 2002/01/25 14:59:53 stelian Exp $
.\"
.Dd __DATE__
.Dt DUMP 8
.Sh SYNOPSIS
.Nm dump
.Op Fl 0123456789ackMnqSu
+.Op Fl A Ar file
.Op Fl B Ar records
.Op Fl b Ar blocksize
.Op Fl d Ar density
copy all files new or modified since the
last dump of a lower level.
The default level is 9.
-.It Fl B Ar records
-The number of 1 kB blocks per volume.
-This option overrides the end-of-media detection, and calculation
-of tape size based on length and density. If compression is on this
-limits the size of the compressed output per volume.
.It Fl a
.Dq auto-size .
Bypass all tape length calculations, and write
Use of this option is particularly recommended when appending to an
existing tape, or using a tape drive with hardware compression
(where you can never be sure about the compression ratio).
+.It Fl A Ar archive_file
+Archive a dump table-of-contents in the
+specified
+.Ar archive_file
+to be used by
+.Xr restore 8
+to determine whether a file is in the dump file that is being restored.
.It Fl b Ar blocksize
The number of kilobytes per dump record.
Since the IO system slices all requests into chunks of MAXBSIZE
.Nm dump
will constrain writes to MAXBSIZE.
The default blocksize is 10.
+.It Fl B Ar records
+The number of 1 kB blocks per volume.
+This option overrides the end-of-media detection, and calculation
+of tape size based on length and density. If compression is on this
+limits the size of the compressed output per volume.
.It Fl c
Change the defaults for use with a cartridge tape drive, with a density
of 8000 bpi, and a length of 1700 feet. Specifying a cartridge drive
overrides the end-of-media detection.
+.It Fl d Ar density
+Set tape density to
+.Ar density .
+The default is 1600BPI. Specifying a tape density overrides the
+end-of-media detection.
.It Fl e Ar inodes
Exclude
.Ar inodes
.Ar file
should be an ordinary file containing inode numbers separated by
newlines.
-.It Fl h Ar level
-Honor the user
-.Dq nodump
-flag
-.Dp Dv UF_NODUMP
-only for dumps at or above the given
-.Ar level .
-The default honor level is 1,
-so that incremental backups omit such files
-but full backups retain them.
-.It Fl d Ar density
-Set tape density to
-.Ar density .
-The default is 1600BPI. Specifying a tape density overrides the
-end-of-media detection.
.It Fl f Ar file
Write the backup to
.Ar file ;
.Nm
reverts back to the real user ID and the real group ID before
running the script.
+.It Fl h Ar level
+Honor the user
+.Dq nodump
+flag
+.Dp Dv UF_NODUMP
+only for dumps at or above the given
+.Ar level .
+The default honor level is 1,
+so that incremental backups omit such files
+but full backups retain them.
.It Fl I Ar nr errors
By default,
.Nm
* Stelian Pop <stelian@popies.net>, 1999-2000
* Stelian Pop <stelian@popies.net> - Alcôve <www.alcove.com>, 2000-2002
*
- * $Id: dump.h,v 1.35 2002/01/22 11:12:28 stelian Exp $
+ * $Id: dump.h,v 1.36 2002/01/25 14:59:53 stelian Exp $
*/
/*-
/*
* All calculations done in 0.1" units!
*/
+extern char *host; /* name of the remote host */
extern const char *disk; /* name of the disk file */
extern char tape[MAXPATHLEN];/* name of the tape file */
extern char *tapeprefix; /* prefix of the tape file */
extern char *dumpdates; /* name of the file containing dump date information*/
extern char lastlevel; /* dump level of previous dump */
extern char level; /* dump level of this dump */
+extern int Afile; /* archive file descriptor */
extern int bzipflag; /* compression is done using bzlib */
extern int uflag; /* update flag */
extern int Mflag; /* multi-volume flag */
extern long dev_bsize; /* block size of underlying disk device */
extern int dev_bshift; /* log2(dev_bsize) */
extern int tp_bshift; /* log2(TP_BSIZE) */
+extern dump_ino_t volinfo[]; /* which inode on which volume archive info */
#ifdef USE_QFA
#define QFA_MAGIC "495115637697"
#endif
void dumpmap __P((char *map, int type, dump_ino_t ino));
void writeheader __P((dump_ino_t ino));
+void mkchecksum __P((union u_spcl *tmpspcl));
/* tape writing routines */
int alloctape __P((void));
#ifndef lint
static const char rcsid[] =
- "$Id: main.c,v 1.66 2002/01/22 11:12:28 stelian Exp $";
+ "$Id: main.c,v 1.67 2002/01/25 14:59:53 stelian Exp $";
#endif /* not lint */
#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <errno.h>
#include <sys/param.h>
#include <sys/time.h>
char lastlevel; /* dump level of previous dump */
char level; /* dump level of this dump */
int bzipflag; /* compression is done using bzlib */
+int Afile = 0; /* archive file descriptor */
int uflag; /* update flag */
int Mflag; /* multi-volume flag */
int qflag; /* quit on errors flag */
long dev_bsize; /* block size of underlying disk device */
int dev_bshift; /* log2(dev_bsize) */
int tp_bshift; /* log2(TP_BSIZE) */
+dump_ino_t volinfo[TP_NINOS];/* which inode on which volume archive info */
#ifdef USE_QFA
int gTapeposfd;
#endif
time_t tnow;
char *diskparam;
+ char *Apath;
spcl.c_label[0] = '\0';
spcl.c_date = time(NULL);
#endif /* USE_QFA */
while ((ch = getopt(argc, argv,
- "0123456789aB:b:cd:e:E:f:F:h:I:"
+ "0123456789A:aB:b:cd:e:E:f:F:h:I:"
#ifdef HAVE_BZLIB
"j::"
#endif
level = ch;
break;
+ case 'A': /* archive file */
+ Apath = optarg;
+ if ((Afile = open(Apath, O_RDWR|O_CREAT|O_TRUNC,
+ S_IRUSR | S_IWUSR)) < 0) {
+ msg("Cannot open %s for writing: %s\n",
+ optarg, strerror(errno));
+ msg("The ENTIRE dump is aborted.\n");
+ exit(X_STARTUP);
+ }
+ memset(volinfo, 0, TP_NINOS * sizeof(dump_ino_t));
+ break;
+
case 'a': /* `auto-size', Write to EOM. */
unlimited = 1;
aflag = 1;
tapeprefix = strchr(host, ':');
*tapeprefix++ = '\0';
#ifdef RDUMP
-#ifdef USE_QFA
- if (tapepos) {
- msg("Cannot use -Q option on remote media\n");
- msg("The ENTIRE dump is aborted.\n");
- exit(X_STARTUP);
- }
-#endif
if (index(tapeprefix, '\n')) {
msg("invalid characters in tape\n");
msg("The ENTIRE dump is aborted.\n");
tend_writing = time(NULL);
spcl.c_type = TS_END;
+
+ if (Afile) {
+ volinfo[1] = ROOTINO;
+ memcpy(spcl.c_inos, volinfo, TP_NINOS * sizeof(dump_ino_t));
+ spcl.c_flags |= DR_INODEINFO;
+ }
+
/*
* Finish off the current tape record with trailer blocks, to ensure
* at least the data in the last partial record makes it to tape.
spcl.c_tapea, tapekb, rate);
}
+ if (Afile)
+ msg("Archiving dump to %s\n", Apath);
+
broadcast("DUMP IS DONE!\7\7\n");
msg("DUMP IS DONE\n");
Exit(X_FINOK);
"k"
#endif
"MnqSu"
- "] [-B records] [-b blocksize] [-d density]\n"
- "\t%s [-e inode#,inode#,...] [-E file] [-f file] [-h level]\n"
- "\t%s [-I nr errors] "
+ "] [-A file] [-B records] [-b blocksize]\n"
+ "\t%s [-d density] [-e inode#,inode#,...] [-E file] [-f file]\n"
+ "\t%s [-h level] [-I nr errors] "
#ifdef HAVE_BZLIB
"[-j zlevel] "
#endif
#ifdef USE_QFA
"[-Q file] "
#endif
- "[-s feet] [-T date] "
+ "[-s feet]\n"
+ "\t%s [-T date] "
#ifdef HAVE_ZLIB
"[-z zlevel] "
#endif
"filesystem\n"
"\t%s [-W | -w]\n",
- __progname, white, white, __progname);
+ __progname, white, white, white, __progname);
exit(X_STARTUP);
}
for (flags = 0; *ap; ++ap) {
switch (*ap) {
+ case 'A':
case 'B':
case 'b':
case 'd':
#ifndef lint
static const char rcsid[] =
- "$Id: tape.c,v 1.60 2002/01/22 11:12:28 stelian Exp $";
+ "$Id: tape.c,v 1.61 2002/01/25 14:59:53 stelian Exp $";
#endif /* not lint */
#include <config.h>
#include <linux/ext2_fs.h>
#endif
#include <ext2fs/ext2fs.h>
+#include <sys/stat.h>
#include <bsdcompat.h>
#elif defined sunos
#include <sys/vnode.h>
long blocksthisvol; /* number of blocks on current output file */
extern int ntrec; /* blocking factor on tape */
extern int cartridge;
-extern char *host;
char *nexttape;
extern pid_t rshpid;
int eot_code = 1;
static void killall __P((void));
static void rollforward __P((void));
#ifdef USE_QFA
-static int GetTapePos __P((long *));
-static void MkTapeString __P((struct s_spcl *, long));
+static int GetTapePos __P((long long *));
+static void MkTapeString __P((struct s_spcl *, long long));
#endif
/*
slp->req[trecno].count = 1;
/* XXX post increment triggers an egcs-1.1.2-12 bug on alpha/sparc */
*(union u_spcl *)(*(nextblock)) = *(union u_spcl *)dp;
+
+ /* Need to write it to the archive file */
+ if (Afile < 0 && isspcl && (spcl.c_type == TS_END))
+ Afile = -Afile;
+ if (Afile > 0) {
+ /* When we dump an inode which is not a directory,
+ * it means we ended the archive contents */
+ if (isspcl && (spcl.c_type == TS_INODE) &&
+ ((spcl.c_dinode.di_mode & S_IFMT) != IFDIR))
+ Afile = -Afile;
+ else {
+ union u_spcl tmp;
+ tmp = *(union u_spcl *)dp;
+ /* Write the record, _uncompressed_ */
+ if (isspcl) {
+ tmp.s_spcl.c_flags &= ~DR_COMPRESSED;
+ mkchecksum(&tmp);
+ }
+ if (write(Afile, &tmp, TP_BSIZE) != TP_BSIZE)
+ msg("error writing archive file: %s\n",
+ strerror(errno));
+ }
+ }
+
nextblock++;
if (isspcl)
lastspclrec = spcl.c_tapea;
if (tapeno > 1)
msg("Volume %d begins with blocks from inode %d\n",
tapeno, slp->inode);
+ if (tapeno < TP_NINOS)
+ volinfo[tapeno] = slp->inode;
}
}
errcode_t retval;
#endif
#ifdef USE_QFA
- long curtapepos;
+ long long curtapepos;
union u_spcl *uspclptr;
struct s_spcl *spclptr;
#endif /* USE_QFA */
* read the current tape position
*/
static int
-GetTapePos(long *pos)
+GetTapePos(long long *pos)
{
int err = 0;
+#ifdef RDUMP
+ if (host) {
+ *pos = (long long) rmtseek(0, SEEK_CUR);
+ err = *pos < 0;
+ }
+ else
+#endif
+ {
if (magtapeout) {
+ long mtpos;
*pos = 0;
- err = (ioctl(tapefd, MTIOCPOS, pos) < 0);
+ err = (ioctl(tapefd, MTIOCPOS, &mtpos) < 0);
+ *pos = (long long)mtpos;
}
else {
- *pos = lseek(tapefd, 0, SEEK_CUR);
+ *pos = LSEEK(tapefd, 0, SEEK_CUR);
err = (*pos < 0);
}
+ }
if (err) {
err = errno;
- msg("[%ld] error: %d (getting tapepos: %ld)\n", getpid(),
+ msg("[%ld] error: %d (getting tapepos: %lld)\n", getpid(),
err, *pos);
return err;
}
}
static void
-MkTapeString(struct s_spcl *spclptr, long curtapepos) {
+MkTapeString(struct s_spcl *spclptr, long long curtapepos) {
#ifdef DEBUG_QFA
- msg("inode %ld at tapepos %ld\n", spclptr->c_inumber, curtapepos);
+ msg("inode %ld at tapepos %lld\n", spclptr->c_inumber, curtapepos);
#endif
- snprintf(gTps, sizeof(gTps), "%ld\t%d\t%ld\n",
+ snprintf(gTps, sizeof(gTps), "%ld\t%d\t%lld\n",
(unsigned long)spclptr->c_inumber,
tapeno,
curtapepos);
#ifndef lint
static const char rcsid[] =
- "$Id: traverse.c,v 1.40 2002/01/16 09:32:14 stelian Exp $";
+ "$Id: traverse.c,v 1.41 2002/01/25 14:59:53 stelian Exp $";
#endif /* not lint */
#include <config.h>
writerec(cp, 0);
}
-/*
- * Write a header record to the dump tape.
- */
#if defined __linux__ && !defined(int32_t)
#define int32_t __s32
#endif
+
+/*
+ * Compute and fill in checksum information.
+ */
void
-writeheader(dump_ino_t ino)
+mkchecksum(union u_spcl *tmpspcl)
{
- register int32_t sum, cnt, *lp;
+ int32_t sum, cnt, *lp;
- spcl.c_inumber = ino;
- spcl.c_magic = NFS_MAGIC;
- spcl.c_checksum = 0;
- lp = (int32_t *)&spcl;
+ tmpspcl->s_spcl.c_checksum = 0;
+ lp = (int32_t *)&tmpspcl->s_spcl;
sum = 0;
cnt = sizeof(union u_spcl) / (4 * sizeof(int32_t));
while (--cnt >= 0) {
sum += *lp++;
sum += *lp++;
}
- spcl.c_checksum = CHECKSUM - sum;
+ tmpspcl->s_spcl.c_checksum = CHECKSUM - sum;
+}
+
+/*
+ * Write a header record to the dump tape.
+ */
+void
+writeheader(dump_ino_t ino)
+{
+ spcl.c_inumber = ino;
+ spcl.c_magic = NFS_MAGIC;
+ mkchecksum((union u_spcl *)&spcl);
writerec((char *)&spcl, 1);
}
* Stelian Pop <stelian@popies.net>, 1999-2000
* Stelian Pop <stelian@popies.net> - Alcôve <www.alcove.com>, 2000-2002
*
- * $Id: extern.h,v 1.14 2002/01/16 09:32:14 stelian Exp $
+ * $Id: extern.h,v 1.15 2002/01/25 14:59:53 stelian Exp $
*/
/*-
void pathcheck __P((char *));
struct direct *pathsearch __P((const char *));
void printdumpinfo __P((void));
+void printvolinfo __P((void));
void removeleaf __P((struct entry *));
void removenode __P((struct entry *));
void removeoldleaves __P((void));
int setflags __P((int, unsigned long));
#ifdef USE_QFA
-int Inode2Tapepos __P((dump_ino_t, long *, long *, int));
-int GetTapePos __P((long *));
-int GotoTapePos __P((long));
+int Inode2Tapepos __P((dump_ino_t, long *, long long *, int));
+int GetTapePos __P((long long *));
+int GotoTapePos __P((long long));
void ReReadFromTape __P((void));
-void RequestVol __P((long));
#endif
+void RequestVol __P((long));
#ifndef lint
static const char rcsid[] =
- "$Id: interactive.c,v 1.19 2002/01/16 10:53:28 stelian Exp $";
+ "$Id: interactive.c,v 1.20 2002/01/25 14:59:53 stelian Exp $";
#endif /* not lint */
#include <config.h>
if (strncmp(cmd, "what", strlen(cmd)) != 0)
goto bad;
printdumpinfo();
+ printvolinfo();
break;
/*
* Turn on debugging.
#ifndef lint
static const char rcsid[] =
- "$Id: main.c,v 1.36 2002/01/22 11:12:28 stelian Exp $";
+ "$Id: main.c,v 1.37 2002/01/25 14:59:53 stelian Exp $";
#endif /* not lint */
#include <config.h>
int aflag = 0, bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
int hflag = 1, mflag = 1, Mflag = 0, Nflag = 0, Vflag = 0, zflag = 0;
int uflag = 0, lflag = 0, Lflag = 0;
+char *Afile = NULL;
int dokerberos = 0;
char command = '\0';
long dumpnum = 1;
char filesys[NAMELEN];
static const char *stdin_opt = NULL;
char *bot_script = NULL;
+dump_ino_t volinfo[TP_NINOS];
#ifdef USE_QFA
FILE *gTapeposfp;
;
obsolete(&argc, &argv);
while ((ch = getopt(argc, argv,
- "ab:CcdD:f:F:hi"
+ "aA:b:CcdD:f:F:hi"
#ifdef KERBEROS
"k"
#endif
case 'a':
aflag = 1;
break;
+ case 'A':
+ Afile = optarg;
+ aflag = 1;
+ break;
case 'b':
/* Change default tape blocksize. */
bflag = 1;
#ifdef USE_QFA
if (!mflag && tapeposflag)
errx(1, "m and Q options are mutually exclusive");
+
+ if (tapeposflag && command != 'i' && command != 'x' && command != 't')
+ errx(1, "Q option is not valid for %c command", command);
#endif
+
+ if (Afile && command != 'i' && command != 'x' && command != 't')
+ errx(1, "A option is not valid for %c command", command);
if (signal(SIGINT, onintr) == SIG_IGN)
(void) signal(SIGINT, SIG_IGN);
setup();
extractdirs(0);
initsymtable((char *)0);
+ printvolinfo();
for (;;) {
NEXTFILE(p);
if (!p)
static void
usage(void)
{
-#ifdef __linux__
+ char white[MAXPATHLEN];
const char *ext2ver, *ext2date;
+ memset(white, ' ', MAXPATHLEN);
+ white[MIN(strlen(__progname), MAXPATHLEN - 1)] = '\0';
+
+#ifdef __linux__
ext2fs_get_library_version(&ext2ver, &ext2date);
(void)fprintf(stderr, "%s %s (using libext2fs %s of %s)\n",
__progname, _DUMP_VERSION, ext2ver, ext2date);
#define qfaflag
#endif
- (void)fprintf(stderr,
- "usage:\t%s%s\n\t%s%s\n\t%s%s\n\t%s%s\n\t%s%s\n\t%s%s\n",
- __progname, " -C [-c" kerbflag "lMvVy] [-b blocksize] [-D filesystem] [-f file] [-F script] [-L limit] [-s fileno]",
- __progname, " -i [-ach" kerbflag "lmMuvVy] [-b blocksize] [-f file] [-F script] " qfaflag "[-s fileno]",
- __progname, " -r [-c" kerbflag "lMuvVy] [-b blocksize] [-f file] [-F script] [-s fileno] [-T directory]",
- __progname, " -R [-c" kerbflag "lMuvVy] [-b blocksize] [-f file] [-F script] [-s fileno] [-T directory]",
- __progname, " -t [-ch" kerbflag "lMuvVy] [-b blocksize] [-f file] [-F script] " qfaflag "[-s fileno] [-X filelist] [file ...]",
- __progname, " -x [-ach" kerbflag "lmMuvVy] [-b blocksize] [-f file] [-F script] " qfaflag "[-s fileno] [-X filelist] [file ...]");
+ fprintf(stderr,
+ "usage:"
+ "\t%s -C [-c" kerbflag "lMvVy] [-b blocksize] [-D filesystem] [-f file]\n"
+ "\t%s [-F script] [-L limit] [-s fileno]\n"
+ "\t%s -i [-ach" kerbflag "lmMuvVy] [-A file] [-b blocksize] [-f file]\n"
+ "\t%s [-F script] " qfaflag "[-s fileno]\n"
+ "\t%s -r [-c" kerbflag "lMuvVy] [-b blocksize] [-f file] [-F script]\n"
+ "\t%s [-s fileno] [-T directory]\n"
+ "\t%s -R [-c" kerbflag "lMuvVy] [-b blocksize] [-f file] [-F script]\n"
+ "\t%s [-s fileno] [-T directory]\n"
+ "\t%s -t [-ch" kerbflag "lMuvVy] [-A file] [-b blocksize] [-f file]\n"
+ "\t%s [-F script] " qfaflag "[-s fileno] [-X filelist] [file ...]\n"
+ "\t%s -x [-ach" kerbflag "lmMuvVy] [-A file] [-b blocksize] [-f file]\n"
+ "\t%s [-F script] " qfaflag "[-s fileno] [-X filelist] [file ...]\n",
+ __progname, white,
+ __progname, white,
+ __progname, white,
+ __progname, white,
+ __progname, white,
+ __progname, white);
exit(1);
}
for (flags = 0; *ap; ++ap) {
switch (*ap) {
+ case 'A':
case 'b':
case 'D':
case 'f':
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $Id: restore.8.in,v 1.23 2002/01/22 11:12:28 stelian Exp $
+.\" $Id: restore.8.in,v 1.24 2002/01/25 14:59:53 stelian Exp $
.\"
.Dd __DATE__
.Dt RESTORE 8
.Nm restore
.Fl i
.Op Fl achklmMNuvVy
+.Op Fl A Ar file
.Op Fl b Ar blocksize
.Op Fl f Ar file
.Op Fl F Ar script
.Nm restore
.Fl t
.Op Fl chklMNuvVy
+.Op Fl A Ar file
.Op Fl b Ar blocksize
.Op Fl f Ar file
.Op Fl F Ar script
.Nm restore
.Fl x
.Op Fl achklmMNuvVy
+.Op Fl A Ar file
.Op Fl b Ar blocksize
.Op Fl f Ar file
.Op Fl F Ar script
with 1. This option is useful when the operator does not know on which
volume the files to be extracted are and/or when he prefers the
longer unattended mode rather than the shorter interactive mode.
+.It Fl A Ar archive_file
+Read the table of contents from
+.Ar archive_file
+instead of the media. This option can be used in combination with the
+.Fl t,
+.Fl i,
+or
+.Fl x
+options, making it possible to check whether files are on the media
+without having to mount the media.
.It Fl b Ar blocksize
The number of kilobytes per dump record.
If the
.Nm
reverts back to the real user ID and the real group ID before
running the script.
-.It Fl k
-Use Kerberos authentication when contacting the remote tape server.
-(Only available if this options was enabled when
-.Nm restore
-was compiled.)
-.Pp
.It Fl h
Extract the actual directory,
rather than the files that it references.
This prevents hierarchical restoration of complete subtrees
from the dump.
+.It Fl k
+Use Kerberos authentication when contacting the remote tape server.
+(Only available if this options was enabled when
+.Nm restore
+was compiled.)
.It Fl l
When doing remote restores, assume the remote file is a
regular file (instead of a tape device). If you're restoring
Use the file
.Ar file
in order to read tape position as stored using the dump Quick File
-Access mode.
+Access mode, in one of
+.Fl i,
+.Fl x
+or
+.Fl t
+mode.
.Pp
It is recommended to set up the st driver to return logical tape
positions rather than physical before calling dump/restore with
driver is set to return the same type of tape position used during the
call to dump. Otherwise restore may be confused.
.Pp
-This option can be used when restoring from local tapes (see above)
-or from local files.
+This option can be used when restoring from local or remote tapes
+(see above) or from local or remote files.
.It Fl s Ar fileno
Read from the specified
.Ar fileno
#ifndef lint
static const char rcsid[] =
- "$Id: restore.c,v 1.24 2002/01/22 11:12:28 stelian Exp $";
+ "$Id: restore.c,v 1.25 2002/01/25 14:59:53 stelian Exp $";
#endif /* not lint */
#include <config.h>
long descend = hflag ? GOOD : FAIL;
#ifdef USE_QFA
long tnum;
- long tpos;
+ long long tpos;
#endif
if (TSTINO(ino, dumpmap) == 0)
#ifdef USE_QFA
if (tapeposflag) { /* add QFA positions to output */
(void)Inode2Tapepos(ino, &tnum, &tpos, 1);
- fprintf(stdout, "%10lu\t%ld\t%ld\t%s\n", (unsigned long)ino,
+ fprintf(stdout, "%10lu\t%ld\t%lld\t%s\n", (unsigned long)ino,
tnum, tpos, name);
}
else
register struct entry *ep;
long curvol;
#ifdef USE_QFA
- long tnum, tpos, curtpos, tmpcnt;
+ long tnum, tmpcnt;
+ long long tpos, curtpos;
time_t tistart, tiend, titaken;
#endif
Vprintf(stdout, "Extract requested files\n");
curfile.action = SKIP;
#ifdef USE_QFA
- if (!tapeposflag)
+ if (tapeposflag)
+ curfile.ino = 0;
+ else
#endif
- getvol((long)1);
+ if (volinfo[1] == ROOTINO)
+ curfile.ino = 0;
+ else
+ getvol((long)1);
skipmaps();
skipdirs();
first = lowerbnd(ROOTINO);
* might be too slow */
if (tpos > curtpos) {
#ifdef DEBUG_QFA
- msg("positioning tape %ld from %ld to %ld for inode %10lu ...\n", volno, curtpos, tpos, (unsigned long)next);
+ msg("positioning tape %ld from %lld to %lld for inode %10lu ...\n", volno, curtpos, tpos, (unsigned long)next);
#endif
if (GotoTapePos(tpos) == 0) {
#ifdef DEBUG_QFA
}
}
}
+ else
#endif /* USA_QFA */
+ if (volinfo[1] == ROOTINO) {
+ int i, goodvol = 1;
+
+ for (i = 1; i < TP_NINOS && volinfo[i] != 0; ++i)
+ if (volinfo[i] < next)
+ goodvol = i;
+
+ if (goodvol != volno)
+ RequestVol(goodvol);
+ }
do {
curvol = volno;
* Stelian Pop <stelian@popies.net>, 1999-2000
* Stelian Pop <stelian@popies.net> - Alcôve <www.alcove.com>, 2000-2002
*
- * $Id: restore.h,v 1.23 2002/01/16 10:29:26 stelian Exp $
+ * $Id: restore.h,v 1.24 2002/01/25 14:59:53 stelian Exp $
*/
/*
* Flags
*/
extern int aflag; /* automatic volume increment */
+extern char *Afile; /* archive file */
extern int cvtflag; /* convert from old to new tape format */
extern int bflag; /* set input block size */
extern int dflag; /* print out debugging info */
/*
* Global variables
*/
+extern char *host; /* name of the remote host */
extern char *dumpmap; /* map of inodes on this dump tape */
extern char *usedinomap; /* map of inodes that are in use on this fs */
extern dump_ino_t maxino; /* highest numbered inode in this file system */
/* isn't seen. */
extern int compare_errors; /* did we encounter any compare errors? */
extern char filesys[NAMELEN];/* name of dumped filesystem */
+extern dump_ino_t volinfo[]; /* which inode on which volume archive info */
/*
* Each file in the file system is described by one of these entries
#ifndef lint
static const char rcsid[] =
- "$Id: tape.c,v 1.54 2002/01/22 11:12:28 stelian Exp $";
+ "$Id: tape.c,v 1.55 2002/01/25 14:59:53 stelian Exp $";
#endif /* not lint */
#include <config.h>
static long tapesread;
static sigjmp_buf restart;
static int gettingfile = 0; /* restart has a valid frame */
-static char *host = NULL;
+char *host = NULL;
static int ofile;
static char *map;
#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB)
static void newcomprbuf __P((int));
+static void (*readtape_func) __P((char *));
static void readtape_set __P((char *));
static void readtape_uncompr __P((char *));
static void readtape_comprfile __P((char *));
#ifdef RRESTORE
if (strchr(source, ':')) {
-#ifdef USE_QFA
- if (tapeposflag)
- errx(1, "cannot use -Q option on remote media");
-#endif
host = source;
source = strchr(host, ':');
*source++ = '\0';
{
int i, j, *ip, bot_code;
struct STAT stbuf;
+ char *temptape;
Vprintf(stdout, "Verify tape and initialize maps\n");
- if (bot_script) {
+ if (Afile == NULL && bot_script) {
msg("Launching %s\n", bot_script);
bot_code = system_command(bot_script, magtape, 1);
if (bot_code != 0 && bot_code != 1) {
exit(1);
}
}
+
+ if (Afile)
+ temptape = Afile;
+ else
+ temptape = magtape;
+
#ifdef RRESTORE
if (host)
- mt = rmtopen(magtape, 0);
+ mt = rmtopen(temptape, 0);
else
#endif
if (pipein)
mt = 0;
else
- mt = OPEN(magtape, O_RDONLY, 0);
+ mt = OPEN(temptape, O_RDONLY, 0);
if (mt < 0)
err(1, "%s", magtape);
- volno = 1;
- setmagtapein();
- setdumpnum();
+ if (!Afile) {
+ volno = 1;
+ setmagtapein();
+ setdumpnum();
+ }
+#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB)
+ readtape_func = readtape_set;
+#endif
FLUSHTAPEBUF();
findtapeblksize();
if (gethead(&spcl) == FAIL) {
if (zflag) {
fprintf(stderr, "Dump tape is compressed.\n");
-#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB)
- newcomprbuf(ntrec);
-#else
+#if !defined(HAVE_ZLIB) && !defined(HAVE_BZLIB)
errx(1,"This restore version doesn't support decompression");
-#endif /* HAVE_ZLIB */
+#endif /* !HAVE_ZLIB && !HAVE_BZLIB */
}
if (pipein) {
endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : NFS_MAGIC;
}
gethdr:
setmagtapein();
+#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB)
+ readtape_func = readtape_set;
+#endif
volno = newvol;
setdumpnum();
FLUSHTAPEBUF();
* If coming to this volume at random, skip to the beginning
* of the next record.
*/
+ if (zflag) {
+ fprintf(stderr, "Dump tape is compressed.\n");
+#if !defined(HAVE_ZLIB) && !defined(HAVE_BZLIB)
+ errx(1,"This restore version doesn't support decompression");
+#endif /* !HAVE_ZLIB && !HAVE_BZLIB */
+ }
Dprintf(stdout, "read %ld recs, tape starts with %ld\n",
tpblksread, (long)tmpbuf.c_firstrec);
if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) {
fprintf(stdout, "Label: %s\n", spcl.c_label);
}
+void
+printvolinfo(void)
+{
+ int i;
+
+ if (volinfo[1] == ROOTINO) {
+ printf("Starting inode numbers by volume:\n");
+ for (i = 1; i < TP_NINOS && volinfo[i] != 0; ++i)
+ printf("\tVolume %d: %lu\n", i, (unsigned long)volinfo[i]);
+ }
+}
+
int
extractfile(char *name)
{
int32_t odi_ctime;
} c_dinode;
int32_t c_count;
- char c_addr[256];
+ char c_fill[256];
} s_ospcl;
} u_ospcl;
buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime;
#endif /* __linux__ */
buf->c_count = u_ospcl.s_ospcl.c_count;
- memmove(buf->c_addr, u_ospcl.s_ospcl.c_addr, (long)256);
+ memmove(buf->c_addr, u_ospcl.s_ospcl.c_fill, (long)256);
if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC ||
checksum((int *)(&u_ospcl.s_ospcl)) == FAIL)
return(FAIL);
/* fall through */
case TS_END:
buf->c_inumber = 0;
+ if (buf->c_flags & DR_INODEINFO) {
+ memcpy(volinfo, buf->c_inos, TP_NINOS * sizeof(dump_ino_t));
+ if (Bcvt)
+ swabst((u_char *)"128i", (u_char *)volinfo);
+ }
break;
case TS_INODE:
* get the current position of the tape
*/
int
-GetTapePos(long *pos)
+GetTapePos(long long *pos)
{
int err = 0;
+#ifdef RDUMP
+ if (host) {
+ *pos = (long long) rmtseek(0, SEEK_CUR);
+ err = *pos < 0;
+ }
+ else
+#endif
+ {
if (magtapein) {
+ long mtpos;
*pos = 0;
- err = (ioctl(mt, MTIOCPOS, pos) < 0);
+ err = (ioctl(mt, MTIOCPOS, &mtpos) < 0);
+ *pos = (long long)mtpos;
}
else {
- *pos = lseek(mt, 0, SEEK_CUR);
+ *pos = LSEEK(mt, 0, SEEK_CUR);
err = (*pos < 0);
}
+ }
if (err) {
err = errno;
- fprintf(stdout, "[%ld] error: %d (getting tapepos: %ld)\n",
+ fprintf(stdout, "[%ld] error: %d (getting tapepos: %lld)\n",
(unsigned long)getpid(), err, *pos);
return err;
}
* go to specified position on tape
*/
int
-GotoTapePos(long pos)
+GotoTapePos(long long pos)
{
int err = 0;
+#ifdef RDUMP
+ if (host)
+ err = (rmtseek((long)pos, SEEK_SET) < 0);
+ else
+#endif
+ {
if (magtapein) {
struct mt_pos buf;
buf.mt_op = MTSEEK;
- buf.mt_count = pos;
+ buf.mt_count = (int) pos;
err = (ioctl(mt, MTIOCTOP, &buf) < 0);
}
else {
- pos = lseek(mt, pos, SEEK_SET);
+ pos = LSEEK(mt, pos, SEEK_SET);
err = (pos < 0);
}
+ }
if (err) {
err = errno;
- fprintf(stdout, "[%ld] error: %d (setting tapepos: %ld)\n",
+ fprintf(stdout, "[%ld] error: %d (setting tapepos: %lld)\n",
(unsigned long)getpid(), err, pos);
return err;
}
findinode(&spcl);
noresyncmesg = 0;
}
+#endif /* USE_QFA */
void
RequestVol(long tnum)
FLUSHTAPEBUF();
getvol(tnum);
}
-#endif /* USE_QFA */
#ifndef lint
static const char rcsid[] =
- "$Id: utilities.c,v 1.17 2002/01/16 09:32:14 stelian Exp $";
+ "$Id: utilities.c,v 1.18 2002/01/25 14:59:53 stelian Exp $";
#endif /* not lint */
#include <config.h>
* if no smaller inode found return tnum=0 and tpos=0
*/
int
-Inode2Tapepos(dump_ino_t ino, long *tnum, long *tpos, int exactmatch)
+Inode2Tapepos(dump_ino_t ino, long *tnum, long long *tpos, int exactmatch)
{
char *p, *pp;
char numbuff[32];
unsigned long tmpino;
long tmptnum;
- long tmptpos;
+ long long tmptpos;
*tpos = 0;
*tnum = 0;
/* read tapepos */
while ((*p != 0) && (*p != '\t'))
*pp++ = *p++;
- tmptpos = atol(numbuff);
+ tmptpos = atoll(numbuff);
if (exactmatch) {
if (tmpino == ino) {