From a94ecd1155631b9f88488a19268874c0e3c6601c Mon Sep 17 00:00:00 2001 From: Stelian Pop Date: Tue, 10 Apr 2001 13:42:21 +0000 Subject: [PATCH] Multifile option to dump. --- CHANGES | 6 ++- TODO | 28 +++++------- dump/dump.8.in | 14 +++--- dump/dump.h | 3 +- dump/main.c | 113 +++++++++++++++++++++++++++++++++++++----------- dump/traverse.c | 50 ++++++++++++++++++++- 6 files changed, 162 insertions(+), 52 deletions(-) diff --git a/CHANGES b/CHANGES index 01d6b67..06f3d98 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,4 @@ -$Id: CHANGES,v 1.109 2001/04/10 12:46:53 stelian Exp $ +$Id: CHANGES,v 1.110 2001/04/10 13:42:21 stelian Exp $ Changes between versions 0.4b21 and 0.4b22 (released ????????????????) ====================================================================== @@ -42,6 +42,10 @@ Changes between versions 0.4b21 and 0.4b22 (released ????????????????) large backups, saves the tapes and the drive's head. Use --enable-qfa option of configure to compile in the QFA support. +8. Added the possibility to dump several files and directories + in a single invocation of dump. Thanks to Uwe Gohlke + for implementing this option. + Changes between versions 0.4b20 and 0.4b21 (released January 13, 2001) ====================================================================== diff --git a/TODO b/TODO index f39c442..bddf3c9 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,4 @@ -$Id: TODO,v 1.17 2001/02/16 14:16:54 stelian Exp $ +$Id: TODO,v 1.18 2001/04/10 13:42:21 stelian Exp $ Need to verify: --------------- @@ -13,45 +13,39 @@ Urgent items (for the next stable version): All others: ----------- -1. Make dump able to backup several directories and/or files in one - invocation, like the SunOS version. +1. More documentation? Examples, crontab? -2. More documentation? Examples, crontab? - -3. Explore and correct dump problems on active filesystems +2. Explore and correct dump problems on active filesystems (lseek/read negative count) (This should be OK as of 0.4b14. Unfortunately, this seems to continue for a very few users). -4. Reimplement the ext2 specific code in a "backend" and +3. Reimplement the ext2 specific code in a "backend" and make the dump code more generic. This would allow creation of other backends for other filesystems. Implementing a (v)fat backend should be quite easy, as for BSD ffs (we already have the code for this). The BSD code in traverse.c (all those #ifdef _BSD) should go into the ffs backend. -5. Implement a DEBUG option which doesn't fork on each tape, making +4. Implement a DEBUG option which doesn't fork on each tape, making it able to debug dump with gdb. -6. Add a compression mode using zlib on each file (see - http://www.cdrom.com/pub/infozip/zlib). +5. Extend the compression patch to use bzip2. -7. Make a bootable dump tape? I don't know if it is possible... +6. Make a bootable dump tape? I don't know if it is possible... -8. From Kjetil Torgrim Homme : +7. 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. -9. Modify (or get rid of) rmt in order to work with non Linux +8. Modify (or get rid of) rmt in order to work with non Linux systems (limited succes has been reported). A good version of rmt to be looked at is part of star http://www.fokus.gmd.de/research/cc/glone/employees/joerg.schilling/private/star.html -10. Rework the makefiles, actually --prefix doesn't work in - configure. Maybe use automake in the same step ? - -11. EA/ACL support in dump (requested by Michael Ju. Tokarev +9. EA/ACL support in dump (requested by Michael Ju. Tokarev . +10. Better readline completition in restore (escape spaces etc). diff --git a/dump/dump.8.in b/dump/dump.8.in index e162046..5d16fc7 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.25 2001/04/10 12:46:53 stelian Exp $ +.\" $Id: dump.8.in,v 1.26 2001/04/10 13:42:22 stelian Exp $ .\" .Dd __DATE__ .Dt DUMP 8 @@ -53,7 +53,7 @@ .Op Fl s Ar feet .Op Fl T Ar date .Op Fl z Ar compression level -.Ar file-to-dump +.Ar files-to-dump .Nm dump .Op Fl W Li \&| Fl w .Pp @@ -84,15 +84,17 @@ tape size, density and/or block count options below. By default, the same output file name is used for each volume after prompting the operator to change media. .Pp -.Ar file-to-dump +.Ar files-to-dump is either a mountpoint of a filesystem -or a directory to be backed up as a subset of a filesystem. +or a list of files and directories to be backed up as a subset of a +filesystem. In the former case, either the path to a mounted filesystem or the device of an unmounted filesystem can be used. In the latter case, certain restrictions are placed on the backup: .Fl u -is not allowed and the only dump level that is supported is -.Fl 0 . +is not allowed, the only dump level that is supported is +.Fl 0 +and all the files and directories must reside on the same filesystem. .Pp The following options are supported by .Nm Ns : diff --git a/dump/dump.h b/dump/dump.h index 8235858..b43beb7 100644 --- a/dump/dump.h +++ b/dump/dump.h @@ -5,7 +5,7 @@ * Stelian Pop , 1999-2000 * Stelian Pop - AlcĂ´ve , 2000 * - * $Id: dump.h,v 1.23 2001/04/10 12:46:53 stelian Exp $ + * $Id: dump.h,v 1.24 2001/04/10 13:42:22 stelian Exp $ */ /*- @@ -141,6 +141,7 @@ long blockest __P((struct dinode const *dp)); int mapfiles __P((dump_ino_t maxino, long *tapesize)); #ifdef __linux__ int mapfilesfromdir __P((dump_ino_t maxino, long *tapesize, char *directory)); +int maponefile __P((dump_ino_t maxino, long *tapesize, char *directory)); #endif int mapdirs __P((dump_ino_t maxino, long *tapesize)); diff --git a/dump/main.c b/dump/main.c index 272d597..3f114c9 100644 --- a/dump/main.c +++ b/dump/main.c @@ -41,7 +41,7 @@ #ifndef lint static const char rcsid[] = - "$Id: main.c,v 1.42 2001/04/10 12:46:53 stelian Exp $"; + "$Id: main.c,v 1.43 2001/04/10 13:42:22 stelian Exp $"; #endif /* not lint */ #include @@ -124,6 +124,8 @@ main(int argc, char *argv[]) register int ch; int i, anydirskipped, bflag = 0, Tflag = 0, honorlevel = 1; dump_ino_t maxino; + struct stat statbuf; + dev_t filedev; #ifdef __linux__ errcode_t retval; char directory[MAXPATHLEN]; @@ -197,6 +199,7 @@ main(int argc, char *argv[]) if (ntrec > maxbsize/1024) { msg("Please choose a blocksize <= %dkB\n", maxbsize/1024); + msg("The ENTIRE dump is aborted.\n"); exit(X_STARTUP); } bflag = 1; @@ -217,12 +220,14 @@ main(int argc, char *argv[]) /* 04-Feb-00 ILC */ case 'e': /* exclude an inode */ if (iexclude_num == IEXCLUDE_MAXNUM) { - (void)fprintf(stderr, "Too many -e options\n"); + msg("Too many -e options\n"); + msg("The ENTIRE dump is aborted.\n"); exit(X_STARTUP); } iexclude_list[iexclude_num++] = numarg("inode to exclude",0L,0L); if (iexclude_list[iexclude_num-1] <= ROOTINO) { - (void)fprintf(stderr, "Cannot exclude inode %ld\n", (long)iexclude_list[iexclude_num-1]); + msg("Cannot exclude inode %ld\n", (long)iexclude_list[iexclude_num-1]); + msg("The ENTIRE dump is aborted.\n"); exit(X_STARTUP); } msg("Added %d to exclude list\n", @@ -291,8 +296,8 @@ main(int argc, char *argv[]) case 'T': /* time of last dump */ spcl.c_ddate = unctime(optarg); if (spcl.c_ddate < 0) { - (void)fprintf(stderr, "bad time \"%s\"\n", - optarg); + msg("bad time \"%s\"\n", optarg); + msg("The ENTIRE dump is aborted.\n"); exit(X_STARTUP); } Tflag = 1; @@ -322,26 +327,20 @@ main(int argc, char *argv[]) argv += optind; if (argc < 1) { - (void)fprintf(stderr, "Must specify disk or filesystem\n"); + msg("Must specify disk or filesystem\n"); + msg("The ENTIRE dump is aborted.\n"); exit(X_STARTUP); } diskparam = *argv++; if (strlen(diskparam) >= MAXPATHLEN) { - (void)fprintf(stderr, "Disk or filesystem name too long: %s\n", - diskparam); + msg("Disk or filesystem name too long: %s\n", diskparam); + msg("The ENTIRE dump is aborted.\n"); exit(X_STARTUP); } argc--; - if (argc >= 1) { - (void)fprintf(stderr, "Unknown arguments to dump:"); - while (argc--) - (void)fprintf(stderr, " %s", *argv++); - (void)fprintf(stderr, "\n"); - exit(X_STARTUP); - } if (Tflag && uflag) { - (void)fprintf(stderr, - "You cannot use the T and u flags together.\n"); + msg("You cannot use the T and u flags together.\n"); + msg("The ENTIRE dump is aborted.\n"); exit(X_STARTUP); } if (strcmp(tapeprefix, "-") == 0) { @@ -374,13 +373,15 @@ main(int argc, char *argv[]) *tapeprefix++ = '\0'; #ifdef RDUMP if (index(tapeprefix, '\n')) { - (void)fprintf(stderr, "invalid characters in tape\n"); - exit(X_STARTUP); + msg("invalid characters in tape\n"); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); } if (rmthost(host) == 0) exit(X_STARTUP); #else - (void)fprintf(stderr, "remote dump not enabled\n"); + msg("remote dump not enabled\n"); + msg("The ENTIRE dump is aborted.\n"); exit(X_STARTUP); #endif } @@ -416,6 +417,7 @@ main(int argc, char *argv[]) of LABEL= or UID= but it was not found */ msg("Cannot find a disk having %s\n", diskparam); + msg("The ENTIRE dump is aborted.\n"); exit(X_STARTUP); } /* @@ -425,6 +427,16 @@ main(int argc, char *argv[]) * the file system name with or without the leading '/'. */ if ((dt = fstabsearch(disk)) != NULL) { + /* if found then only one parameter (i.e. partition) + * is allowed */ + if (argc >= 1) { + (void)fprintf(stderr, "Unknown arguments to dump:"); + while (argc--) + (void)fprintf(stderr, " %s", *argv++); + (void)fprintf(stderr, "\n"); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } disk = rawname(dt->fs_spec); (void)strncpy(spcl.c_dev, dt->fs_spec, NAMELEN); (void)strncpy(spcl.c_filesys, dt->fs_file, NAMELEN); @@ -470,11 +482,13 @@ main(int argc, char *argv[]) if (directory[0] != 0) { if (level != '0') { - (void)fprintf(stderr, "Only level 0 dumps are allowed on a subdirectory\n"); + msg("Only level 0 dumps are allowed on a subdirectory\n"); + msg("The ENTIRE dump is aborted.\n"); exit(X_STARTUP); } if (uflag) { - (void)fprintf(stderr, "You can't update the dumpdates file when dumping a subdirectory\n"); + msg("You can't update the dumpdates file when dumping a subdirectory\n"); + msg("The ENTIRE dump is aborted.\n"); exit(X_STARTUP); } } @@ -519,16 +533,19 @@ main(int argc, char *argv[]) if (retval) { com_err(disk, retval, "while opening filesystem"); if (retval == EXT2_ET_REV_TOO_HIGH) - printf ("Get a newer version of dump!\n"); + msg("Get a newer version of dump!\n"); + msg("The ENTIRE dump is aborted.\n"); exit(X_STARTUP); } if (fs->super->s_rev_level > DUMP_CURRENT_REV) { com_err(disk, retval, "while opening filesystem"); - printf ("Get a newer version of dump!\n"); + msg("Get a newer version of dump!\n"); + msg("The ENTIRE dump is aborted.\n"); exit(X_STARTUP); } if ((diskfd = open(disk, O_RDONLY)) < 0) { msg("Cannot open %s\n", disk); + msg("The ENTIRE dump is aborted.\n"); exit(X_STARTUP); } /* if no user label specified, use ext2 filesystem label if available */ @@ -556,6 +573,7 @@ main(int argc, char *argv[]) #else /* __linux __*/ if ((diskfd = open(disk, O_RDONLY)) < 0) { msg("Cannot open %s\n", disk); + msg("The ENTIRE dump is aborted.\n"); exit(X_STARTUP); } sync(); @@ -600,8 +618,51 @@ main(int argc, char *argv[]) #ifdef __linux__ if (directory[0] == 0) anydirskipped = mapfiles(maxino, &tapesize); - else - anydirskipped = mapfilesfromdir(maxino, &tapesize, directory); + else { + if (stat(pathname, &statbuf) == -1) { + msg("File cannot be accessed (%s).\n", pathname); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + filedev = statbuf.st_dev; + if (!(statbuf.st_mode & S_IFDIR)) /* is a file */ + anydirskipped = maponefile(maxino, &tapesize, + directory); + else + anydirskipped = mapfilesfromdir(maxino, &tapesize, + directory); + } + while (argc--) { + int anydirskipped2; + char *p = *argv; + /* check if file is available */ + if (stat(p, &statbuf) == -1) { + msg("File cannot be accessed (%s).\n", p); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + /* check if file is on same unix partiton as the first + * argument */ + if (statbuf.st_dev != filedev) { + msg("Files are not on same file system (%s).\n", p); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + /* check if file is a directory */ + if (!(statbuf.st_mode & S_IFDIR)) + anydirskipped2 = maponefile(maxino, &tapesize, + p+strlen(dt->fs_file)); + else + /* read directory inodes. + * NOTE: nested directories are not recognized + * so inodes may be umped twice! + */ + anydirskipped2 = mapfilesfromdir(maxino, &tapesize, + p+strlen(dt->fs_file)); + if (!anydirskipped) + anydirskipped = anydirskipped2; + argv++; + } #else anydirskipped = mapfiles(maxino, &tapesize); #endif diff --git a/dump/traverse.c b/dump/traverse.c index c4e1e9a..0ea5b96 100644 --- a/dump/traverse.c +++ b/dump/traverse.c @@ -41,7 +41,7 @@ #ifndef lint static const char rcsid[] = - "$Id: traverse.c,v 1.31 2001/03/28 12:59:48 stelian Exp $"; + "$Id: traverse.c,v 1.32 2001/04/10 13:42:22 stelian Exp $"; #endif /* not lint */ #include @@ -369,6 +369,54 @@ mapfiles(dump_ino_t maxino, long *tapesize) } #endif /* __linux__ */ +#ifdef __linux__ +int +maponefile(dump_ino_t maxino, long *tapesize, char *directory) +{ + errcode_t retval; + ext2_ino_t dir_ino; + char dir_name [MAXPATHLEN]; + int i, anydirskipped = 0; + + /* + * Mark every directory in the path as being dumped + */ + for (i = 0; i < strlen (directory); i++) { + if (directory[i] == '/') { + strncpy (dir_name, directory, i); + dir_name[i] = '\0'; + retval = ext2fs_namei(fs, ROOTINO, ROOTINO, + dir_name, &dir_ino); + if (retval) { + com_err(disk, retval, + "while translating %s", dir_name); + exit(X_ABORT); + } + mapfileino((dump_ino_t) dir_ino, 0, + tapesize, &anydirskipped); + } + } + /* + * Mark the final directory + */ + retval = ext2fs_namei(fs, ROOTINO, ROOTINO, directory, &dir_ino); + if (retval) { + com_err(disk, retval, "while translating %s", directory); + exit(X_ABORT); + } + mapfileino((dump_ino_t)dir_ino, 0, tapesize, &anydirskipped); + + mapfileino(ROOTINO, 0, tapesize, &anydirskipped); + + /* + * Restore gets very upset if the root is not dumped, + * so ensure that it always is dumped. + */ + SETINO(ROOTINO, dumpdirmap); + return anydirskipped; +} +#endif /* __linux__ */ + #ifdef __linux__ struct mapfile_context { long *tapesize; -- 2.39.2