]> git.wh0rd.org - dump.git/commitdiff
Use the libext2fs inode-scanning functions.
authorStelian Pop <stelian@popies.net>
Tue, 5 Dec 2000 16:57:37 +0000 (16:57 +0000)
committerStelian Pop <stelian@popies.net>
Tue, 5 Dec 2000 16:57:37 +0000 (16:57 +0000)
CHANGES
dump/dump.h
dump/traverse.c

diff --git a/CHANGES b/CHANGES
index 02aa723bf51c7df24506a2f62fd740fb55c387d8..13a5cbce9d49316c4eac32759e3c82ec0c75f3dd 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,4 @@
-$Id: CHANGES,v 1.96 2000/12/05 16:31:35 stelian Exp $
+$Id: CHANGES,v 1.97 2000/12/05 16:57:37 stelian Exp $
 
 Changes between versions 0.4b20 and 0.4b21 (released ?????????????????)
 =======================================================================
@@ -26,6 +26,14 @@ Changes between versions 0.4b20 and 0.4b21 (released ?????????????????)
        messages.  Thanks to Andreas Dilger <adilger@turbolinux.com> 
        for the patch.
 
+6.     Use libext2fs's inode scanning routines, which are particularly
+       robust when dealing with errors (especially when having some
+       bad blocks on the filesystem). Many thanks to Colin
+       <colin@horizon.com> for reporting the bug, investigating
+       the issues, finding a workaround, writing the patch and
+       fully testing it... (of course, if this patch will break
+       anything, he is to blame for :-)).
+
 Changes between versions 0.4b19 and 0.4b20 (released November 10, 2000)
 =======================================================================
 
index 0db752c24dcb931c49b4d0cfdb56bf7ed6420c5b..c83293b39e94bb45b64a6f0f7348e2e5c9162ef5 100644 (file)
@@ -5,7 +5,7 @@
  *     Stelian Pop <pop@noos.fr>, 1999-2000
  *     Stelian Pop <pop@noos.fr> - AlcĂ´ve <www.alcove.fr>, 2000
  *
- *     $Id: dump.h,v 1.17 2000/12/05 16:31:36 stelian Exp $
+ *     $Id: dump.h,v 1.18 2000/12/05 16:57:38 stelian Exp $
  */
 
 /*-
@@ -123,7 +123,7 @@ time_t      unctime __P((const char *str));
 
 /* mapping rouintes */
 struct dinode;
-long   blockest __P((struct dinode *dp));
+long   blockest __P((struct dinode const *dp));
 int    mapfiles __P((ino_t maxino, long *tapesize));
 #ifdef __linux__
 int    mapfilesfromdir __P((ino_t maxino, long *tapesize, char *directory));
index a49434bdd50943ab9ee95353933132c4308fe9de..69cf6a2a56f0aad024a528a97d3e52a9d97c291c 100644 (file)
@@ -41,7 +41,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: traverse.c,v 1.23 2000/12/04 15:43:16 stelian Exp $";
+       "$Id: traverse.c,v 1.24 2000/12/05 16:57:38 stelian Exp $";
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -103,7 +103,7 @@ 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       0x0004 */
@@ -146,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;
 
@@ -223,20 +223,21 @@ exclude_ino(ino_t ino)
         (!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__
@@ -274,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)
 {
@@ -290,6 +336,7 @@ mapfiles(ino_t maxino, long *tapesize)
        SETINO(ROOTINO, dumpinomap);
        return (anydirskipped);
 }
+#endif /* __linux__ */
 
 #ifdef __linux__
 struct mapfile_context {
@@ -300,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;
@@ -308,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) &&
@@ -356,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);
                }
        }
        /*
@@ -367,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;
@@ -382,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.
@@ -1097,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__ */