X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=dump%2Fmain.c;h=573414989c94d395353f7254ae017cb9151b805b;hb=dbb649e870428cffea2583ed34233d0239b80992;hp=2ee429a6c660ef2805d37b585ec4257229d6f728;hpb=6d732772201861bc57348f4ad5c0970ac00b5d93;p=dump.git diff --git a/dump/main.c b/dump/main.c index 2ee429a..5734149 100644 --- a/dump/main.c +++ b/dump/main.c @@ -2,8 +2,8 @@ * Ported to Linux's Second Extended File System as part of the * dump and restore backup suit * Remy Card , 1994-1997 - * Stelian Pop , 1999-2000 - * Stelian Pop - Alcôve , 2000 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 */ /*- @@ -41,7 +41,7 @@ #ifndef lint static const char rcsid[] = - "$Id: main.c,v 1.53 2001/07/19 09:03:44 stelian Exp $"; + "$Id: main.c,v 1.80 2003/01/10 10:52:48 stelian Exp $"; #endif /* not lint */ #include @@ -49,12 +49,13 @@ static const char rcsid[] = #include #include #include -#include #include #include #include #include #include +#include +#include #include #include @@ -88,11 +89,81 @@ static const char rcsid[] = #define SBOFF (SBLOCK * DEV_BSIZE) #endif +/* + * Dump maps used to describe what is to be dumped. + */ +int mapsize; /* size of the state maps */ +char *usedinomap; /* map of allocated inodes */ +char *dumpdirmap; /* map of directories to be dumped */ +char *dumpinomap; /* map of files to be dumped */ +char *metainomap; /* which of the inodes in dumpinomap will get + only their metadata dumped */ + +const char *disk; /* name of the disk file */ +char tape[MAXPATHLEN];/* name of the tape file */ +char *tapeprefix; /* prefix of the tape file */ +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; /* dump metadata only if possible */ +int Mflag; /* multi-volume flag */ +int qflag; /* quit on errors flag */ +int vflag; /* verbose flag */ +int breademax = 32; /* maximum number of bread errors before we quit */ +char *eot_script; /* end of volume script fiag */ +int diskfd; /* disk file descriptor */ +int tapefd; /* tape file descriptor */ +int pipeout; /* true => output to standard output */ +int fifoout; /* true => output to fifo */ +dump_ino_t curino; /* current inumber; used globally */ +int newtape; /* new tape flag */ +int density; /* density in 0.1" units */ +long tapesize; /* estimated tape size, blocks */ +long tsize; /* tape size in 0.1" units */ +long asize; /* number of 0.1" units written on current tape */ +int etapes; /* estimated number of tapes */ +int nonodump; /* if set, do not honor UF_NODUMP user flags */ +int unlimited; /* if set, write to end of medium */ +int compressed; /* if set, dump is to be compressed */ +long long bytes_written;/* total bytes written to tape */ +long uncomprblks; /* uncompressed blocks written to tape */ +int notify; /* notify operator flag */ +int blockswritten; /* number of blocks written on current tape */ +int tapeno; /* current tape number */ +time_t tstart_writing; /* when started writing the first tape block */ +time_t tend_writing; /* after writing the last tape block */ +#ifdef __linux__ +ext2_filsys fs; +#else +struct fs *sblock; /* the file system super block */ +char sblock_buf[MAXBSIZE]; +#endif +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; +char *gTapeposfile; +char gTps[255]; +int32_t gThisDumpDate; +#endif /* USE_QFA */ + +struct dumptime *dthead; /* head of the list version */ +int nddates; /* number of records (might be zero) */ +int ddates_in; /* we have read the increment file */ +struct dumpdates **ddatev; /* the arrayfied version */ + int notify = 0; /* notify operator flag */ int blockswritten = 0; /* number of blocks written on current tape */ int tapeno = 0; /* current tape number */ int density = 0; /* density in bytes/0.1" " <- this is for hilit19 */ -int ntrec = NTREC; /* # tape blocks in each tape record */ +int ntrec = NTREC; /* # blocks in each tape record */ int cartridge = 0; /* Assume non-cartridge tape */ #ifdef USE_QFA int tapepos = 0; /* assume no QFA tapeposition needed by user */ @@ -110,12 +181,13 @@ long uncomprblks = 0;/* uncompressed blocks written */ char *__progname; #endif -int maxbsize = 64*1024; /* XXX MAXBSIZE from sys/param.h */ +int maxbsize = 1024*1024; /* XXX MAXBSIZE from sys/param.h */ static long numarg __P((const char *, long, long)); static void obsolete __P((int *, char **[])); static void usage __P((void)); static void do_exclude_from_file __P((char *)); static void do_exclude_ino_str __P((char *)); +static void incompat_flags __P((int, char, char)); static dump_ino_t iexclude_list[IEXCLUDE_MAXNUM];/* the inode exclude list */ static int iexclude_num = 0; /* number of elements in the list */ @@ -123,13 +195,14 @@ static int iexclude_num = 0; /* number of elements in the list */ int main(int argc, char *argv[]) { - register dump_ino_t ino; - register int dirty; - register struct dinode *dp; - register struct fstab *dt; - register char *map; - register int ch; - int i, anydirskipped, bflag = 0, Tflag = 0, honorlevel = 1; + dump_ino_t ino; + int dirty; + struct dinode *dp; + struct mntent *dt; + char *map; + int ch; + int i, anydirskipped; + int aflag = 0, bflag = 0, Tflag = 0, honorlevel = 1; dump_ino_t maxino; struct STAT statbuf; dev_t filedev = 0; @@ -140,6 +213,7 @@ main(int argc, char *argv[]) #endif time_t tnow; char *diskparam; + char *Apath = NULL; spcl.c_label[0] = '\0'; spcl.c_date = time(NULL); @@ -170,15 +244,19 @@ main(int argc, char *argv[]) #endif /* USE_QFA */ while ((ch = getopt(argc, argv, - "0123456789aB:b:cd:e:E:f:F:h:L:" + "0123456789A:aB:b:cd:e:E:f:F:h:I:" +#ifdef HAVE_BZLIB + "j::" +#endif + "L:" #ifdef KERBEROS "k" #endif - "Mn" + "mMnq" #ifdef USE_QFA "Q:" #endif - "s:ST:uWw" + "s:ST:uvWw" #ifdef HAVE_ZLIB "z::" #endif @@ -190,8 +268,21 @@ 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; break; case 'B': /* blocks per output file */ @@ -202,7 +293,7 @@ main(int argc, char *argv[]) case 'b': /* blocks per tape write */ ntrec = numarg("number of blocks per write", - 1L, 1000L); + 1L, 1048576L); if (ntrec > maxbsize/1024) { msg("Please choose a blocksize <= %dkB\n", maxbsize/1024); @@ -253,6 +344,20 @@ main(int argc, char *argv[]) honorlevel = numarg("honor level", 0L, 10L); break; +#ifdef HAVE_BZLIB + case 'j': + compressed = 2; + bzipflag = 1; + if (optarg) + compressed = numarg("compress level", 1L, 9L); + break; +#endif /* HAVE_BZLIB */ + + case 'I': + breademax = + numarg ("number of errors to ignore", 0L, 0L); + break; + #ifdef KERBEROS case 'k': dokerberos = 1; @@ -276,6 +381,10 @@ main(int argc, char *argv[]) } break; + case 'm': /* metadata only flag */ + mflag = 1; + break; + case 'M': /* multi-volume flag */ Mflag = 1; break; @@ -284,6 +393,10 @@ main(int argc, char *argv[]) notify = 1; break; + case 'q': + qflag = 1; + break; + #ifdef USE_QFA case 'Q': /* create tapeposfile */ gTapeposfile = optarg; @@ -315,6 +428,10 @@ main(int argc, char *argv[]) uflag = 1; break; + case 'v': /* verbose */ + vflag = 1; + break; + case 'W': /* what to do */ case 'w': lastdump(ch); @@ -345,11 +462,12 @@ main(int argc, char *argv[]) exit(X_STARTUP); } argc--; - if (Tflag && uflag) { - msg("You cannot use the T and u flags together.\n"); - msg("The ENTIRE dump is aborted.\n"); - exit(X_STARTUP); - } + incompat_flags(Tflag && uflag, 'T', 'u'); + incompat_flags(aflag && blocksperfile, 'a', 'B'); + incompat_flags(aflag && cartridge, 'a', 'c'); + incompat_flags(aflag && density, 'a', 'd'); + incompat_flags(aflag && tsize, 'a', 's'); + if (strcmp(tapeprefix, "-") == 0) { pipeout++; tapeprefix = "standard output"; @@ -408,6 +526,13 @@ main(int argc, char *argv[]) signal(SIGTERM, sig); if (signal(SIGINT, interrupt) == SIG_IGN) signal(SIGINT, SIG_IGN); +#ifdef SIGXCPU + signal(SIGXCPU, SIG_IGN); +#endif /* SIGXCPU */ +#ifdef SIGXFSZ + signal(SIGXFSZ, SIG_IGN); +#endif /* SIGXFSZ */ + set_operators(); /* /etc/group snarfed */ getfstab(); /* /etc/fstab snarfed */ @@ -417,7 +542,8 @@ main(int argc, char *argv[]) */ i = strlen(diskparam) - 1; if (i > 1 && diskparam[i] == '/') - diskparam[i] = '\0'; + if (!(i == 6 && !strcmp(diskparam, "LABEL=/"))) + diskparam[i] = '\0'; disk = get_device_name(diskparam); if (!disk) { /* null means the disk is some form @@ -444,9 +570,9 @@ main(int argc, char *argv[]) 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); + disk = rawname(dt->mnt_fsname); + (void)strncpy(spcl.c_dev, dt->mnt_fsname, NAMELEN); + (void)strncpy(spcl.c_filesys, dt->mnt_dir, NAMELEN); } else { #ifdef __linux__ #ifdef HAVE_REALPATH @@ -458,9 +584,9 @@ main(int argc, char *argv[]) * a filesystem specified in fstab. Search for it. */ if ((dt = fstabsearch(pathname)) != NULL) { - disk = rawname(dt->fs_spec); - (void)strncpy(spcl.c_dev, dt->fs_spec, NAMELEN); - (void)strncpy(spcl.c_filesys, dt->fs_file, NAMELEN); + disk = rawname(dt->mnt_fsname); + (void)strncpy(spcl.c_dev, dt->mnt_fsname, NAMELEN); + (void)strncpy(spcl.c_filesys, dt->mnt_dir, NAMELEN); } else { /* * The argument was not found in the fstab @@ -469,11 +595,11 @@ main(int argc, char *argv[]) dt = fstabsearchdir(pathname, directory); if (dt != NULL) { char name[MAXPATHLEN]; - (void)strncpy(spcl.c_dev, dt->fs_spec, NAMELEN); + (void)strncpy(spcl.c_dev, dt->mnt_fsname, NAMELEN); (void)snprintf(name, sizeof(name), "%s (dir %s)", - dt->fs_file, directory); + dt->mnt_dir, directory); (void)strncpy(spcl.c_filesys, name, NAMELEN); - disk = rawname(dt->fs_spec); + disk = rawname(dt->mnt_fsname); } else { (void)strncpy(spcl.c_dev, disk, NAMELEN); (void)strncpy(spcl.c_filesys, "an unlisted file system", @@ -544,6 +670,14 @@ main(int argc, char *argv[]) } /* end of size estimate */ #ifdef __linux__ + if ((diskfd = OPEN(disk, O_RDONLY)) < 0) { + msg("Cannot open %s\n", disk); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } +#ifdef BLKFLSBUF + (void)ioctl(diskfd, BLKFLSBUF); +#endif retval = dump_fs_open(disk, &fs); if (retval) { com_err(disk, retval, "while opening filesystem"); @@ -558,11 +692,6 @@ main(int argc, char *argv[]) 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 */ if (spcl.c_label[0] == '\0') { const char *lbl; @@ -581,10 +710,8 @@ main(int argc, char *argv[]) tp_bshift = ffs(TP_BSIZE) - 1; if (TP_BSIZE != (1 << tp_bshift)) quit("TP_BSIZE (%d) is not a power of 2", TP_BSIZE); - maxino = fs->super->s_inodes_count; -#if 0 + maxino = fs->super->s_inodes_count + 1; spcl.c_flags |= DR_NEWINODEFMT; -#endif #else /* __linux __*/ if ((diskfd = open(disk, O_RDONLY)) < 0) { msg("Cannot open %s\n", disk); @@ -613,7 +740,9 @@ main(int argc, char *argv[]) usedinomap = (char *)calloc((unsigned) mapsize, sizeof(char)); dumpdirmap = (char *)calloc((unsigned) mapsize, sizeof(char)); dumpinomap = (char *)calloc((unsigned) mapsize, sizeof(char)); - if (usedinomap == NULL || dumpdirmap == NULL || dumpinomap == NULL) + metainomap = (char *)calloc((unsigned) mapsize, sizeof(char)); + if (usedinomap == NULL || dumpdirmap == NULL || + dumpinomap == NULL || metainomap == NULL) quit("out of memory allocating inode maps\n"); tapesize = 2 * (howmany(mapsize * sizeof(char), TP_BSIZE) + 1); @@ -621,10 +750,12 @@ main(int argc, char *argv[]) if (!sizest) { msg("Label: %s\n", spcl.c_label); + + msg("Writing %d Kilobyte records\n", ntrec); if (compressed) - msg("Compressing output at compression level %d\n", - compressed); + msg("Compressing output at compression level %d (%s)\n", + compressed, bzipflag ? "bzlib" : "zlib"); } #if defined(SIGINFO) @@ -669,14 +800,14 @@ main(int argc, char *argv[]) /* check if file is a directory */ if (!(statbuf.st_mode & S_IFDIR)) anydirskipped2 = maponefile(maxino, &tapesize, - p+strlen(dt->fs_file)); + p+strlen(dt->mnt_dir)); 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)); + p+strlen(dt->mnt_dir)); if (!anydirskipped) anydirskipped = anydirskipped2; argv++; @@ -698,7 +829,7 @@ main(int argc, char *argv[]) if (pipeout || unlimited) { tapesize += 1 + ntrec; /* 1 map header + trailer blocks */ - msg("estimated %ld tape blocks.\n", tapesize); + msg("estimated %ld blocks.\n", tapesize); } else { double fetapes; @@ -738,21 +869,22 @@ main(int argc, char *argv[]) tapesize += (etapes - 1) * (howmany(mapsize * sizeof(char), TP_BSIZE) + 1); tapesize += etapes + ntrec; /* headers + trailer blks */ - msg("estimated %ld tape blocks on %3.2f tape(s).\n", + msg("estimated %ld blocks on %3.2f tape(s).\n", tapesize, fetapes); } #ifdef USE_QFA if (tapepos) { msg("writing QFA positions to %s\n", gTapeposfile); - if ((gTapeposfd = open(gTapeposfile, O_RDWR|O_CREAT)) < 0) + if ((gTapeposfd = open(gTapeposfile, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR | S_IWUSR)) < 0) quit("can't open tapeposfile\n"); /* print QFA-file header */ - sprintf(gTps, "%s\n%s\n%ld\n\n", QFA_MAGIC, QFA_VERSION, (unsigned long)spcl.c_date); - if (write(gTapeposfd, gTps, strlen(gTps)) != strlen(gTps)) + snprintf(gTps, sizeof(gTps), "%s\n%s\n%ld\n\n", QFA_MAGIC, QFA_VERSION, (unsigned long)spcl.c_date); + gTps[sizeof(gTps) - 1] = '\0'; + if (write(gTapeposfd, gTps, strlen(gTps)) != (ssize_t)strlen(gTps)) quit("can't write tapeposfile\n"); sprintf(gTps, "ino\ttapeno\ttapepos\n"); - if (write(gTapeposfd, gTps, strlen(gTps)) != strlen(gTps)) + if (write(gTapeposfd, gTps, strlen(gTps)) != (ssize_t)strlen(gTps)) quit("can't write tapeposfile\n"); } #endif /* USE_QFA */ @@ -789,6 +921,8 @@ main(int argc, char *argv[]) */ if (dp->di_nlink == 0 || dp->di_dtime != 0) continue; + if (vflag) + msg("dumping directory inode %lu\n", ino); (void)dumpdirino(dp, ino); #else (void)dumpino(dp, ino); @@ -815,11 +949,24 @@ main(int argc, char *argv[]) * inodes since this is done in dumpino(). */ #endif - (void)dumpino(dp, ino); + if (vflag) { + if (mflag && TSTINO(ino, metainomap)) + msg("dumping regular inode %lu (meta only)\n", ino); + else + msg("dumping regular inode %lu\n", ino); + } + (void)dumpino(dp, ino, mflag && TSTINO(ino, metainomap)); } 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. @@ -831,10 +978,10 @@ main(int argc, char *argv[]) tnow = trewind(); if (pipeout || fifoout) - msg("%ld tape blocks (%.2fMB)\n", spcl.c_tapea, + msg("%ld blocks (%.2fMB)\n", spcl.c_tapea, ((double)spcl.c_tapea * TP_BSIZE / 1048576)); else - msg("%ld tape blocks (%.2fMB) on %d volume(s)\n", + msg("%ld blocks (%.2fMB) on %d volume(s)\n", spcl.c_tapea, ((double)spcl.c_tapea * TP_BSIZE / 1048576), spcl.c_volume); @@ -860,6 +1007,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); @@ -888,19 +1038,24 @@ usage(void) #ifdef KERBEROS "k" #endif - "MnSu" - "] [-B records] [-b blocksize] [-d density]\n" - "\t%s [-e inode#,inode#,...] [-E file] [-f file] [-h level] " + "mMnqSuv" + "] [-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 - "\n\t%s [-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); } @@ -997,6 +1152,7 @@ obsolete(int *argcp, char **argvp[]) for (flags = 0; *ap; ++ap) { switch (*ap) { + case 'A': case 'B': case 'b': case 'd': @@ -1064,7 +1220,7 @@ exclude_ino(dump_ino_t ino) * This tests adds an inode to the exclusion list if it isn't already there */ void -do_exclude_ino(dump_ino_t ino) +do_exclude_ino(dump_ino_t ino, const char *reason) { if (!exclude_ino(ino)) { if (iexclude_num == IEXCLUDE_MAXNUM) { @@ -1072,7 +1228,11 @@ do_exclude_ino(dump_ino_t ino) msg("The ENTIRE dump is aborted.\n"); exit(X_STARTUP); } - msg("Added inode %u to exclude list\n", ino); + if (reason) + msg("Excluding inode %u (%s) from dump\n", + ino, reason); + else + msg("Excluding inode %u from dump\n", ino); iexclude_list[iexclude_num++] = ino; } } @@ -1083,12 +1243,12 @@ do_exclude_ino_str(char * ino) { unsigned long inod; inod = strtoul(ino, &r, 10); - if (*r != '\0' || inod <= ROOTINO) { + if (( *r != '\0' && !isspace(*r) ) || inod <= ROOTINO) { msg("Invalid inode argument %s\n", ino); msg("The ENTIRE dump is aborted.\n"); exit(X_STARTUP); } - do_exclude_ino(inod); + do_exclude_ino(inod, NULL); } /* @@ -1114,3 +1274,12 @@ do_exclude_from_file(char *file) { } fclose(f); } + +static void incompat_flags(int cond, char flag1, char flag2) { + if (cond) { + msg("You cannot use the %c and %c flags together.\n", + flag1, flag2); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } +}