From 8bd0c95908baa3af706b9e731daff9472bec74c9 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 3 Jan 2002 03:29:19 -0500 Subject: dir_iterate.c (ext2fs_dir_iterate2, ext2fs_process_dir_block): Add support for a new flag, DIRENT_FLAG_INCLUDE_REMOVED, which will return deleted directory entries. ext2fs_dir_iterate2 takes a new callback function which is identical with the one used by ext2fs_dblist_dir_iterate(). If the directory entry is deleted, the callback function will be called with the entry paraemter set to DIRENT_DELETED_FILE. Makefile.in, alloc_stats.c (ext2fs_inode_alloc_stats, ext2fs_block_alloc_stats): New functions which update block/inode allocation statistics in the bitmaps, block group descriptors, and superblock. mkjournal.c (mkjournal_proc), mkdir.c (ext2fs_mkdir), expanddir.c (expand_dir_proc), bb_inode.c (clear_bad_block_proc, set_bad_block_proc, ext2fs_update_bb_inode), alloc.c (ext2fs_alloc_block): Update to use new block/inode allocation statistics. --- lib/ext2fs/dir_iterate.c | 124 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 102 insertions(+), 22 deletions(-) (limited to 'lib/ext2fs/dir_iterate.c') diff --git a/lib/ext2fs/dir_iterate.c b/lib/ext2fs/dir_iterate.c index ae97d820..35fae073 100644 --- a/lib/ext2fs/dir_iterate.c +++ b/lib/ext2fs/dir_iterate.c @@ -21,16 +21,41 @@ #include "ext2_fs.h" #include "ext2fsP.h" -errcode_t ext2fs_dir_iterate(ext2_filsys fs, - ext2_ino_t dir, - int flags, - char *block_buf, - int (*func)(struct ext2_dir_entry *dirent, - int offset, - int blocksize, - char *buf, - void *priv_data), - void *priv_data) +/* + * This function checks to see whether or not a potential deleted + * directory entry looks valid. What we do is check the deleted entry + * and each successive entry to make sure that they all look valid and + * that the last deleted entry ends at the beginning of the next + * undeleted entry. Returns 1 if the deleted entry looks valid, zero + * if not valid. + */ +static int ext2fs_validate_entry(char *buf, int offset, int final_offset) +{ + struct ext2_dir_entry *dirent; + + while (offset < final_offset) { + dirent = (struct ext2_dir_entry *)(buf + offset); + offset += dirent->rec_len; + if ((dirent->rec_len < 8) || + ((dirent->rec_len % 4) != 0) || + (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) + return 0; + } + return (offset == final_offset); +} + +errcode_t ext2fs_dir_iterate2(ext2_filsys fs, + ext2_ino_t dir, + int flags, + char *block_buf, + int (*func)(ext2_ino_t dir, + int entry, + struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data), + void *priv_data) { struct dir_context ctx; errcode_t retval; @@ -51,7 +76,6 @@ errcode_t ext2fs_dir_iterate(ext2_filsys fs, return retval; } ctx.func = func; - ctx.func2 = 0; ctx.priv_data = priv_data; ctx.errcode = 0; retval = ext2fs_block_iterate2(fs, dir, 0, 0, @@ -63,6 +87,45 @@ errcode_t ext2fs_dir_iterate(ext2_filsys fs, return ctx.errcode; } +struct xlate { + int (*func)(struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data); + void *real_private; +}; + +static int xlate_func(ext2_ino_t dir, int entry, + struct ext2_dir_entry *dirent, int offset, + int blocksize, char *buf, void *priv_data) +{ + struct xlate *xl = (struct xlate *) priv_data; + + return (*xl->func)(dirent, offset, blocksize, buf, xl->real_private); +} + +extern errcode_t ext2fs_dir_iterate(ext2_filsys fs, + ext2_ino_t dir, + int flags, + char *block_buf, + int (*func)(struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data), + void *priv_data) +{ + struct xlate xl; + + xl.real_private = priv_data; + xl.func = func; + + return ext2fs_dir_iterate2(fs, dir, flags, block_buf, + xlate_func, &xl); +} + + /* * Helper function which is private to this module. Used by * ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate() @@ -76,10 +139,11 @@ int ext2fs_process_dir_block(ext2_filsys fs, { struct dir_context *ctx = (struct dir_context *) priv_data; int offset = 0; + int next_real_entry = 0; int ret = 0; int changed = 0; int do_abort = 0; - int entry; + int entry, size; struct ext2_dir_entry *dirent; if (blockcnt < 0) @@ -104,16 +168,14 @@ int ext2fs_process_dir_block(ext2_filsys fs, !(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY)) goto next; - if (ctx->func) - ret = (ctx->func)(dirent, offset, fs->blocksize, - ctx->buf, ctx->priv_data); - else if (ctx->func2) { - ret = (ctx->func2)(ctx->dir, entry, dirent, offset, - fs->blocksize, ctx->buf, - ctx->priv_data); - if (entry < DIRENT_OTHER_FILE) - entry++; - } + ret = (ctx->func)(ctx->dir, + (next_real_entry > offset) ? + DIRENT_DELETED_FILE : entry, + dirent, offset, + fs->blocksize, ctx->buf, + ctx->priv_data); + if (entry < DIRENT_OTHER_FILE) + entry++; if (ret & DIRENT_CHANGED) changed++; @@ -122,6 +184,24 @@ int ext2fs_process_dir_block(ext2_filsys fs, break; } next: + if (next_real_entry == offset) + next_real_entry += dirent->rec_len; + + if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) { + size = ((dirent->name_len & 0xFF) + 11) & ~3; + + if (dirent->rec_len != size) { + int final_offset = offset + dirent->rec_len; + + offset += size; + while (offset < final_offset && + !ext2fs_validate_entry(ctx->buf, + offset, + final_offset)) + offset += 4; + continue; + } + } offset += dirent->rec_len; } -- cgit v1.2.3