X-Git-Url: https://git.wh0rd.org/?p=dump.git;a=blobdiff_plain;f=dump%2Foptr.c;h=056a6a6c123f9e7f3cd6164be37c451499139a3b;hp=471ea5b9693bf4556186e858fd94aa77339206ef;hb=c43794b1b0a6115b1d12f0dc2ad2135d2a36fdc9;hpb=e4a8bde40a6d8319d1b28e054e1a419ba3df2363 diff --git a/dump/optr.c b/dump/optr.c index 471ea5b..056a6a6 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-2000 - * Stelian Pop - Alcôve , 2000 + * 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. * @@ -41,16 +37,18 @@ #ifndef lint static const char rcsid[] = - "$Id: optr.c,v 1.23 2001/06/18 10:58:28 stelian Exp $"; + "$Id: optr.c,v 1.40 2006/03/14 11:09:51 stelian Exp $"; #endif /* not lint */ #include #include #include #include +#include #include -#include +#include +#include #include #include #include @@ -69,7 +67,6 @@ static const char rcsid[] = #include #include #include -#include #endif #include "dump.h" @@ -105,6 +102,12 @@ query(const char *question) 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) @@ -155,7 +158,7 @@ char lastmsg[BUFSIZ]; * sleep for 2 minutes in case nobody comes to satisfy dump */ static void -alarmcatch(int signo) +alarmcatch(UNUSED(int signo)) { int save_errno = errno; if (notify == 0) { @@ -183,7 +186,7 @@ alarmcatch(int signo) * Here if an inquisitive operator interrupts the dump program */ void -interrupt(int signo) +interrupt(UNUSED(int signo)) { msg("Interrupt received.\n"); if (query("Do you want to abort dump?")) @@ -279,7 +282,7 @@ static void sendmes(const char *tty, const char *message) { char t[MAXPATHLEN], buf[BUFSIZ]; - register const char *cp; + const char *cp; int lmsg = 1; FILE *f_tty; @@ -417,67 +420,110 @@ quit(fmt, va_alist) * we don't actually do it */ -static struct fstab * -allocfsent(struct fstab *fs) +struct pfstab { + struct pfstab *pf_next; + struct dumpdates *pf_dd; + struct mntent *pf_mntent; +}; + +static struct pfstab *table; + +static struct mntent * +allocfsent(struct mntent *fs) { - register struct fstab *new; + struct mntent *new; + const char *disk; + struct stat buf, tabbuf; + struct pfstab *tabpf; + struct mntent *tabfs; - new = (struct fstab *)malloc(sizeof (*fs)); + new = (struct mntent *)malloc(sizeof (*fs)); if (new == NULL) quit("%s\n", strerror(errno)); - if (strlen(fs->fs_file) > 1 && fs->fs_file[strlen(fs->fs_file) - 1] == '/') - fs->fs_file[strlen(fs->fs_file) - 1] = '\0'; - if ((new->fs_file = strdup(fs->fs_file)) == NULL || - (new->fs_type = strdup(fs->fs_type)) == NULL || - (new->fs_vfstype = strdup(fs->fs_vfstype)) == NULL || - (new->fs_spec = strdup(fs->fs_spec)) == NULL) + + /* 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; + if (tabfs->mnt_freq > 3659) + quit("Dump frequency in fstab/mtab for %s is too big: %d > 3659\n", + tabfs->mnt_fsname, tabfs->mnt_freq); + return NULL; + } + } + + 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->fs_passno = fs->fs_passno; - new->fs_freq = fs->fs_freq; + new->mnt_passno = fs->mnt_passno; + new->mnt_freq = fs->mnt_freq; + if (new->mnt_freq > 3659) + quit("Dump frequency in fstab/mtab for %s %s is too big: %d > 3659\n", + new->mnt_dir, new->mnt_fsname, new->mnt_freq); return (new); } -struct pfstab { - struct pfstab *pf_next; - struct dumpdates *pf_dd; - struct fstab *pf_fstab; -}; - -static struct pfstab *table; - void getfstab(void) { - struct fstab *fs; + struct mntent *fs; struct pfstab *pf; struct pfstab *pfold = NULL; - - if (setfsent() == 0) { - msg("Can't open %s for dump table information: %s\n", - _PATH_FSTAB, strerror(errno)); - return; - } - while ((fs = getfsent()) != NULL) { - if (strcmp(fs->fs_type, FSTAB_RW) && - strcmp(fs->fs_type, FSTAB_RO) && - strcmp(fs->fs_type, FSTAB_RQ)) + 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); - fs->fs_passno = 0; - if ((pf = (struct pfstab *)malloc(sizeof (*pf))) == NULL) - quit("%s\n", strerror(errno)); - pf->pf_fstab = 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; - + } + 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(); } /* @@ -491,27 +537,27 @@ getfstab(void) * * The file name can omit the leading '/'. */ -struct fstab * +struct mntent * fstabsearch(const char *key) { - register struct pfstab *pf; - register struct fstab *fs; + 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); } } @@ -519,12 +565,12 @@ fstabsearch(const char *key) } #ifdef __linux__ -struct fstab * +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; @@ -532,14 +578,14 @@ fstabsearchdir(const char *key, char *directory) 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) + 1 && - 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) { @@ -559,15 +605,9 @@ static void print_wmsg(char arg, int dumpme, const char *dev, int level, const char *mtpt, time_t ddate) { - char *date = NULL; - - if (ddate) { - char *d; - date = (char *)ctime(&ddate); - d = strchr(date, '\n'); - if (d) *d = '\0'; - } - +#ifdef FDEBUG + printf("checking dev %s: lvl %d, mtpt %s\n", dev, level, mtpt); +#endif if (!dumpme && arg == 'w') return; @@ -576,10 +616,18 @@ print_wmsg(char arg, int dumpme, const char *dev, int level, dev, mtpt ? mtpt : ""); - if (ddate) - printf("Level %c, Date %s\n", - level, date); - else + /* + * 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 (level >= 0 && 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"); } @@ -597,7 +645,7 @@ lastdump(char arg) /* w ==> just what to do; W ==> most recent dumps */ initdumptimes(0); /* dumpdates input */ if (ddatev == NULL && table == NULL) { (void) printf("No %s or %s file found\n", - _PATH_FSTAB, _PATH_DUMPDATES); + _PATH_MNTTAB, dumpdates); return; } @@ -606,6 +654,7 @@ lastdump(char arg) /* w ==> just what to do; W ==> most recent dumps */ else (void) printf("Last dump(s) done (Dump '>' file systems):\n"); + /* For files in dumpdates, get the last dump level and date */ if (ddatev != NULL) { struct dumpdates *dtwalk = NULL; int i; @@ -615,7 +664,7 @@ lastdump(char arg) /* w ==> just what to do; W ==> most recent dumps */ lastname = "??"; ITITERATE(i, dtwalk) { - struct fstab *dt; + struct mntent *dt; if (strncmp(lastname, dtwalk->dd_name, sizeof(dtwalk->dd_name)) == 0) continue; @@ -624,34 +673,51 @@ lastdump(char arg) /* w ==> just what to do; W ==> most recent dumps */ /* Overload fs_freq as dump level and * fs_passno as date, because we can't * change struct fstab format. - * A negative fs_freq means this + * A positive fs_freq means this * filesystem needs to be dumped. + * + * UGLY HACK: values in 0-3659 range indicate + * original value from /etc/fstab (maximum + * 10 years...) + * + * Values bigger than 3659 indicate that + * the fs is to be dumped, and the latest + * dump level was x-3660 + * + * Negative values indicate that the fs is + * not to be dumped, and the latest dump + * level was -x-1 */ - dt->fs_passno = dtwalk->dd_ddate; - if (dt->fs_freq > 0 && (dtwalk->dd_ddate < - tnow - (dt->fs_freq * 86400))) - dt->fs_freq = -dtwalk->dd_level - 1; + dt->mnt_passno = dtwalk->dd_ddate; + if (dt->mnt_freq > 0 && (dtwalk->dd_ddate < + tnow - (dt->mnt_freq * 86400))) + dt->mnt_freq = 3660 + dtwalk->dd_level; else - dt->fs_freq = dtwalk->dd_level + 1; - + dt->mnt_freq = -dtwalk->dd_level - 1; +#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 fstab *dt = pf->pf_fstab; + struct mntent *dt = pf->pf_mntent; char **type; for (type = fstypes; *type != NULL; type++) { - if (strncmp(dt->fs_vfstype, *type, - sizeof(dt->fs_vfstype)) == 0) { - const char *disk = get_device_name(dt->fs_spec); - print_wmsg(arg, dt->fs_freq < 0, - disk ? disk : dt->fs_spec, - dt->fs_freq < 0 ? -dt->fs_freq - 1 : dt->fs_freq - 1, - dt->fs_file, - dt->fs_passno); + 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 - 1 : + dt->mnt_freq < 3660 ? -1 : + dt->mnt_freq - 3660), + dt->mnt_dir, + dt->mnt_passno); } } }