]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
dir_iterate.c (ext2fs_dir_iterate2, ext2fs_process_dir_block):
authorTheodore Ts'o <tytso@mit.edu>
Thu, 3 Jan 2002 08:29:19 +0000 (03:29 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 3 Jan 2002 08:29:19 +0000 (03:29 -0500)
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.

12 files changed:
lib/ext2fs/ChangeLog
lib/ext2fs/Makefile.in
lib/ext2fs/alloc.c
lib/ext2fs/alloc_stats.c [new file with mode: 0644]
lib/ext2fs/bb_inode.c
lib/ext2fs/dblist_dir.c
lib/ext2fs/dir_iterate.c
lib/ext2fs/expanddir.c
lib/ext2fs/ext2fs.h
lib/ext2fs/ext2fsP.h
lib/ext2fs/mkdir.c
lib/ext2fs/mkjournal.c

index 05dbd9a8e1905d21231d9afeb3d25c90f20385fc..0319a715d92c7fd4f3d9c85105018adad16b1a25 100644 (file)
@@ -1,3 +1,25 @@
+2002-01-03  Theodore Tso  <tytso@valinux.com>
+
+       * 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.
+
 2001-12-24  Theodore Tso  <tytso@valinux.com>
 
        * ismounted.c (is_swap_device): New function used by
index bb048137cd8f313d1c701ecce2d4fb867ebf69df..98a8b9c4b3faeb8c6b0aca055849eb8c23116f5b 100644 (file)
@@ -17,6 +17,7 @@ INSTALL = @INSTALL@
 OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) \
        ext2_err.o \
        alloc.o \
+       alloc_stats.o \
        alloc_tables.o \
        badblocks.o \
        bb_inode.o \
@@ -62,6 +63,7 @@ OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) \
 
 SRCS= ext2_err.c \
        $(srcdir)/alloc.c \
+       $(srcdir)/alloc_stats.c \
        $(srcdir)/alloc_tables.c \
        $(srcdir)/badblocks.c \
        $(srcdir)/bb_compat.c \
index 2de05bcaacc865c6d3082c5811347572bfbb1bc2..2dc4fc7dbf2b8b40449d1617c582a0dc9b3e7066 100644 (file)
@@ -107,7 +107,6 @@ errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
 {
        errcode_t       retval;
        blk_t           block;
-       int             group;
        char            *buf = 0;
 
        if (!block_buf) {
@@ -132,12 +131,7 @@ errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
        if (retval)
                goto fail;
        
-       fs->super->s_free_blocks_count--;
-       group = ext2fs_group_of_blk(fs, block);
-       fs->group_desc[group].bg_free_blocks_count--;
-       ext2fs_mark_block_bitmap(fs->block_map, block);
-       ext2fs_mark_super_dirty(fs);
-       ext2fs_mark_bb_dirty(fs);
+       ext2fs_block_alloc_stats(fs, block, +1);
        *ret = block;
        return 0;
 
diff --git a/lib/ext2fs/alloc_stats.c b/lib/ext2fs/alloc_stats.c
new file mode 100644 (file)
index 0000000..986f459
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * alloc_stats.c --- Update allocation statistics for ext2fs
+ *
+ * Copyright (C) 2001 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ * 
+ */
+
+#include <stdio.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse)
+{
+       int     group = ext2fs_group_of_ino(fs, ino);
+
+       if (inuse > 0)
+               ext2fs_mark_inode_bitmap(fs->inode_map, ino);
+       else
+               ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
+       fs->group_desc[group].bg_free_inodes_count -= inuse;
+       fs->super->s_free_inodes_count -= inuse;
+       ext2fs_mark_super_dirty(fs);
+       ext2fs_mark_ib_dirty(fs);
+}
+
+void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse)
+{
+       int     group = ext2fs_group_of_blk(fs, blk);
+
+       if (inuse > 0)
+               ext2fs_mark_block_bitmap(fs->block_map, blk);
+       else
+               ext2fs_unmark_block_bitmap(fs->block_map, blk);
+       fs->group_desc[group].bg_free_blocks_count -= inuse;
+       fs->super->s_free_blocks_count -= inuse;
+       ext2fs_mark_super_dirty(fs);
+       ext2fs_mark_bb_dirty(fs);
+}
index 34c49552f19fd867bebd8bd09bca2bc586dd1700..4c575cf8d34701f4c678fa03edfada0a7d33f303 100644 (file)
@@ -59,7 +59,6 @@ errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list)
        errcode_t                       retval;
        struct set_badblock_record      rec;
        struct ext2_inode               inode;
