X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=dump%2Ftraverse.c;h=5833da7a4cdf8739b35d528b4ef528f74d1ac336;hb=fa7fb4174752ee1b573c537624d531a8ddddcdd9;hp=204f518de8e5b6cf712eb9913361673745eedac8;hpb=8eb05297aafdfd88bbd946a35d4db771604503bd;p=dump.git diff --git a/dump/traverse.c b/dump/traverse.c index 204f518..5833da7 100644 --- a/dump/traverse.c +++ b/dump/traverse.c @@ -2,7 +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 , 1999-2000 + * Stelian Pop - AlcĂ´ve , 2000 */ /*- @@ -40,9 +41,10 @@ #ifndef lint static const char rcsid[] = - "$Id: traverse.c,v 1.16 2000/02/10 09:42:32 stelian Exp $"; + "$Id: traverse.c,v 1.25 2000/12/21 11:14:54 stelian Exp $"; #endif /* not lint */ +#include #include #include #ifdef __linux__ @@ -84,11 +86,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 +104,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 +135,7 @@ int dump_fs_open(const char *disk, ext2_filsys *fs) retval = EXT2_ET_RO_UNSUPP_FEATURE; } } +#endif /* defined && defined && defined... */ return retval; } @@ -137,9 +147,10 @@ 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; + u_quad_t i_size; /* * dp->di_size is the size of the file in bytes. @@ -155,19 +166,20 @@ blockest(struct dinode *dp) * dump blocks (sizeest vs. blkest in the indirect block * calculation). */ - blkest = howmany(dbtob(dp->di_blocks), TP_BSIZE); - sizeest = howmany(dp->di_size, TP_BSIZE); + blkest = howmany((u_quad_t)dp->di_blocks*fs->blocksize, TP_BSIZE); + i_size = dp->di_size + ((u_quad_t) dp->di_size_high << 32); + sizeest = howmany(i_size, TP_BSIZE); if (blkest > sizeest) blkest = sizeest; #ifdef __linux__ - if (dp->di_size > fs->blocksize * NDADDR) { + if (i_size > fs->blocksize * NDADDR) { /* 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) { + if (i_size > sblock->fs_bsize * NDADDR) { /* calculate the number of indirect blocks on the dump tape */ blkest += howmany(sizeest - NDADDR * sblock->fs_bsize / TP_BSIZE, @@ -177,37 +189,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 +254,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; idxdi_flags & UF_NODUMP)) + if ( NODUMP_FLAG(dp) || exclude_ino(ino) ) CLRINO(ino, usedinomap); -#endif *dirskipped = 1; } } @@ -258,6 +278,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 +339,7 @@ mapfiles(ino_t maxino, long *tapesize) SETINO(ROOTINO, dumpinomap); return (anydirskipped); } +#endif /* __linux__ */ #ifdef __linux__ struct mapfile_context { @@ -284,7 +350,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 +358,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 +406,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 +417,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 +432,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. @@ -619,7 +685,8 @@ struct block_context { * Dump a block to the tape */ static int -dumponeblock(ext2_filsys fs, blk_t *blocknr, int blockcnt, void *private) +dumponeblock(ext2_filsys fs, blk_t *blocknr, e2_blkcnt_t blockcnt, + blk_t ref_block, int ref_offset, void * private) { struct block_context *p; int i; @@ -652,7 +719,7 @@ dumponeblock(ext2_filsys fs, blk_t *blocknr, int blockcnt, void *private) void dumpino(struct dinode *dp, ino_t ino) { - int cnt; + unsigned long cnt; fsizeT size; char buf[TP_BSIZE]; struct old_bsd_inode obi; @@ -661,6 +728,7 @@ dumpino(struct dinode *dp, ino_t ino) #else int ind_level; #endif + u_quad_t i_size = dp->di_size + ((u_quad_t) dp->di_size_high << 32); if (newtape) { newtape = 0; @@ -672,7 +740,7 @@ dumpino(struct dinode *dp, ino_t ino) obi.di_mode = dp->di_mode; obi.di_uid = dp->di_uid; obi.di_gid = dp->di_gid; - obi.di_qsize.v = (u_quad_t)dp->di_size; + obi.di_qsize.v = i_size; obi.di_atime = dp->di_atime; obi.di_mtime = dp->di_mtime; obi.di_ctime = dp->di_ctime; @@ -681,7 +749,7 @@ dumpino(struct dinode *dp, ino_t ino) obi.di_flags = dp->di_flags; obi.di_gen = dp->di_gen; memmove(&obi.di_db, &dp->di_db, (NDADDR + NIADDR) * sizeof(daddr_t)); - if (dp->di_file_acl || dp->di_dir_acl) + if (dp->di_file_acl) warn("ACLs in inode #%ld won't be dumped", (long)ino); memmove(&spcl.c_dinode, &obi, sizeof(obi)); #else /* __linux__ */ @@ -708,8 +776,8 @@ dumpino(struct dinode *dp, ino_t ino) * Check for short symbolic link. */ #ifdef __linux__ - if (dp->di_size > 0 && - dp->di_size < EXT2_N_BLOCKS * sizeof (daddr_t)) { + if (i_size > 0 && + i_size < EXT2_N_BLOCKS * sizeof (daddr_t)) { spcl.c_addr[0] = 1; spcl.c_count = 1; writeheader(ino); @@ -737,7 +805,7 @@ dumpino(struct dinode *dp, ino_t ino) case S_IFDIR: #endif case S_IFREG: - if (dp->di_size > 0) + if (i_size) break; /* fall through */ @@ -752,16 +820,16 @@ dumpino(struct dinode *dp, ino_t ino) msg("Warning: undefined file type 0%o\n", dp->di_mode & IFMT); return; } - if (dp->di_size > NDADDR * sblock->fs_bsize) + if (i_size > NDADDR * sblock->fs_bsize) #ifdef __linux__ cnt = NDADDR * EXT2_FRAGS_PER_BLOCK(fs->super); #else cnt = NDADDR * sblock->fs_frag; #endif else - cnt = howmany(dp->di_size, sblock->fs_fsize); + cnt = howmany(i_size, sblock->fs_fsize); blksout(&dp->di_db[0], cnt, ino); - if ((size = dp->di_size - NDADDR * sblock->fs_bsize) <= 0) + if ((quad_t) (size = i_size - NDADDR * sblock->fs_bsize) <= 0) return; #ifdef __linux__ bc.max = NINDIR(sblock) * EXT2_FRAGS_PER_BLOCK(fs->super); @@ -770,7 +838,7 @@ dumpino(struct dinode *dp, ino_t ino) bc.ino = ino; bc.next_block = NDADDR; - ext2fs_block_iterate (fs, ino, 0, NULL, dumponeblock, (void *)&bc); + ext2fs_block_iterate2(fs, ino, 0, NULL, dumponeblock, (void *)&bc); if (bc.cnt > 0) { blksout (bc.buf, bc.cnt, bc.ino); } @@ -890,7 +958,7 @@ dumpdirino(struct dinode *dp, ino_t ino) obi.di_flags = dp->di_flags; obi.di_gen = dp->di_gen; memmove(&obi.di_db, &dp->di_db, (NDADDR + NIADDR) * sizeof(daddr_t)); - if (dp->di_file_acl || dp->di_dir_acl) + if (dp->di_file_acl) warn("ACLs in inode #%ld won't be dumped", (long)ino); memmove(&spcl.c_dinode, &obi, sizeof(obi)); #else /* __linux__ */ @@ -1081,9 +1149,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__ */