]> git.wh0rd.org - dump.git/blobdiff - dump/traverse.c
Use the libext2fs inode-scanning functions.
[dump.git] / dump / traverse.c
index ed52904ffe6dd150c35ac0e20a438fc4c367272d..69cf6a2a56f0aad024a528a97d3e52a9d97c291c 100644 (file)
@@ -2,7 +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@cybercable.fr>, 1999-2000
+ *     Stelian Pop <pop@noos.fr>, 1999-2000
+ *     Stelian Pop <pop@noos.fr> - AlcĂ´ve <www.alcove.fr>, 2000
  */
 
 /*-
@@ -40,7 +41,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: traverse.c,v 1.15 2000/02/04 20:22:21 stelian Exp $";
+       "$Id: traverse.c,v 1.24 2000/12/05 16:57:38 stelian Exp $";
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -84,11 +85,15 @@ static const char rcsid[] =
 #define        HASDUMPEDFILE   0x1
 #define        HASSUBDIRS      0x2
 
+#ifdef __linux__
+typedef u_quad_t fsizeT;
+#else
 #ifdef FS_44INODEFMT
 typedef        quad_t fsizeT;
 #else
 typedef        long fsizeT;
 #endif
+#endif
 
 #ifdef __linux__
 static int searchdir __P((struct ext2_dir_entry *dp, int offset,
@@ -98,20 +103,23 @@ static     int dirindir __P((ino_t ino, daddr_t blkno, int level, long *size));
 static void dmpindir __P((ino_t ino, daddr_t blk, int level, fsizeT *size));
 static int searchdir __P((ino_t ino, daddr_t blkno, long size, long filesize));
 #endif
-static void mapfileino __P((ino_t ino, long *tapesize, int *dirskipped));
+static void mapfileino __P((ino_t ino, struct dinode const *dp, long *tapesize, int *dirskipped));
+static int exclude_ino __P((ino_t ino));
 
-/* #define EXT3_FEATURE_INCOMPAT_RECOVER */
+/* #define EXT3_FEATURE_INCOMPAT_RECOVER       0x0004 */
+#ifdef EXT3_FEATURE_INCOMPAT_RECOVER
+#define FORCE_OPEN     EXT2_FLAG_FORCE
+#else
+#define FORCE_OPEN     0
+#endif
 
 int dump_fs_open(const char *disk, ext2_filsys *fs)
 {
        int retval;
        struct ext2fs_sb *s;
 
-#ifdef EXT3_FEATURE_INCOMPAT_RECOVER
-       retval = ext2fs_open(disk, EXT2_FLAG_FORCE, 0, 0, unix_io_manager, fs);
-#else
-       retval = ext2fs_open(disk, 0, 0, 0, unix_io_manager, fs);
-#endif
+       retval = ext2fs_open(disk, FORCE_OPEN, 0, 0, unix_io_manager, fs);
+#if defined(EXT2_LIB_FEATURE_COMPAT_SUPP) && defined(EXT2_LIB_FEATURE_INCOMPAT_SUPP) && defined(EXT2_LIB_FEATURE_RO_COMPAT_SUPP) && defined(EXT2_ET_UNSUPP_FEATURE) && defined(EXT2_ET_RO_UNSUPP_FEATURE)
        if (!retval) {
                s = (struct ext2fs_sb *) (*fs)->super;
                if ((s->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
@@ -126,6 +134,7 @@ int dump_fs_open(const char *disk, ext2_filsys *fs)
                        retval = EXT2_ET_RO_UNSUPP_FEATURE;
                }
        }
+#endif /* defined && defined && defined... */
        return retval;
 }
 
@@ -137,7 +146,7 @@ int dump_fs_open(const char *disk, ext2_filsys *fs)
  * hence the estimate may be high.
  */
 long
-blockest(struct dinode *dp)
+blockest(struct dinode const *dp)
 {
        long blkest, sizeest;
 
@@ -164,7 +173,7 @@ blockest(struct dinode *dp)
                /* calculate the number of indirect blocks on the dump tape */
                blkest +=
                        howmany(sizeest - NDADDR * fs->blocksize / TP_BSIZE,
-                       TP_NINDIR);
+                       NINDIR(sblock) * EXT2_FRAGS_PER_BLOCK(fs->super));
        }
 #else
        if (dp->di_size > sblock->fs_bsize * NDADDR) {
@@ -177,37 +186,58 @@ blockest(struct dinode *dp)
        return (blkest + 1);
 }
 
+extern ino_t iexclude_list[IEXCLUDE_MAXNUM];   /* the inode exclude list */
+extern int iexclude_num;       /* number of elements in the list */
+
+/*
+ * This tests whether an inode is in the exclude list 
+ */
+int
+exclude_ino(ino_t ino)
+{
+       /* 04-Feb-00 ILC */
+       if (iexclude_num) {     /* if there are inodes in the exclude list */
+               int idx;        /* then check this inode against it */
+               for (idx = 0; idx < iexclude_num; idx++)
+                       if (ino == iexclude_list[idx])
+                               return 1;
+       }
+       return 0;
+}
+
 /* Auxiliary macro to pick up files changed since previous dump. */
 #define        CHANGEDSINCE(dp, t) \
        ((dp)->di_mtime >= (t) || (dp)->di_ctime >= (t))
 