-       blk_t                           blk;
        
        EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 
@@ -101,16 +100,6 @@ errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list)
         * block inode (!).
         */
        if (bb_list) {
-               retval = ext2fs_badblocks_list_iterate_begin(bb_list,
-                                                            &rec.bb_iter);
-               if (retval)
-                       goto cleanup;
-               while (ext2fs_badblocks_list_iterate(rec.bb_iter, &blk)) {
-                       ext2fs_mark_block_bitmap(fs->block_map, blk); 
-               }
-               ext2fs_badblocks_list_iterate_end(rec.bb_iter);
-               ext2fs_mark_bb_dirty(fs);
-               
                retval = ext2fs_badblocks_list_iterate_begin(bb_list,
                                                             &rec.bb_iter);
                if (retval)
@@ -168,7 +157,6 @@ static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
        struct set_badblock_record *rec = (struct set_badblock_record *)
                priv_data;
        errcode_t       retval;
-       int             group;
        unsigned long   old_size;
 
        if (!*block_nr)
@@ -202,12 +190,7 @@ static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
        /*
         * Mark the block as unused, and update accounting information
         */
-       ext2fs_unmark_block_bitmap(fs->block_map, *block_nr);
-       ext2fs_mark_bb_dirty(fs);
-       group = ext2fs_group_of_blk(fs, *block_nr);
-       fs->group_desc[group].bg_free_blocks_count++;
-       fs->super->s_free_blocks_count++;
-       ext2fs_mark_super_dirty(fs);
+       ext2fs_block_alloc_stats(fs, *block_nr, -1);
        
        *block_nr = 0;
        return BLOCK_CHANGED;
@@ -230,7 +213,6 @@ static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
                priv_data;
        errcode_t       retval;
        blk_t           blk;
-       int             group;
 
        if (blockcnt >= 0) {
                /*
@@ -264,17 +246,12 @@ static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
                        rec->err = retval;
                        return BLOCK_ABORT;
                }
-               ext2fs_mark_block_bitmap(fs->block_map, blk); 
-               ext2fs_mark_bb_dirty(fs);
        }
        
        /*
         * Update block counts
         */
-       group = ext2fs_group_of_blk(fs, blk);
-       fs->group_desc[group].bg_free_blocks_count--;
-       fs->super->s_free_blocks_count--;
-       ext2fs_mark_super_dirty(fs);
+       ext2fs_block_alloc_stats(fs, blk, +1);
        
        *block_nr = blk;
        return BLOCK_CHANGED;
index c4ea584f29ce42562346c548dbb7288bbdc2b7b9..f0e4a26f0379fa6a9cd2dca69a89a064ac5d3d48 100644 (file)
@@ -50,8 +50,7 @@ errcode_t ext2fs_dblist_dir_iterate(ext2_dblist dblist,
                if (retval)
                        return retval;
        }
-       ctx.func = 0;
-       ctx.func2 = func;
+       ctx.func = func;
        ctx.priv_data = priv_data;
        ctx.errcode = 0;
 
index ae97d82001943a7ec665040ff151aeaaa59c9040..35fae0736df78b841f5a0ba314e5ff81f018c71a 100644 (file)
 #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;
        }
 
index 112dedc2c566767ed008b417f58a78cf28863b63..efc2b22e36c51ca70b45bb5c9a9acef788eb0221 100644 (file)
@@ -36,7 +36,6 @@ static int expand_dir_proc(ext2_filsys                fs,
        static blk_t    last_blk = 0;
        char            *block;
        errcode_t       retval;
-       int             group;
        
        if (*blocknr) {
                last_blk = *blocknr;
@@ -70,12 +69,7 @@ static int expand_dir_proc(ext2_filsys               fs,
        }
        ext2fs_free_mem((void **) &block);
        *blocknr = new_blk;
-       ext2fs_mark_block_bitmap(fs->block_map, new_blk);
-       ext2fs_mark_bb_dirty(fs);
-       group = ext2fs_group_of_blk(fs, new_blk);
-       fs->group_desc[group].bg_free_blocks_count--;
-       fs->super->s_free_blocks_count--;
-       ext2fs_mark_super_dirty(fs);
+       ext2fs_block_alloc_stats(fs, new_blk, +1);
        es->newblocks++;
 
        if (es->done)
index 3ddd45280a6f012fc289e0ab1e792d65eb4b0a83..bfca032698e15958fa31d5dea311b509a773bf50 100644 (file)
@@ -300,11 +300,12 @@ struct struct_ext2_filsys {
  */
 
 #define DIRENT_FLAG_INCLUDE_EMPTY      1
-
+#define DIRENT_FLAG_INCLUDE_REMOVED    2
 
 #define DIRENT_DOT_FILE                1
 #define DIRENT_DOT_DOT_FILE    2
 #define DIRENT_OTHER_FILE      3
+#define DIRENT_DELETED_FILE    4
 
 /*
  * Inode scan definitions
@@ -442,6 +443,10 @@ extern errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start,
 extern errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
                                    char *block_buf, blk_t *ret);
 
+/* alloc_stats.c */
+void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse);
+void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse);
+
 /* alloc_tables.c */
 extern errcode_t ext2fs_allocate_tables(ext2_filsys fs);
 extern errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
@@ -603,6 +608,18 @@ extern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
                                          char  *buf,
                                          void  *priv_data),
                              void *priv_data);
