Whamcloud - gitweb
e2fsck: Fix handling of non-zero i_blocks_high field
[tools/e2fsprogs.git] / e2fsck / e2fsck.c
index 592541b..26f7b5e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * e2fsck.c - a consistency checker for the new extended file system.
- * 
+ *
  * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
  *
  * %Begin-Header%
 
 #include <errno.h>
 
-#include "et/com_err.h"
-
 #include "e2fsck.h"
 #include "problem.h"
 
 /*
- * This function allocates an e2fsck context 
+ * This function allocates an e2fsck context
  */
 errcode_t e2fsck_allocate_context(e2fsck_t *ret)
 {
        e2fsck_t        context;
+       errcode_t       retval;
+       char            *time_env;
 
-       context = malloc(sizeof(struct e2fsck_struct));
-       if (!context)
-               return ENOMEM;
+       retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
+       if (retval)
+               return retval;
 
        memset(context, 0, sizeof(struct e2fsck_struct));
 
        context->process_inode_size = 256;
+       context->ext_attr_ver = 2;
+       context->blocks_per_page = 1;
+       context->htree_slack_percentage = 255;
+
+       time_env = getenv("E2FSCK_TIME");
+       if (time_env)
+               context->now = strtoul(time_env, NULL, 0);
+       else
+               context->now = time(0);
 
        *ret = context;
        return 0;
@@ -41,6 +50,11 @@ errcode_t e2fsck_allocate_context(e2fsck_t *ret)
  */
 errcode_t e2fsck_reset_context(e2fsck_t ctx)
 {
+       int     i;
+
+       ctx->flags = 0;
+       ctx->lost_and_found = 0;
+       ctx->bad_lost_and_found = 0;
        if (ctx->inode_used_map) {
                ext2fs_free_inode_bitmap(ctx->inode_used_map);
                ctx->inode_used_map = 0;
@@ -49,6 +63,10 @@ errcode_t e2fsck_reset_context(e2fsck_t ctx)
                ext2fs_free_inode_bitmap(ctx->inode_dir_map);
                ctx->inode_dir_map = 0;
        }
+       if (ctx->inode_reg_map) {
+               ext2fs_free_inode_bitmap(ctx->inode_reg_map);
+               ctx->inode_reg_map = 0;
+       }
        if (ctx->block_found_map) {
                ext2fs_free_block_bitmap(ctx->block_found_map);
                ctx->block_found_map = 0;
@@ -57,15 +75,35 @@ errcode_t e2fsck_reset_context(e2fsck_t ctx)
                ext2fs_free_icount(ctx->inode_link_info);
                ctx->inode_link_info = 0;
        }
-       if (ctx->fs->dblist) {
+       if (ctx->journal_io) {
+               if (ctx->fs && ctx->fs->io != ctx->journal_io)
+                       io_channel_close(ctx->journal_io);
+               ctx->journal_io = 0;
+       }
+       if (ctx->fs && ctx->fs->dblist) {
                ext2fs_free_dblist(ctx->fs->dblist);
                ctx->fs->dblist = 0;
        }
-       free_dir_info(ctx->fs);
+       e2fsck_free_dir_info(ctx);
+#ifdef ENABLE_HTREE
+       e2fsck_free_dx_dir_info(ctx);
+#endif
+       if (ctx->refcount) {
+               ea_refcount_free(ctx->refcount);
+               ctx->refcount = 0;
+       }
+       if (ctx->refcount_extra) {
+               ea_refcount_free(ctx->refcount_extra);
+               ctx->refcount_extra = 0;
+       }
        if (ctx->block_dup_map) {
                ext2fs_free_block_bitmap(ctx->block_dup_map);
                ctx->block_dup_map = 0;
        }
+       if (ctx->block_ea_map) {
+               ext2fs_free_block_bitmap(ctx->block_ea_map);
+               ctx->block_ea_map = 0;
+       }
        if (ctx->inode_bb_map) {
                ext2fs_free_inode_bitmap(ctx->inode_bb_map);
                ctx->inode_bb_map = 0;
@@ -74,20 +112,28 @@ errcode_t e2fsck_reset_context(e2fsck_t ctx)
                ext2fs_free_inode_bitmap(ctx->inode_bad_map);
                ctx->inode_bad_map = 0;
        }
+       if (ctx->inode_imagic_map) {
+               ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
+               ctx->inode_imagic_map = 0;
+       }
+       if (ctx->dirs_to_hash) {
+               ext2fs_u32_list_free(ctx->dirs_to_hash);
+               ctx->dirs_to_hash = 0;
+       }
 
        /*
         * Clear the array of invalid meta-data flags
         */
        if (ctx->invalid_inode_bitmap_flag) {
-               free(ctx->invalid_inode_bitmap_flag);
+               ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
                ctx->invalid_inode_bitmap_flag = 0;
        }
        if (ctx->invalid_block_bitmap_flag) {
-               free(ctx->invalid_block_bitmap_flag);
+               ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
                ctx->invalid_block_bitmap_flag = 0;
        }
        if (ctx->invalid_inode_table_flag) {
-               free(ctx->invalid_inode_table_flag);
+               ext2fs_free_mem(&ctx->invalid_inode_table_flag);
                ctx->invalid_inode_table_flag = 0;
        }
 
@@ -107,10 +153,15 @@ errcode_t e2fsck_reset_context(e2fsck_t ctx)
        ctx->fs_dind_count = 0;
        ctx->fs_tind_count = 0;
        ctx->fs_fragmented = 0;
+       ctx->fs_fragmented_dir = 0;
+       ctx->large_files = 0;
+
+       for (i=0; i < MAX_EXTENT_DEPTH_COUNT; i++)
+               ctx->extent_depth_count[i] = 0;
 
        /* Reset the superblock to the user's requested value */
        ctx->superblock = ctx->use_superblock;
-       
+
        return 0;
 }
 
@@ -118,8 +169,58 @@ void e2fsck_free_context(e2fsck_t ctx)
 {
        if (!ctx)
                return;
-       
+
        e2fsck_reset_context(ctx);
-       
-       free(ctx);
+       if (ctx->blkid)
+               blkid_put_cache(ctx->blkid);
+
+       if (ctx->profile)
+               profile_release(ctx->profile);
+
+       if (ctx->filesystem_name)
+               ext2fs_free_mem(&ctx->filesystem_name);
+
+       if (ctx->device_name)
+               ext2fs_free_mem(&ctx->device_name);
+
+       ext2fs_free_mem(&ctx);
+}
+
+/*
+ * This function runs through the e2fsck passes and calls them all,
+ * returning restart, abort, or cancel as necessary...
+ */
+typedef void (*pass_t)(e2fsck_t ctx);
+
+pass_t e2fsck_passes[] = {
+       e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
+       e2fsck_pass5, 0 };
+
+#define E2F_FLAG_RUN_RETURN    (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
+
+int e2fsck_run(e2fsck_t ctx)
+{
+       int     i;
+       pass_t  e2fsck_pass;
+
+#ifdef HAVE_SETJMP_H
+       if (setjmp(ctx->abort_loc)) {
+               ctx->flags &= ~E2F_FLAG_SETJMP_OK;
+               return (ctx->flags & E2F_FLAG_RUN_RETURN);
+       }
+       ctx->flags |= E2F_FLAG_SETJMP_OK;
+#endif
+
+       for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
+               if (ctx->flags & E2F_FLAG_RUN_RETURN)
+                       break;
+               e2fsck_pass(ctx);
+               if (ctx->progress)
+                       (void) (ctx->progress)(ctx, 0, 0, 0);
+       }
+       ctx->flags &= ~E2F_FLAG_SETJMP_OK;
+
+       if (ctx->flags & E2F_FLAG_RUN_RETURN)
+               return (ctx->flags & E2F_FLAG_RUN_RETURN);
+       return 0;
 }