-/* The WANTTODUMP macro decides whether a file should be dumped. */
+/* The NODUMP_FLAG macro tests if a file has the nodump flag. */
 #ifdef UF_NODUMP
-#define        WANTTODUMP(dp) \
-       (CHANGEDSINCE(dp, spcl.c_ddate) && \
-        (nonodump || ((dp)->di_flags & UF_NODUMP) != UF_NODUMP))
+#define NODUMP_FLAG(dp) (!nonodump && (((dp)->di_flags & UF_NODUMP) == UF_NODUMP))
 #else
-#define        WANTTODUMP(dp) CHANGEDSINCE(dp, spcl.c_ddate)
+#define NODUMP_FLAG(dp) 0
 #endif
 
-extern ino_t iexclude_list[IEXCLUDE_MAXNUM];   /* the inode exclude list */
-extern int iexclude_num;       /* number of elements in the list */
+/* The WANTTODUMP macro decides whether a file should be dumped. */
+#define        WANTTODUMP(dp, ino) \
+       (CHANGEDSINCE(dp, spcl.c_ddate) && \
+        (!NODUMP_FLAG(dp)) && \
+        (!exclude_ino(ino)))
 
 /*
- * Determine if given inode should be dumped
+ * Determine if given inode should be dumped. "dp" must either point to a
+ * copy of the given inode, or be NULL (in which case it is fetched.)
  */