+extern 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);
 
 /* dupfs.c */
 extern errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest);
index aedee1535b48daabd0eb37a5cc3c38e6ce63e6b4..57833546e6c4d8e43fba07ad6078c8f0871d572a 100644 (file)
@@ -48,18 +48,13 @@ struct dir_context {
        ext2_ino_t              dir;
        int             flags;
        char            *buf;
-       int (*func)(struct ext2_dir_entry *dirent,
+       int (*func)(ext2_ino_t  dir,
+                   int entry,
+                   struct ext2_dir_entry *dirent,
                    int offset,
                    int blocksize,
                    char        *buf,
                    void        *priv_data);
-       int (*func2)(ext2_ino_t dir,
-                    int        entry,
-                    struct ext2_dir_entry *dirent,
-                    int        offset,
-                    int        blocksize,
-                    char       *buf,
-                    void       *priv_data);
        void            *priv_data;
        errcode_t       errcode;
 };
index 98f0496303820a8a18513ac15d6471991a4323be..4fa711d01af87ebe2064200286069a11752b2f2a 100644 (file)
@@ -39,7 +39,6 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
        ext2_ino_t              scratch_ino;
        blk_t                   blk;
        char                    *block = 0;
-       int                     group;
 
        EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 
@@ -130,20 +129,9 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
        /*
         * Update accounting....
         */
-       ext2fs_mark_block_bitmap(fs->block_map, blk);
-       ext2fs_mark_bb_dirty(fs);
-       ext2fs_mark_inode_bitmap(fs->inode_map, ino);
-       ext2fs_mark_ib_dirty(fs);
-
-       group = ext2fs_group_of_blk(fs, blk);
-       fs->group_desc[group].bg_free_blocks_count--;
-       group = ext2fs_group_of_ino(fs, ino);
-       fs->group_desc[group].bg_free_inodes_count--;
-       fs->group_desc[group].bg_used_dirs_count++;
-       fs->super->s_free_blocks_count--;
-       fs->super->s_free_inodes_count--;
-       ext2fs_mark_super_dirty(fs);
-       
+       ext2fs_block_alloc_stats(fs, blk, +1);
+       ext2fs_inode_alloc_stats(fs, ino, +1);
+
 cleanup:
        if (block)
                ext2fs_free_mem((void **) &block);
index ae2584102367a3ace01e41ed8aabaea31fcaf2eb..eb35ba80f7992ff3a461e98dc37d7b5d19fd1d04 100644 (file)
@@ -154,7 +154,6 @@ static int mkjournal_proc(ext2_filsys               fs,
        blk_t   new_blk;
        static blk_t    last_blk = 0;
        errcode_t       retval;
-       int             group;
        
        if (*blocknr) {
                last_blk = *blocknr;
@@ -180,12 +179,7 @@ static int mkjournal_proc(ext2_filsys              fs,
        }
        *blocknr = new_blk;
        last_blk = new_blk;
-       ext2fs_mark_block_bitmap(fs->block_map, new_blk);
-       ext2fs_mark_bb_dirty(fs);
-       group = ext2fs_group_of_blk(fs, new_blk);
-       fs->group_desc[group].bg_free_blocks_count--;
-       fs->super->s_free_blocks_count--;
-       ext2fs_mark_super_dirty(fs);
+       ext2fs_block_alloc_stats(fs, new_blk, +1);
 
        if (es->num_blocks == 0)
                return (BLOCK_CHANGED | BLOCK_ABORT);