]> git.wh0rd.org - dump.git/blobdiff - dump/optr.c
A wrong line in /etc/fstab containing LABEL=... could prevent dump from running....
[dump.git] / dump / optr.c
index 0ac0acee6db937e42fc64d112acb68d9786a4727..a4504da1520f0078201bfbb2e295cfc6e69c3222 100644 (file)
@@ -2,8 +2,8 @@
  *     Ported to Linux's Second Extended File System as part of the
  *     dump and restore backup suit
  *     Remy Card <card@Linux.EU.Org>, 1994-1997
- *     Stelian Pop <pop@noos.fr>, 1999-2000
- *     Stelian Pop <pop@noos.fr> - Alcôve <www.alcove.fr>, 2000
+ *     Stelian Pop <stelian@popies.net>, 1999-2000
+ *     Stelian Pop <stelian@popies.net> - Alcôve <www.alcove.com>, 2000-2002
  */
 
 /*-
  * 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.
  *
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: optr.c,v 1.17 2000/12/05 16:31:36 stelian Exp $";
+       "$Id: optr.c,v 1.39 2004/07/05 15:12:45 stelian Exp $";
 #endif /* not lint */
 
+#include <config.h>
 #include <sys/param.h>
 #include <sys/wait.h>
 #include <sys/time.h>
+#include <time.h>
 
 #include <errno.h>
-#include <fstab.h>
+#include <mntent.h>
+#include <paths.h>
 #include <grp.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -60,7 +59,11 @@ static const char rcsid[] =
 #include <sys/stat.h>
 
 #ifdef __linux__
+#ifdef HAVE_EXT2FS_EXT2_FS_H
+#include <ext2fs/ext2_fs.h>
+#else
 #include <linux/ext2_fs.h>
+#endif
 #include <ext2fs/ext2fs.h>
 #include <bsdcompat.h>
 #include <signal.h>
@@ -99,11 +102,13 @@ query(const char *question)
        FILE    *mytty;
        time_t  firstprompt, when_answered;
 
-#ifdef __linux__
-       (void)time4(&(firstprompt));
-#else
-       (void)time((time_t *)&(firstprompt));
-#endif
+       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));
@@ -136,16 +141,12 @@ query(const char *question)
        if (signal(SIGALRM, sig) == SIG_IGN)
                signal(SIGALRM, SIG_IGN);
        (void) fclose(mytty);
-#ifdef __linux__
-       (void)time4(&(when_answered));
-#else
-       (void)time((time_t *)&(when_answered));
-#endif
+       when_answered = time(NULL);
        /*
         * Adjust the base for time estimates to ignore time we spent waiting
         * for operator input.
         */
-       if ((tstart_writing != 0) && (when_answered != (time_t)-1) && (firstprompt != (time_t)-1))
+       if (tstart_writing != 0)
                tstart_writing += (when_answered - firstprompt);
        return(back);
 }
@@ -157,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) {
@@ -185,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?"))
@@ -245,7 +246,7 @@ broadcast(const char *message)
                return;
        }
 
-       clock = time((time_t *)0);
+       clock = time(NULL);
        localclock = localtime(&clock);
 
        if ((f_utmp = fopen(_PATH_UTMP, "r")) == NULL) {
@@ -281,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;
 
@@ -322,13 +323,8 @@ time_t     tschedule = 0;
 void
 timeest(void)
 {
-       time_t tnow;
+       time_t tnow = time(NULL);
 
-#ifdef __linux__
-       (void) time4(&tnow);
-#else
-       (void) time((time_t *) &tnow);
-#endif
        if (tnow >= tschedule) {
                char *buf = mktimeest(tnow);
                tschedule = tnow + 300;
@@ -424,67 +420,104 @@ 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;
+                       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;
        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();
 }
 
 /*
@@ -498,27 +531,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;
-       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);
                }
        }
@@ -526,12 +559,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;
 
@@ -539,14 +572,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) {
@@ -566,15 +599,9 @@ static void
 print_wmsg(char arg, int dumpme, const char *dev, int level,
           const char *mtpt, time_t ddate)
 {
-       char *date;
-       
-       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;
 
@@ -583,10 +610,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 (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");
 }
 
@@ -599,12 +634,12 @@ lastdump(char arg) /* w ==> just what to do; W ==> most recent dumps */
        struct pfstab *pf;
        time_t tnow;
 
-       (void) time(&tnow);
+       tnow = time(NULL);
        getfstab();             /* /etc/fstab input */
        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;
        }
 
@@ -613,6 +648,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;
@@ -622,7 +658,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;
@@ -631,34 +667,38 @@ 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.
                                 */
-                               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 = dtwalk->dd_level;
                                else
-                                       dt->fs_freq = dtwalk->dd_level + 1;
-
+                                       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 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 :
+                                                             dt->mnt_freq,
+                                          dt->mnt_dir,
+                                          dt->mnt_passno);
                        }
                }
        }