X-Git-Url: https://git.wh0rd.org/?p=dump.git;a=blobdiff_plain;f=dump%2Fmain.c;h=508ec15fab28d3734a7e8bcc90b6535ffef42bf6;hp=d7462c89fc6030c9c8c8cae93115297aaa17ad69;hb=c993d83a80c45bdf72ac623bd7f25766c6cb7682;hpb=54ec08c6ea42e9189423def508c5119f33466db2 diff --git a/dump/main.c b/dump/main.c index d7462c8..508ec15 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.54 2001/07/19 09:49:35 stelian Exp $"; + "$Id: main.c,v 1.77 2002/11/15 09:49:40 stelian Exp $"; #endif /* not lint */ #include @@ -55,6 +55,7 @@ static const char rcsid[] = #include #include #include +#include #include #include @@ -88,6 +89,76 @@ 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 */ @@ -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 fstab *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", 1L, 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 @@ -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); @@ -623,8 +752,8 @@ main(int argc, char *argv[]) msg("Label: %s\n", spcl.c_label); 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) @@ -745,14 +874,15 @@ main(int argc, char *argv[]) #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 +919,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 +947,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. @@ -860,6 +1005,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 +1036,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 +1150,7 @@ obsolete(int *argcp, char **argvp[]) for (flags = 0; *ap; ++ap) { switch (*ap) { + case 'A': case 'B': case 'b': case 'd': @@ -1073,10 +1227,10 @@ do_exclude_ino(dump_ino_t ino, const char *reason) exit(X_STARTUP); } if (reason) - msg("Added inode %u to exclude list (%s)\n", + msg("Excluding inode %u (%s) from dump\n", ino, reason); else - msg("Added inode %u to exclude list\n", ino); + msg("Excluding inode %u from dump\n", ino); iexclude_list[iexclude_num++] = ino; } } @@ -1087,7 +1241,7 @@ 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); @@ -1118,3 +1272,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); + } +}