Home | History | Annotate | Download | only in e2fsck
      1 /*
      2  * e2fsck.c - a consistency checker for the new extended file system.
      3  *
      4  * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
      5  *
      6  * %Begin-Header%
      7  * This file may be redistributed under the terms of the GNU Public
      8  * License.
      9  * %End-Header%
     10  */
     11 
     12 #include "config.h"
     13 #include <errno.h>
     14 
     15 #include "e2fsck.h"
     16 #include "problem.h"
     17 
     18 /*
     19  * This function allocates an e2fsck context
     20  */
     21 errcode_t e2fsck_allocate_context(e2fsck_t *ret)
     22 {
     23 	e2fsck_t	context;
     24 	errcode_t	retval;
     25 	char		*time_env;
     26 
     27 	retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
     28 	if (retval)
     29 		return retval;
     30 
     31 	memset(context, 0, sizeof(struct e2fsck_struct));
     32 
     33 	context->process_inode_size = 256;
     34 	context->ext_attr_ver = 2;
     35 	context->blocks_per_page = 1;
     36 	context->htree_slack_percentage = 255;
     37 
     38 	time_env = getenv("E2FSCK_TIME");
     39 	if (time_env)
     40 		context->now = strtoul(time_env, NULL, 0);
     41 	else {
     42 		context->now = time(0);
     43 		if (context->now < 1262322000) /* January 1 2010 */
     44 			context->flags |= E2F_FLAG_TIME_INSANE;
     45 	}
     46 
     47 	*ret = context;
     48 	return 0;
     49 }
     50 
     51 /*
     52  * This function resets an e2fsck context; it is called when e2fsck
     53  * needs to be restarted.
     54  */
     55 errcode_t e2fsck_reset_context(e2fsck_t ctx)
     56 {
     57 	int	i;
     58 
     59 	ctx->flags &= E2F_RESET_FLAGS;
     60 	ctx->lost_and_found = 0;
     61 	ctx->bad_lost_and_found = 0;
     62 	if (ctx->inode_used_map) {
     63 		ext2fs_free_inode_bitmap(ctx->inode_used_map);
     64 		ctx->inode_used_map = 0;
     65 	}
     66 	if (ctx->inode_dir_map) {
     67 		ext2fs_free_inode_bitmap(ctx->inode_dir_map);
     68 		ctx->inode_dir_map = 0;
     69 	}
     70 	if (ctx->inode_reg_map) {
     71 		ext2fs_free_inode_bitmap(ctx->inode_reg_map);
     72 		ctx->inode_reg_map = 0;
     73 	}
     74 	if (ctx->block_found_map) {
     75 		ext2fs_free_block_bitmap(ctx->block_found_map);
     76 		ctx->block_found_map = 0;
     77 	}
     78 	if (ctx->inode_link_info) {
     79 		ext2fs_free_icount(ctx->inode_link_info);
     80 		ctx->inode_link_info = 0;
     81 	}
     82 	if (ctx->journal_io) {
     83 		if (ctx->fs && ctx->fs->io != ctx->journal_io)
     84 			io_channel_close(ctx->journal_io);
     85 		ctx->journal_io = 0;
     86 	}
     87 	if (ctx->fs && ctx->fs->dblist) {
     88 		ext2fs_free_dblist(ctx->fs->dblist);
     89 		ctx->fs->dblist = 0;
     90 	}
     91 	e2fsck_free_dir_info(ctx);
     92 	e2fsck_free_dx_dir_info(ctx);
     93 	if (ctx->refcount) {
     94 		ea_refcount_free(ctx->refcount);
     95 		ctx->refcount = 0;
     96 	}
     97 	if (ctx->refcount_extra) {
     98 		ea_refcount_free(ctx->refcount_extra);
     99 		ctx->refcount_extra = 0;
    100 	}
    101 	if (ctx->block_dup_map) {
    102 		ext2fs_free_block_bitmap(ctx->block_dup_map);
    103 		ctx->block_dup_map = 0;
    104 	}
    105 	if (ctx->block_ea_map) {
    106 		ext2fs_free_block_bitmap(ctx->block_ea_map);
    107 		ctx->block_ea_map = 0;
    108 	}
    109 	if (ctx->block_metadata_map) {
    110 		ext2fs_free_block_bitmap(ctx->block_metadata_map);
    111 		ctx->block_metadata_map = 0;
    112 	}
    113 	if (ctx->inode_bb_map) {
    114 		ext2fs_free_inode_bitmap(ctx->inode_bb_map);
    115 		ctx->inode_bb_map = 0;
    116 	}
    117 	if (ctx->inode_bad_map) {
    118 		ext2fs_free_inode_bitmap(ctx->inode_bad_map);
    119 		ctx->inode_bad_map = 0;
    120 	}
    121 	if (ctx->inode_imagic_map) {
    122 		ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
    123 		ctx->inode_imagic_map = 0;
    124 	}
    125 	if (ctx->dirs_to_hash) {
    126 		ext2fs_u32_list_free(ctx->dirs_to_hash);
    127 		ctx->dirs_to_hash = 0;
    128 	}
    129 
    130 	/*
    131 	 * Clear the array of invalid meta-data flags
    132 	 */
    133 	if (ctx->invalid_inode_bitmap_flag) {
    134 		ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
    135 		ctx->invalid_inode_bitmap_flag = 0;
    136 	}
    137 	if (ctx->invalid_block_bitmap_flag) {
    138 		ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
    139 		ctx->invalid_block_bitmap_flag = 0;
    140 	}
    141 	if (ctx->invalid_inode_table_flag) {
    142 		ext2fs_free_mem(&ctx->invalid_inode_table_flag);
    143 		ctx->invalid_inode_table_flag = 0;
    144 	}
    145 	if (ctx->encrypted_dirs) {
    146 		ext2fs_u32_list_free(ctx->encrypted_dirs);
    147 		ctx->encrypted_dirs = 0;
    148 	}
    149 
    150 	/* Clear statistic counters */
    151 	ctx->fs_directory_count = 0;
    152 	ctx->fs_regular_count = 0;
    153 	ctx->fs_blockdev_count = 0;
    154 	ctx->fs_chardev_count = 0;
    155 	ctx->fs_links_count = 0;
    156 	ctx->fs_symlinks_count = 0;
    157 	ctx->fs_fast_symlinks_count = 0;
    158 	ctx->fs_fifo_count = 0;
    159 	ctx->fs_total_count = 0;
    160 	ctx->fs_badblocks_count = 0;
    161 	ctx->fs_sockets_count = 0;
    162 	ctx->fs_ind_count = 0;
    163 	ctx->fs_dind_count = 0;
    164 	ctx->fs_tind_count = 0;
    165 	ctx->fs_fragmented = 0;
    166 	ctx->fs_fragmented_dir = 0;
    167 	ctx->large_files = 0;
    168 
    169 	for (i=0; i < MAX_EXTENT_DEPTH_COUNT; i++)
    170 		ctx->extent_depth_count[i] = 0;
    171 
    172 	/* Reset the superblock to the user's requested value */
    173 	ctx->superblock = ctx->use_superblock;
    174 
    175 	return 0;
    176 }
    177 
    178 void e2fsck_free_context(e2fsck_t ctx)
    179 {
    180 	if (!ctx)
    181 		return;
    182 
    183 	e2fsck_reset_context(ctx);
    184 	if (ctx->blkid)
    185 		blkid_put_cache(ctx->blkid);
    186 
    187 	if (ctx->profile)
    188 		profile_release(ctx->profile);
    189 
    190 	if (ctx->filesystem_name)
    191 		ext2fs_free_mem(&ctx->filesystem_name);
    192 
    193 	if (ctx->device_name)
    194 		ext2fs_free_mem(&ctx->device_name);
    195 
    196 	if (ctx->log_fn)
    197 		free(ctx->log_fn);
    198 
    199 	ext2fs_free_mem(&ctx);
    200 }
    201 
    202 /*
    203  * This function runs through the e2fsck passes and calls them all,
    204  * returning restart, abort, or cancel as necessary...
    205  */
    206 typedef void (*pass_t)(e2fsck_t ctx);
    207 
    208 static pass_t e2fsck_passes[] = {
    209 	e2fsck_pass1, e2fsck_pass1e, e2fsck_pass2, e2fsck_pass3,
    210 	e2fsck_pass4, e2fsck_pass5, 0 };
    211 
    212 int e2fsck_run(e2fsck_t ctx)
    213 {
    214 	int	i;
    215 	pass_t	e2fsck_pass;
    216 
    217 #ifdef HAVE_SETJMP_H
    218 	if (setjmp(ctx->abort_loc)) {
    219 		ctx->flags &= ~E2F_FLAG_SETJMP_OK;
    220 		return (ctx->flags & E2F_FLAG_RUN_RETURN);
    221 	}
    222 	ctx->flags |= E2F_FLAG_SETJMP_OK;
    223 #endif
    224 
    225 	for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
    226 		if (ctx->flags & E2F_FLAG_RUN_RETURN)
    227 			break;
    228 		if (e2fsck_mmp_update(ctx->fs))
    229 			fatal_error(ctx, 0);
    230 		e2fsck_pass(ctx);
    231 		if (ctx->progress)
    232 			(void) (ctx->progress)(ctx, 0, 0, 0);
    233 	}
    234 	ctx->flags &= ~E2F_FLAG_SETJMP_OK;
    235 
    236 	if (ctx->flags & E2F_FLAG_RUN_RETURN)
    237 		return (ctx->flags & E2F_FLAG_RUN_RETURN);
    238 	return 0;
    239 }
    240