-void
-mapfileino(ino_t ino, long *tapesize, int *dirskipped)
+static void
+mapfileino(ino_t ino, struct dinode const *dp, long *tapesize, int *dirskipped)
 {
        register int mode;
-       register struct dinode *dp;
 
        /*
         * Skip inode if we've already marked it for dumping
         */
        if (TSTINO(ino, usedinomap))
                return;
-       dp = getino(ino);
+       if (!dp)
+               dp = getino(ino);
        if ((mode = (dp->di_mode & IFMT)) == 0)
                return;
 #ifdef __linux__
@@ -221,20 +251,9 @@ mapfileino(ino_t ino, long *tapesize, int *dirskipped)
         */
        SETINO(ino, usedinomap);
 
-       /* 04-Feb-00 ILC */
-       if(iexclude_num) {      /* if there are inodes in the exclude list */
-               int idx;        /* then check this inode against it */
-               for (idx=0; idx<iexclude_num; idx++) {
-                       if (ino == iexclude_list[idx]) {
-                               msg("Excluding inode number %d\n", ino);
-                               return; /* if in list then skip */
-                       }
-               }
-       }
-
        if (mode == IFDIR)
                SETINO(ino, dumpdirmap);
-       if (WANTTODUMP(dp)) {
+       if (WANTTODUMP(dp, ino)) {
                SETINO(ino, dumpinomap);
                if (mode != IFREG && mode != IFDIR && mode != IFLNK)
                        *tapesize += 1;
@@ -243,10 +262,8 @@ mapfileino(ino_t ino, long *tapesize, int *dirskipped)
                return;
        }
        if (mode == IFDIR) {
-#ifdef UF_NODUMP
-               if (!nonodump && (dp->di_flags & UF_NODUMP))
+               if ( NODUMP_FLAG(dp) || exclude_ino(ino) )
                        CLRINO(ino, usedinomap);
-#endif
                *dirskipped = 1;
        }
 }
@@ -258,6 +275,51 @@ mapfileino(ino_t ino, long *tapesize, int *dirskipped)
  * that have been modified since the previous dump time. Also, find all
  * the directories in the filesystem.
  */
+#ifdef __linux__
+int
+mapfiles(ino_t maxino, long *tapesize)
+{
+       ino_t ino;
+       int anydirskipped = 0;
+       ext2_inode_scan scan;
+       errcode_t err;
+       struct ext2_inode inode;
+
+       /*
+        * We use libext2fs's inode scanning routines, which are particularly
+        * robust.  (Note that getino cannot return an error.)
+        */
+       err = ext2fs_open_inode_scan(fs, 0, &scan);
+       if (err) {
+               com_err(disk, err, "while opening inodes\n");
+               exit(X_ABORT);
+       }
+       for (;;) {
+               err = ext2fs_get_next_inode(scan, &ino, &inode);
+               if (err == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
+                       continue;
+               if (err) {
+                       com_err(disk, err, "while scanning inode #%ld\n",
+                               (long)ino);
+                       exit(X_ABORT);
+               }
+               if (ino == 0)
+                       break;
+
+               curino = ino;
+               mapfileino(ino, (struct dinode const *)&inode, tapesize,
+                          &anydirskipped);
+       }
+       ext2fs_close_inode_scan(scan);
+
+       /*
+        * Restore gets very upset if the root is not dumped,
+        * so ensure that it always is dumped.
+        */
+       SETINO(ROOTINO, dumpinomap);
+       return (anydirskipped);
+}
+#else
 int
 mapfiles(ino_t maxino, long *tapesize)
 {
@@ -274,6 +336,7 @@ mapfiles(ino_t maxino, long *tapesize)
        SETINO(ROOTINO, dumpinomap);
        return (anydirskipped);
 }
+#endif /* __linux__ */
 
 #ifdef __linux__
 struct mapfile_context {
@@ -284,7 +347,7 @@ struct mapfile_context {
 static int
 mapfilesindir(struct ext2_dir_entry *dirent, int offset, int blocksize, char *buf, void *private)
 {
-       register struct dinode *dp;
+       register struct dinode const *dp;
        register int mode;
        errcode_t retval;
        struct mapfile_context *mfc;
@@ -292,10 +355,10 @@ mapfilesindir(struct ext2_dir_entry *dirent, int offset, int blocksize, char *bu
 
        ino = dirent->inode;
        mfc = (struct mapfile_context *)private;
+       dp = getino(dirent->inode);
 
-       mapfileino(dirent->inode, mfc->tapesize, mfc->anydirskipped);
+       mapfileino(dirent->inode, dp, mfc->tapesize, mfc->anydirskipped);
 
-       dp = getino(dirent->inode);
        mode = dp->di_mode & IFMT;
        if (mode == IFDIR && dp->di_nlink != 0 && dp->di_dtime == 0) {
                if ((dirent->name[0] != '.' || ( dirent->name_len & 0xFF ) != 1) &&
@@ -340,7 +403,7 @@ mapfilesfromdir(ino_t maxino, long *tapesize, char *directory)
                                        dir_name);
                                exit(X_ABORT);
                        }
-                       mapfileino(dir_ino, tapesize, &anydirskipped);
+                       mapfileino(dir_ino, 0, tapesize, &anydirskipped);
                }
        }
        /*
@@ -351,7 +414,7 @@ mapfilesfromdir(ino_t maxino, long *tapesize, char *directory)
                com_err(disk, retval, "while translating %s", directory);
                exit(X_ABORT);
        }
-       mapfileino(dir_ino, tapesize, &anydirskipped);
+       mapfileino(dir_ino, 0, tapesize, &anydirskipped);
 
        mfc.tapesize = tapesize;
        mfc.anydirskipped = &anydirskipped;
@@ -366,7 +429,7 @@ mapfilesfromdir(ino_t maxino, long *tapesize, char *directory)
         * Ensure that the root inode actually appears in the file list
         * for a subdir
         */
-       mapfileino(ROOTINO, tapesize, &anydirskipped);
+       mapfileino(ROOTINO, 0, tapesize, &anydirskipped);
        /*
         * Restore gets very upset if the root is not dumped,
         * so ensure that it always is dumped.
@@ -803,22 +866,21 @@ static int
 convert_dir(struct ext2_dir_entry *dirent, int offset, int blocksize, char *buf, void *private)
 {
        struct convert_dir_context *p;
-       struct direct *dp;
+       struct olddirect *dp;
        int reclen;
 
        p = (struct convert_dir_context *)private;
 
        reclen = EXT2_DIR_REC_LEN((dirent->name_len & 0xFF) + 1);
        if (((p->offset + reclen - 1) / p->bs) != (p->offset / p->bs)) {
-               dp = (struct direct *)(p->buf + p->prev_offset);
+               dp = (struct olddirect *)(p->buf + p->prev_offset);
                dp->d_reclen += p->bs - (p->offset % p->bs);
                p->offset += p->bs - (p->offset % p->bs);
        }
 
-       dp = (struct direct *)(p->buf + p->offset);
+       dp = (struct olddirect *)(p->buf + p->offset);
        dp->d_ino = dirent->inode;
        dp->d_reclen = reclen;
-       dp->d_type = 0;
        dp->d_namlen = dirent->name_len & 0xFF;
        strncpy(dp->d_name, dirent->name, dp->d_namlen);
        dp->d_name[dp->d_namlen] = '\0';
@@ -1082,9 +1144,14 @@ struct dinode *
 getino(ino_t inum)
 {
        static struct dinode dinode;
+       errcode_t err;
 
        curino = inum;
-       ext2fs_read_inode(fs, inum, (struct ext2_inode *) &dinode);
+       err = ext2fs_read_inode(fs, inum, (struct ext2_inode *) &dinode);
+       if (err) {
+               com_err(disk, err, "while reading inode #%ld\n", (long)inum);
+               exit(X_ABORT);
+       }
        return &dinode;
 }
 #else  /* __linux__ */