From e51470bfc05d83f82c37d24504220c7163bbd4c1 Mon Sep 17 00:00:00 2001 From: Stelian Pop Date: Fri, 25 Jan 2002 14:59:53 +0000 Subject: [PATCH] -A archive file implementation -Q on remote tape/files. --- CHANGES | 18 +++-- THANKS | 3 +- TODO | 17 +--- compat/include/protocols/dumprestore.h | 15 +++- dump/dump.8.in | 50 +++++++----- dump/dump.h | 6 +- dump/main.c | 49 ++++++++---- dump/tape.c | 61 +++++++++++--- dump/traverse.c | 32 +++++--- restore/extern.h | 11 +-- restore/interactive.c | 3 +- restore/main.c | 52 +++++++++--- restore/restore.8.in | 37 ++++++--- restore/restore.c | 31 ++++++-- restore/restore.h | 5 +- restore/tape.c | 105 ++++++++++++++++++------- restore/utilities.c | 8 +- 17 files changed, 356 insertions(+), 147 deletions(-) diff --git a/CHANGES b/CHANGES index 55a910a..87d4ba7 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,4 @@ -$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 ???????????????) ===================================================================== @@ -16,10 +16,18 @@ 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 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) ===================================================================== diff --git a/THANKS b/THANKS index 6f75519..385510d 100644 --- a/THANKS +++ b/THANKS @@ -1,4 +1,4 @@ -$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. @@ -43,6 +43,7 @@ Uwe Gohlke uwe@ugsoft.de 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 diff --git a/TODO b/TODO index a928652..d3d4102 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,4 @@ -$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: --------------- @@ -31,18 +31,7 @@ All others: 5. Make a bootable dump tape? I don't know if it is possible... -6. From Kjetil Torgrim Homme : - 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 . -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). diff --git a/compat/include/protocols/dumprestore.h b/compat/include/protocols/dumprestore.h index a9f68e0..2c3a945 100644 --- a/compat/include/protocols/dumprestore.h +++ b/compat/include/protocols/dumprestore.h @@ -5,7 +5,7 @@ * Stelian Pop , 1999-2000 * Stelian Pop - Alcôve , 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 $ */ /* @@ -67,6 +67,7 @@ #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 @@ -76,6 +77,11 @@ 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 { @@ -93,7 +99,7 @@ union u_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 */ @@ -106,6 +112,9 @@ union u_spcl { } 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 */ @@ -122,6 +131,8 @@ union u_spcl { #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. diff --git a/dump/dump.8.in b/dump/dump.8.in index 22ed340..86548f9 100644 --- a/dump/dump.8.in +++ b/dump/dump.8.in @@ -30,7 +30,7 @@ .\" 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 @@ -41,6 +41,7 @@ .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 @@ -117,11 +118,6 @@ to 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 @@ -130,6 +126,13 @@ for most modern tape drives, and is the default. 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 @@ -140,10 +143,20 @@ Therefore .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 @@ -159,21 +172,6 @@ The file .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 ; @@ -222,6 +220,16 @@ For security reasons, .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 diff --git a/dump/dump.h b/dump/dump.h index e2c008f..2ce50e3 100644 --- a/dump/dump.h +++ b/dump/dump.h @@ -5,7 +5,7 @@ * Stelian Pop , 1999-2000 * Stelian Pop - Alcôve , 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 $ */ /*- @@ -67,12 +67,14 @@ extern char *dumpinomap; /* map of files to be dumped */ /* * 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 */ @@ -110,6 +112,7 @@ extern long xferrate; /* averaged transfer rate of all volumes */ 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" @@ -158,6 +161,7 @@ void dumpdirino __P((struct dinode *dp, dump_ino_t ino)); #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)); diff --git a/dump/main.c b/dump/main.c index a64ad67..ac6a7a1 100644 --- a/dump/main.c +++ b/dump/main.c @@ -41,7 +41,7 @@ #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 @@ -55,6 +55,7 @@ static const char rcsid[] = #include #include #include +#include #include #include @@ -104,6 +105,7 @@ char *dumpdates; /* name of the file containing dump date information*/ 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 */ @@ -140,6 +142,7 @@ long xferrate; /* averaged transfer rate of all volumes */ 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; @@ -207,6 +210,7 @@ main(int argc, char *argv[]) #endif time_t tnow; char *diskparam; + char *Apath; spcl.c_label[0] = '\0'; spcl.c_date = time(NULL); @@ -237,7 +241,7 @@ main(int argc, char *argv[]) #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 @@ -261,6 +265,18 @@ main(int argc, char *argv[]) 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; @@ -470,13 +486,6 @@ main(int argc, char *argv[]) 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"); @@ -929,6 +938,13 @@ main(int argc, char *argv[]) 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. @@ -969,6 +985,9 @@ main(int argc, char *argv[]) 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); @@ -998,22 +1017,23 @@ usage(void) "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); } @@ -1110,6 +1130,7 @@ obsolete(int *argcp, char **argvp[]) for (flags = 0; *ap; ++ap) { switch (*ap) { + case 'A': case 'B': case 'b': case 'd': diff --git a/dump/tape.c b/dump/tape.c index df86763..66fc821 100644 --- a/dump/tape.c +++ b/dump/tape.c @@ -41,7 +41,7 @@ #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 @@ -80,6 +80,7 @@ int write(), read(); #include #endif #include +#include #include #elif defined sunos #include @@ -110,7 +111,6 @@ extern long blocksperfile; /* number of blocks per output file */ 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; @@ -125,8 +125,8 @@ static void flushtape __P((void)); 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 /* @@ -234,6 +234,30 @@ writerec(const void *dp, int isspcl) 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; @@ -892,6 +916,8 @@ restore_check_point: if (tapeno > 1) msg("Volume %d begins with blocks from inode %d\n", tapeno, slp->inode); + if (tapeno < TP_NINOS) + volinfo[tapeno] = slp->inode; } } @@ -1052,7 +1078,7 @@ doslave(int cmd, int slave_number, int first) errcode_t retval; #endif #ifdef USE_QFA - long curtapepos; + long long curtapepos; union u_spcl *uspclptr; struct s_spcl *spclptr; #endif /* USE_QFA */ @@ -1320,21 +1346,32 @@ atomic_write(int fd, const void *buf, size_t count) * 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; } @@ -1342,13 +1379,13 @@ GetTapePos(long *pos) } 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); diff --git a/dump/traverse.c b/dump/traverse.c index 06eeb73..80d7e86 100644 --- a/dump/traverse.c +++ b/dump/traverse.c @@ -41,7 +41,7 @@ #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 @@ -1176,21 +1176,20 @@ dumpmap(char *map, int type, dump_ino_t ino) 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) { @@ -1199,7 +1198,18 @@ writeheader(dump_ino_t ino) 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); } diff --git a/restore/extern.h b/restore/extern.h index babafea..7cc9804 100644 --- a/restore/extern.h +++ b/restore/extern.h @@ -5,7 +5,7 @@ * Stelian Pop , 1999-2000 * Stelian Pop - Alcôve , 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 $ */ /*- @@ -90,6 +90,7 @@ void panic __P((const char *, ...)); 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)); @@ -127,9 +128,9 @@ int fgetflags __P((const char *, unsigned long *)); 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)); diff --git a/restore/interactive.c b/restore/interactive.c index 10cc5bf..fb29a4f 100644 --- a/restore/interactive.c +++ b/restore/interactive.c @@ -41,7 +41,7 @@ #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 @@ -316,6 +316,7 @@ loop: if (strncmp(cmd, "what", strlen(cmd)) != 0) goto bad; printdumpinfo(); + printvolinfo(); break; /* * Turn on debugging. diff --git a/restore/main.c b/restore/main.c index ab058ab..fb51380 100644 --- a/restore/main.c +++ b/restore/main.c @@ -41,7 +41,7 @@ #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 @@ -83,6 +83,7 @@ static const char rcsid[] = 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; @@ -100,6 +101,7 @@ int compare_errors; char filesys[NAMELEN]; static const char *stdin_opt = NULL; char *bot_script = NULL; +dump_ino_t volinfo[TP_NINOS]; #ifdef USE_QFA FILE *gTapeposfp; @@ -154,7 +156,7 @@ main(int argc, char *argv[]) ; obsolete(&argc, &argv); while ((ch = getopt(argc, argv, - "ab:CcdD:f:F:hi" + "aA:b:CcdD:f:F:hi" #ifdef KERBEROS "k" #endif @@ -167,6 +169,10 @@ main(int argc, char *argv[]) case 'a': aflag = 1; break; + case 'A': + Afile = optarg; + aflag = 1; + break; case 'b': /* Change default tape blocksize. */ bflag = 1; @@ -284,7 +290,13 @@ main(int argc, char *argv[]) #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); @@ -469,6 +481,7 @@ main(int argc, char *argv[]) setup(); extractdirs(0); initsymtable((char *)0); + printvolinfo(); for (;;) { NEXTFILE(p); if (!p) @@ -523,9 +536,13 @@ main(int argc, char *argv[]) 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); @@ -545,14 +562,26 @@ usage(void) #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); } @@ -586,6 +615,7 @@ obsolete(int *argcp, char **argvp[]) for (flags = 0; *ap; ++ap) { switch (*ap) { + case 'A': case 'b': case 'D': case 'f': diff --git a/restore/restore.8.in b/restore/restore.8.in index 90fb1e3..54f289e 100644 --- a/restore/restore.8.in +++ b/restore/restore.8.in @@ -29,7 +29,7 @@ .\" 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 @@ -51,6 +51,7 @@ .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 @@ -76,6 +77,7 @@ .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 @@ -87,6 +89,7 @@ .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 @@ -316,6 +319,16 @@ option disables this behaviour and reads all the volumes starting 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 @@ -376,17 +389,16 @@ For security reasons, .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 @@ -437,7 +449,12 @@ command without actually writing any file on disk. 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 @@ -451,8 +468,8 @@ Before calling restore with parameter Q, always make sure the st 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 diff --git a/restore/restore.c b/restore/restore.c index 3cc2bad..a44f50d 100644 --- a/restore/restore.c +++ b/restore/restore.c @@ -41,7 +41,7 @@ #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 @@ -83,7 +83,7 @@ listfile(char *name, dump_ino_t ino, int type) long descend = hflag ? GOOD : FAIL; #ifdef USE_QFA long tnum; - long tpos; + long long tpos; #endif if (TSTINO(ino, dumpmap) == 0) @@ -92,7 +92,7 @@ listfile(char *name, dump_ino_t ino, int type) #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 @@ -839,16 +839,22 @@ createfiles(void) 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); @@ -911,7 +917,7 @@ createfiles(void) * 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 @@ -928,7 +934,18 @@ createfiles(void) } } } + 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; diff --git a/restore/restore.h b/restore/restore.h index ba6af08..a9dba7b 100644 --- a/restore/restore.h +++ b/restore/restore.h @@ -5,7 +5,7 @@ * Stelian Pop , 1999-2000 * Stelian Pop - Alcôve , 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 $ */ /* @@ -52,6 +52,7 @@ * 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 */ @@ -70,6 +71,7 @@ extern char* bot_script; /* beginning of tape script */ /* * 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 */ @@ -90,6 +92,7 @@ extern int compare_ignore_not_found; /* 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 diff --git a/restore/tape.c b/restore/tape.c index cf02471..ff524ce 100644 --- a/restore/tape.c +++ b/restore/tape.c @@ -46,7 +46,7 @@ #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 @@ -116,7 +116,7 @@ static long tpblksread = 0; /* TP_BSIZE blocks read */ 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; @@ -154,6 +154,7 @@ static void setmagtapein __P((void)); #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 *)); @@ -190,10 +191,6 @@ setinput(char *source) #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'; @@ -268,9 +265,10 @@ setup(void) { 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) { @@ -278,20 +276,31 @@ setup(void) 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) { @@ -306,11 +315,9 @@ setup(void) 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; @@ -505,6 +512,9 @@ again: } gethdr: setmagtapein(); +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) + readtape_func = readtape_set; +#endif volno = newvol; setdumpnum(); FLUSHTAPEBUF(); @@ -546,6 +556,12 @@ gethdr: * 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)) { @@ -642,6 +658,18 @@ printdumpinfo(void) 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) { @@ -1986,7 +2014,7 @@ gethead(struct s_spcl *buf) int32_t odi_ctime; } c_dinode; int32_t c_count; - char c_addr[256]; + char c_fill[256]; } s_ospcl; } u_ospcl; @@ -2032,7 +2060,7 @@ gethead(struct s_spcl *buf) 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); @@ -2078,6 +2106,11 @@ good: /* 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: @@ -2385,21 +2418,32 @@ swabl(u_long x) * 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; } @@ -2415,23 +2459,30 @@ typedef struct mt_pos { * 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; } @@ -2454,6 +2505,7 @@ ReReadFromTape(void) findinode(&spcl); noresyncmesg = 0; } +#endif /* USE_QFA */ void RequestVol(long tnum) @@ -2461,4 +2513,3 @@ RequestVol(long tnum) FLUSHTAPEBUF(); getvol(tnum); } -#endif /* USE_QFA */ diff --git a/restore/utilities.c b/restore/utilities.c index c94d36f..4960b9a 100644 --- a/restore/utilities.c +++ b/restore/utilities.c @@ -41,7 +41,7 @@ #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 @@ -485,13 +485,13 @@ panic(fmt, va_alist) * 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; @@ -523,7 +523,7 @@ Inode2Tapepos(dump_ino_t ino, long *tnum, long *tpos, int exactmatch) /* read tapepos */ while ((*p != 0) && (*p != '\t')) *pp++ = *p++; - tmptpos = atol(numbuff); + tmptpos = atoll(numbuff); if (exactmatch) { if (tmpino == ino) { -- 2.39.5