X-Git-Url: https://git.wh0rd.org/?p=dump.git;a=blobdiff_plain;f=dump%2Foptr.c;h=a4504da1520f0078201bfbb2e295cfc6e69c3222;hp=c1ba8a97a7b9917249911745a77d527a5fefd6f2;hb=97be3358a32b246d4336692ebad4b1c366446932;hpb=b45f51d61e911ac8a040bef1efda6afd82261e03 diff --git a/dump/optr.c b/dump/optr.c index c1ba8a9..a4504da 100644 --- a/dump/optr.c +++ b/dump/optr.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 - * + * Stelian Pop , 1999-2000 + * Stelian Pop - AlcĂ´ve , 2000-2002 */ /*- @@ -18,11 +18,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -40,19 +36,19 @@ */ #ifndef lint -#if 0 -static char sccsid[] = "@(#)optr.c 8.2 (Berkeley) 1/6/94"; -#endif static const char rcsid[] = - "$Id: optr.c,v 1.2 1999/10/11 12:53:22 stelian Exp $"; + "$Id: optr.c,v 1.39 2004/07/05 15:12:45 stelian Exp $"; #endif /* not lint */ +#include #include #include #include +#include #include -#include +#include +#include #include #include #include @@ -60,9 +56,14 @@ static const char rcsid[] = #include #include #include +#include #ifdef __linux__ +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else #include +#endif #include #include #include @@ -70,10 +71,14 @@ static const char rcsid[] = #include "dump.h" #include "pathnames.h" +#include "bylabel.h" -void alarmcatch __P((/* int, int */)); +static void alarmcatch __P((int)); int datesort __P((const void *, const void *)); -static void sendmes __P((char *, char *)); +static void sendmes __P((const char *, const char *)); + +/* List of filesystem types that we can dump (same ext2 on-disk format) */ +static char *fstypes[] = { "ext2", "ext3", "InterMezzo", NULL }; /* * Query the operator; This previously-fascist piece of code @@ -87,21 +92,29 @@ static void sendmes __P((char *, char *)); * that dump needs attention. */ static int timeout; -static char *attnmessage; /* attention message */ +static const char *attnmessage; /* attention message */ int -query(question) - char *question; +query(const char *question) { char replybuffer[64]; int back, errcount; FILE *mytty; + time_t firstprompt, when_answered; + + if (qflag) { + msg("%s - forced abort\n", question); + dumpabort(0); + /* NOTREACHED */ + } + + firstprompt = time(NULL); if ((mytty = fopen(_PATH_TTY, "r")) == NULL) quit("fopen on %s fails: %s\n", _PATH_TTY, strerror(errno)); attnmessage = question; timeout = 0; - alarmcatch(); + alarmcatch(0); back = -1; errcount = 0; do { @@ -128,18 +141,26 @@ query(question) if (signal(SIGALRM, sig) == SIG_IGN) signal(SIGALRM, SIG_IGN); (void) fclose(mytty); + when_answered = time(NULL); + /* + * Adjust the base for time estimates to ignore time we spent waiting + * for operator input. + */ + if (tstart_writing != 0) + tstart_writing += (when_answered - firstprompt); return(back); } -char lastmsg[100]; +char lastmsg[BUFSIZ]; /* * Alert the console operator, and enable the alarm clock to * sleep for 2 minutes in case nobody comes to satisfy dump */ -void -alarmcatch() +static void +alarmcatch(UNUSED(int signo)) { + int save_errno = errno; if (notify == 0) { if (timeout == 0) (void) fprintf(stderr, @@ -158,14 +179,14 @@ alarmcatch() signal(SIGALRM, alarmcatch); (void) alarm(120); timeout = 1; + errno = save_errno; } /* * Here if an inquisitive operator interrupts the dump program */ void -interrupt(signo) - int signo; +interrupt(UNUSED(int signo)) { msg("Interrupt received.\n"); if (query("Do you want to abort dump?")) @@ -183,7 +204,7 @@ struct group *gp; * Get the names from the group entry "operator" to notify. */ void -set_operators() +set_operators(void) { if (!notify) /*not going to notify*/ return; @@ -203,8 +224,7 @@ struct tm *localclock; * that the process control groups are not messed up */ void -broadcast(message) - char *message; +broadcast(const char *message) { time_t clock; FILE *f_utmp; @@ -226,7 +246,7 @@ broadcast(message) return; } - clock = time((time_t *)0); + clock = time(NULL); localclock = localtime(&clock); if ((f_utmp = fopen(_PATH_UTMP, "r")) == NULL) { @@ -259,11 +279,10 @@ broadcast(message) } static void -sendmes(tty, message) - char *tty, *message; +sendmes(const char *tty, const char *message) { char t[MAXPATHLEN], buf[BUFSIZ]; - register char *cp; + const char *cp; int lmsg = 1; FILE *f_tty; @@ -281,7 +300,7 @@ DUMP: NEEDS ATTENTION: ", if (*cp == '\0') { if (lmsg) { cp = message; - if (*cp == '\0') + if (!(cp && *cp != '\0')) break; lmsg = 0; } else @@ -302,26 +321,23 @@ DUMP: NEEDS ATTENTION: ", time_t tschedule = 0; void -timeest() +timeest(void) { - time_t tnow, deltat; + time_t tnow = time(NULL); - (void) time((time_t *) &tnow); if (tnow >= tschedule) { + char *buf = mktimeest(tnow); tschedule = tnow + 300; - if (blockswritten < 500) - return; - deltat = tstart_writing - tnow + - (1.0 * (tnow - tstart_writing)) - / blockswritten * tapesize; - msg("%3.2f%% done, finished in %d:%02d\n", - (blockswritten * 100.0) / tapesize, - deltat / 3600, (deltat % 3600) / 60); + if (buf) { + fprintf(stderr, " DUMP: "); + fwrite(buf, strlen(buf), 1, stderr); + fflush(stderr); + } } } void -#if __STDC__ +#ifdef __STDC__ msg(const char *fmt, ...) #else msg(fmt, va_alist) @@ -335,20 +351,26 @@ msg(fmt, va_alist) #ifdef TDEBUG (void) fprintf(stderr, "pid=%d ", getpid()); #endif -#if __STDC__ +#ifdef __STDC__ va_start(ap, fmt); #else va_start(ap); #endif (void) vfprintf(stderr, fmt, ap); + va_end(ap); (void) fflush(stdout); (void) fflush(stderr); - (void) vsprintf(lastmsg, fmt, ap); +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void) vsnprintf(lastmsg, sizeof(lastmsg), fmt, ap); va_end(ap); } void -#if __STDC__ +#ifdef __STDC__ msgtail(const char *fmt, ...) #else msgtail(fmt, va_alist) @@ -357,7 +379,7 @@ msgtail(fmt, va_alist) #endif { va_list ap; -#if __STDC__ +#ifdef __STDC__ va_start(ap, fmt); #else va_start(ap); @@ -367,7 +389,7 @@ msgtail(fmt, va_alist) } void -#if __STDC__ +#ifdef __STDC__ quit(const char *fmt, ...) #else quit(fmt, va_alist) @@ -381,7 +403,7 @@ quit(fmt, va_alist) #ifdef TDEBUG (void) fprintf(stderr, "pid=%d ", getpid()); #endif -#if __STDC__ +#ifdef __STDC__ va_start(ap, fmt); #else va_start(ap); @@ -398,54 +420,104 @@ quit(fmt, va_alist) * we don't actually do it */ -struct fstab * -allocfsent(fs) - register struct fstab *fs; -{ - register struct fstab *new; - - new = (struct fstab *)malloc(sizeof (*fs)); - if (new == NULL || - (new->fs_file = strdup(fs->fs_file)) == NULL || - (new->fs_type = strdup(fs->fs_type)) == NULL || - (new->fs_spec = strdup(fs->fs_spec)) == NULL) - quit("%s\n", strerror(errno)); - new->fs_passno = fs->fs_passno; - new->fs_freq = fs->fs_freq; - return (new); -} - struct pfstab { struct pfstab *pf_next; - struct fstab *pf_fstab; + struct dumpdates *pf_dd; + struct mntent *pf_mntent; }; static struct pfstab *table; -void -getfstab() +static struct mntent * +allocfsent(struct mntent *fs) { - register struct fstab *fs; - register struct pfstab *pf; + struct mntent *new; + const char *disk; + struct stat buf, tabbuf; + struct pfstab *tabpf; + struct mntent *tabfs; + + new = (struct mntent *)malloc(sizeof (*fs)); + if (new == NULL) + quit("%s\n", strerror(errno)); - if (setfsent() == 0) { - msg("Can't open %s for dump table information: %s\n", - _PATH_FSTAB, strerror(errno)); - return; + /* Translade UUID=, LABEL= ... */ + disk = get_device_name(fs->mnt_fsname); + if (disk == NULL) + disk = strdup(fs->mnt_fsname); + + /* Discard non block devices */ + if (stat(disk, &buf) != 0 || !S_ISBLK(buf.st_mode)) { + free(new); + return NULL; + } + + /* Discard same major/minor devices */ + for (tabpf = table; tabpf != NULL; tabpf = tabpf->pf_next) { + tabfs = tabpf->pf_mntent; + if (stat(tabfs->mnt_fsname, &tabbuf) != 0) + /* should not happen */ + quit("Cannot access %s\n", tabfs->mnt_fsname); + if (tabbuf.st_rdev == buf.st_rdev) { + free(new); + /* Copy passno and freq from /etc/fstab because + * /etc/mtab does always have them as 0 0 */ + if (!tabfs->mnt_passno) + tabfs->mnt_passno = fs->mnt_passno; + if (!tabfs->mnt_freq) + tabfs->mnt_freq = fs->mnt_freq; + return NULL; + } } - while ((fs = getfsent()) != NULL) { - if (strcmp(fs->fs_type, FSTAB_RW) && - strcmp(fs->fs_type, FSTAB_RO) && - strcmp(fs->fs_type, FSTAB_RQ)) + + if (strlen(fs->mnt_dir) > 1 && fs->mnt_dir[strlen(fs->mnt_dir) - 1] == '/') + fs->mnt_dir[strlen(fs->mnt_dir) - 1] = '\0'; + if ((new->mnt_dir = strdup(fs->mnt_dir)) == NULL || + (new->mnt_type = strdup(fs->mnt_type)) == NULL || + (new->mnt_opts = strdup(fs->mnt_opts)) == NULL || + (new->mnt_fsname = strdup(disk)) == NULL) + quit("%s\n", strerror(errno)); + new->mnt_passno = fs->mnt_passno; + new->mnt_freq = fs->mnt_freq; + return (new); +} + +void +getfstab(void) +{ + struct mntent *fs; + struct pfstab *pf; + struct pfstab *pfold = NULL; + FILE *mntfp; + char *mnttables[] = { _PATH_MOUNTED, _PATH_MNTTAB, 0 }; + int i; + + for (i = 0; mnttables[i]; i++) { + mntfp = setmntent(mnttables[i], "r"); + if (mntfp == NULL) { + msg("Can't open %s for dump table information: %s\n", + mnttables[i], strerror(errno)); continue; - fs = allocfsent(fs); - if ((pf = (struct pfstab *)malloc(sizeof (*pf))) == NULL) - quit("%s\n", strerror(errno)); - pf->pf_fstab = fs; - pf->pf_next = table; - table = pf; + } + while ((fs = getmntent(mntfp)) != NULL) { + fs = allocfsent(fs); + if (!fs) + continue; + fs->mnt_passno = 0; + if ((pf = (struct pfstab *)malloc(sizeof (*pf))) == NULL) + quit("%s\n", strerror(errno)); + pf->pf_mntent = fs; + pf->pf_next = NULL; + + /* keep table in /etc/fstab order for use with -w and -W */ + if (pfold) { + pfold->pf_next = pf; + pfold = pf; + } else + pfold = table = pf; + } + (void) endmntent(mntfp); } - (void) endfsent(); } /* @@ -459,28 +531,27 @@ getfstab() * * The file name can omit the leading '/'. */ -struct fstab * -fstabsearch(key) - char *key; +struct mntent * +fstabsearch(const char *key) { - register struct pfstab *pf; - register struct fstab *fs; - char *rn; + struct pfstab *pf; + struct mntent *fs; + const char *rn; for (pf = table; pf != NULL; pf = pf->pf_next) { - fs = pf->pf_fstab; - if (strcmp(fs->fs_file, key) == 0 || - strcmp(fs->fs_spec, key) == 0) + fs = pf->pf_mntent; + if (strcmp(fs->mnt_dir, key) == 0 || + strcmp(fs->mnt_fsname, key) == 0) return (fs); - rn = rawname(fs->fs_spec); + rn = rawname(fs->mnt_fsname); if (rn != NULL && strcmp(rn, key) == 0) return (fs); if (key[0] != '/') { - if (*fs->fs_spec == '/' && - strcmp(fs->fs_spec + 1, key) == 0) + if (*fs->mnt_fsname == '/' && + strcmp(fs->mnt_fsname + 1, key) == 0) return (fs); - if (*fs->fs_file == '/' && - strcmp(fs->fs_file + 1, key) == 0) + if (*fs->mnt_dir == '/' && + strcmp(fs->mnt_dir + 1, key) == 0) return (fs); } } @@ -488,25 +559,27 @@ fstabsearch(key) } #ifdef __linux__ -struct fstab * -fstabsearchdir(key, directory) - char *key; - char *directory; +struct mntent * +fstabsearchdir(const char *key, char *directory) { - register struct pfstab *pf; - register struct fstab *fs; - register struct fstab *found_fs = NULL; + struct pfstab *pf; + struct mntent *fs; + struct mntent *found_fs = NULL; unsigned int size = 0; + struct stat buf; + + if (stat(key, &buf) == 0 && S_ISBLK(buf.st_mode)) + return NULL; for (pf = table; pf != NULL; pf = pf->pf_next) { - fs = pf->pf_fstab; - if (strlen(fs->fs_file) > size && - strlen(key) > strlen(fs->fs_file) + 2 && - strncmp(fs->fs_file, key, strlen(fs->fs_file)) == 0 && - (key[strlen(fs->fs_file)] == '/' || - fs->fs_file[strlen(fs->fs_file) - 1] == '/')) { + fs = pf->pf_mntent; + if (strlen(fs->mnt_dir) > size && + strlen(key) > strlen(fs->mnt_dir) && + strncmp(fs->mnt_dir, key, strlen(fs->mnt_dir)) == 0 && + (key[strlen(fs->mnt_dir)] == '/' || + fs->mnt_dir[strlen(fs->mnt_dir) - 1] == '/')) { found_fs = fs; - size = strlen(fs->fs_file); + size = strlen(fs->mnt_dir); } } if (found_fs != NULL) { @@ -522,55 +595,135 @@ fstabsearchdir(key, directory) } #endif +static void +print_wmsg(char arg, int dumpme, const char *dev, int level, + const char *mtpt, time_t ddate) +{ +#ifdef FDEBUG + printf("checking dev %s: lvl %d, mtpt %s\n", dev, level, mtpt); +#endif + if (!dumpme && arg == 'w') + return; + + (void) printf("%c %8s\t(%6s) Last dump: ", + dumpme && (arg != 'w') ? '>' : ' ', + dev, + mtpt ? mtpt : ""); + + /* + * Check ddate > 365 to avoid issues with fs in stab but not dumpdates. + * Not a problem, because ddate is in seconds since the epoch anyways. + */ + if (ddate > 365) { + char *date, *d; + + date = (char *)ctime(&ddate); + d = strchr(date, '\n'); + if (d) *d = '\0'; + printf("Level %d, Date %s\n", level, date); + } else + printf("never\n"); +} + /* * Tell the operator what to do */ void -lastdump(arg) - char arg; /* w ==> just what to do; W ==> most recent dumps */ +lastdump(char arg) /* w ==> just what to do; W ==> most recent dumps */ { - register int i; - register struct fstab *dt; - register struct dumpdates *dtwalk; - char *lastname, *date; - int dumpme; + struct pfstab *pf; time_t tnow; - (void) time(&tnow); + tnow = time(NULL); getfstab(); /* /etc/fstab input */ - initdumptimes(); /* /etc/dumpdates input */ - qsort((char *) ddatev, nddates, sizeof(struct dumpdates *), datesort); + initdumptimes(0); /* dumpdates input */ + if (ddatev == NULL && table == NULL) { + (void) printf("No %s or %s file found\n", + _PATH_MNTTAB, dumpdates); + return; + } if (arg == 'w') (void) printf("Dump these file systems:\n"); else (void) printf("Last dump(s) done (Dump '>' file systems):\n"); - lastname = "??"; - ITITERATE(i, dtwalk) { - if (strncmp(lastname, dtwalk->dd_name, - sizeof(dtwalk->dd_name)) == 0) - continue; - date = (char *)ctime(&dtwalk->dd_ddate); - date[16] = '\0'; /* blast away seconds and year */ - lastname = dtwalk->dd_name; - dt = fstabsearch(dtwalk->dd_name); - dumpme = (dt != NULL && - dt->fs_freq != 0 && - dtwalk->dd_ddate < tnow - (dt->fs_freq * 86400)); - if (arg != 'w' || dumpme) - (void) printf( - "%c %8s\t(%6s) Last dump: Level %c, Date %s\n", - dumpme && (arg != 'w') ? '>' : ' ', - dtwalk->dd_name, - dt ? dt->fs_file : "", - dtwalk->dd_level, - date); + + /* For files in dumpdates, get the last dump level and date */ + if (ddatev != NULL) { + struct dumpdates *dtwalk = NULL; + int i; + char *lastname; + + qsort((char *) ddatev, nddates, sizeof(struct dumpdates *), datesort); + + lastname = "??"; + ITITERATE(i, dtwalk) { + struct mntent *dt; + if (strncmp(lastname, dtwalk->dd_name, + sizeof(dtwalk->dd_name)) == 0) + continue; + lastname = dtwalk->dd_name; + if ((dt = dtwalk->dd_fstab) != NULL) { + /* Overload fs_freq as dump level and + * fs_passno as date, because we can't + * change struct fstab format. + * A positive fs_freq means this + * filesystem needs to be dumped. + */ + dt->mnt_passno = dtwalk->dd_ddate; + if (dt->mnt_freq > 0 && (dtwalk->dd_ddate < + tnow - (dt->mnt_freq * 86400))) + dt->mnt_freq = dtwalk->dd_level; + else + dt->mnt_freq = -dtwalk->dd_level; +#ifdef FDEBUG + printf("%s fs_freq set to %d\n", lastname, + dt->mnt_freq); +#endif + } + } + } + + /* print in /etc/fstab order only those filesystem types we can dump */ + for (pf = table; pf != NULL; pf = pf->pf_next) { + struct mntent *dt = pf->pf_mntent; + char **type; + + for (type = fstypes; *type != NULL; type++) { + if (strncmp(dt->mnt_type, *type, + sizeof(dt->mnt_type)) == 0) { + const char *disk = get_device_name(dt->mnt_fsname); + print_wmsg(arg, dt->mnt_freq > 0, + disk ? disk : dt->mnt_fsname, + dt->mnt_freq < 0 ? -dt->mnt_freq : + dt->mnt_freq, + dt->mnt_dir, + dt->mnt_passno); + } + } + } + + /* print in /etc/dumpdates order if not in /etc/fstab */ + if (ddatev != NULL) { + struct dumpdates *dtwalk = NULL; + char *lastname; + int i; + + lastname = "??"; + ITITERATE(i, dtwalk) { + if (strncmp(lastname, dtwalk->dd_name, + sizeof(dtwalk->dd_name)) == 0 || + dtwalk->dd_fstab != NULL) + continue; + lastname = dtwalk->dd_name; + print_wmsg(arg, 0, dtwalk->dd_name, + dtwalk->dd_level, NULL, dtwalk->dd_ddate); + } } } int -datesort(a1, a2) - const void *a1, *a2; +datesort(const void *a1, const void *a2) { struct dumpdates *d1 = *(struct dumpdates **)a1; struct dumpdates *d2 = *(struct dumpdates **)a2;