119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * pass2.c --- check directory structure
33984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o
519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %Begin-Header%
719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This file may be redistributed under the terms of the GNU Public
819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * License.
919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %End-Header%
103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
1119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Pass 2 of e2fsck iterates through all active directory inodes, and
1219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * applies to following tests to each directory entry in the directory
1319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * blocks in the inodes:
1419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
1519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *	- The length of the directory entry (rec_len) should be at
1619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 		least 8 bytes, and no more than the remaining space
1719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 		left in the directory block.
1819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 	- The length of the name in the directory entry (name_len)
193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * 		should be less than (rec_len - 8).
2019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *	- The inode number in the directory entry should be within
2119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 		legal bounds.
2219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 	- The inode number should refer to a in-use inode.
2319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *	- The first entry should be '.', and its inode should be
2419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 		the inode of the directory.
2519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 	- The second entry should be '..'.
2619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
2719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * To minimize disk seek time, the directory blocks are processed in
2819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * sorted order of block numbers.
2919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
3019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Pass 2 also collects the following information:
3119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 	- The inode numbers of the subdirectories for each directory.
3219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
3319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Pass 2 relies on the following information from previous passes:
3419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 	- The directory information collected in pass 1.
3519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 	- The inode_used_map bitmap
3619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 	- The inode_bad_map bitmap
3719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 	- The inode_dir_map bitmap
3819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
3919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Pass 2 frees the following data structures
4019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 	- The inode_bad_map bitmap
4119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 	- The inode_reg_map bitmap
4219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
4319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
4419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define _GNU_SOURCE 1 /* get strnlen() */
4519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <string.h>
4619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
4719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "e2fsck.h"
4819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "problem.h"
4919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "dict.h"
5019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
5119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef NO_INLINE_FUNCS
5219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define _INLINE_
5319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#else
5419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define _INLINE_ inline
5519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
5619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
5719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* #define DX_DEBUG */
5819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
5919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
6019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Keeps track of how many times an inode is referenced.
6119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
6219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
6319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int check_dir_block(ext2_filsys fs,
6419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   struct ext2_db_entry *dir_blocks_info,
6519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   void *priv_data);
6619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int allocate_dir_block(e2fsck_t ctx,
6719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      struct ext2_db_entry *dir_blocks_info,
6819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      char *buf, struct problem_context *pctx);
6919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
7019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int htree_depth(struct dx_dir_info *dx_dir,
7119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		       struct dx_dirblock_info *dx_db);
7219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b);
7319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
7419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstruct check_dir_struct {
7519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	char *buf;
7619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct problem_context	pctx;
7719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	count, max;
7819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2fsck_t ctx;
793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt};
8019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
8119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectvoid e2fsck_pass2(e2fsck_t ctx)
8219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
8319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_super_block *sb = ctx->fs->super;
8419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct problem_context	pctx;
8519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_filsys 		fs = ctx->fs;
8619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	char			*buf;
8719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef RESOURCE_TRACK
8819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct resource_track	rtrack;
8919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
9019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct check_dir_struct cd;
9119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct dx_dir_info	*dx_dir;
9219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct dx_dirblock_info	*dx_db, *dx_parent;
9319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int			b;
9419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int			i, depth;
9519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	problem_t		code;
9619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int			bad_dir;
9719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	init_resource_track(&rtrack, ctx->fs->io);
9919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	clear_problem_context(&cd.pctx);
10019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
10119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef MTRACE
10219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	mtrace_print("Pass 2");
10319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
10419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
10519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!(ctx->options & E2F_OPT_PREEN))
10619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
10719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	e2fsck_setup_tdb_icount(ctx, EXT2_ICOUNT_OPT_INCREMENT,
10919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				&ctx->inode_count);
11019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ctx->inode_count)
11119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		cd.pctx.errcode = 0;
1123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	else
1133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		cd.pctx.errcode = ext2fs_create_icount2(fs,
11419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						EXT2_ICOUNT_OPT_INCREMENT,
11519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						0, ctx->inode_link_info,
11619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						&ctx->inode_count);
11719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (cd.pctx.errcode) {
11819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
11919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ctx->flags |= E2F_FLAG_ABORT;
12019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
12119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
12219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
12319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					      "directory scan buffer");
12419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
12519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
12619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Set up the parent pointer for the root directory, if
12719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * present.  (If the root directory is not present, we will
12819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * create it in pass 3.)
12919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
13019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	(void) e2fsck_dir_info_set_parent(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
13119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
13219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	cd.buf = buf;
13319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	cd.ctx = ctx;
13419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	cd.count = 1;
13519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	cd.max = ext2fs_dblist_count(fs->dblist);
13619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
13719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ctx->progress)
13819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		(void) (ctx->progress)(ctx, 2, 0, cd.max);
13919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
14019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
14119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
1423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
14319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
14419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						&cd);
1453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART)
14619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
1473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (ctx->flags & E2F_FLAG_RESTART_LATER) {
1493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ctx->flags |= E2F_FLAG_RESTART;
1503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
1513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
1523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
15319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (cd.pctx.errcode) {
15419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
15519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ctx->flags |= E2F_FLAG_ABORT;
15619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
15719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
15819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
15919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef ENABLE_HTREE
16019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
16119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
16219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return;
16319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (dx_dir->numblocks == 0)
16419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			continue;
16519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		clear_problem_context(&pctx);
16619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		bad_dir = 0;
16719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.dir = dx_dir->ino;
16819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dx_db = dx_dir->dx_block;
16919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (dx_db->flags & DX_FLAG_REFERENCED)
17019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dx_db->flags |= DX_FLAG_DUP_REF;
17119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		else
17219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dx_db->flags |= DX_FLAG_REFERENCED;
17319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		/*
17419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * Find all of the first and last leaf blocks, and
17519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * update their parent's min and max hash values
17619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 */
17719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		for (b=0, dx_db = dx_dir->dx_block;
17819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		     b < dx_dir->numblocks;
17919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		     b++, dx_db++) {
18019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
18119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			    !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
18219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				continue;
18319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dx_parent = &dx_dir->dx_block[dx_db->parent];
18419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			/*
18519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * XXX Make sure dx_parent->min_hash > dx_db->min_hash
18619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 */
18719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (dx_db->flags & DX_FLAG_FIRST)
18819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dx_parent->min_hash = dx_db->min_hash;
18919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			/*
19019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * XXX Make sure dx_parent->max_hash < dx_db->max_hash
19119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 */
19219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (dx_db->flags & DX_FLAG_LAST)
19319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dx_parent->max_hash = dx_db->max_hash;
19419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
1953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		for (b=0, dx_db = dx_dir->dx_block;
19719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		     b < dx_dir->numblocks;
19819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		     b++, dx_db++) {
19919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			pctx.blkcount = b;
20019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			pctx.group = dx_db->parent;
20119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			code = 0;
20219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (!(dx_db->flags & DX_FLAG_FIRST) &&
20319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			    (dx_db->min_hash < dx_db->node_min_hash)) {
20419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				pctx.blk = dx_db->min_hash;
20519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				pctx.blk2 = dx_db->node_min_hash;
20619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				code = PR_2_HTREE_MIN_HASH;
20719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				fix_problem(ctx, code, &pctx);
20819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				bad_dir++;
20919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
21019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (dx_db->type == DX_DIRBLOCK_LEAF) {
21119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				depth = htree_depth(dx_dir, dx_db);
21219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				if (depth != dx_dir->depth) {
2133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					pctx.num = dx_dir->depth;
21419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					code = PR_2_HTREE_BAD_DEPTH;
21519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					fix_problem(ctx, code, &pctx);
21619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					bad_dir++;
21719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				}
21819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
21919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			/*
2203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			 * This test doesn't apply for the root block
22119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * at block #0
22219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 */
22319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (b &&
22419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			    (dx_db->max_hash > dx_db->node_max_hash)) {
22519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				pctx.blk = dx_db->max_hash;
22619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				pctx.blk2 = dx_db->node_max_hash;
22719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				code = PR_2_HTREE_MAX_HASH;
22819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				fix_problem(ctx, code, &pctx);
22919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				bad_dir++;
23019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
23119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
23219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				code = PR_2_HTREE_NOTREF;
23319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				fix_problem(ctx, code, &pctx);
23419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				bad_dir++;
23519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			} else if (dx_db->flags & DX_FLAG_DUP_REF) {
23619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				code = PR_2_HTREE_DUPREF;
23719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				fix_problem(ctx, code, &pctx);
23819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				bad_dir++;
23919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
24019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
24119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
24219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			clear_htree(ctx, dx_dir->ino);
24319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dx_dir->numblocks = 0;
24419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
24519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
2463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	e2fsck_free_dx_dir_info(ctx);
24719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
24819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_free_mem(&buf);
24919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_free_dblist(fs->dblist);
25019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
25119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ctx->inode_bad_map) {
25219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_free_inode_bitmap(ctx->inode_bad_map);
25319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ctx->inode_bad_map = 0;
25419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
25519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ctx->inode_reg_map) {
25619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_free_inode_bitmap(ctx->inode_reg_map);
25719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ctx->inode_reg_map = 0;
25819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
25919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
26019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	clear_problem_context(&pctx);
26119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ctx->large_files) {
26219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (!(sb->s_feature_ro_compat &
26319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		      EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
26419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
26519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			sb->s_feature_ro_compat |=
26619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
26719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
26819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ext2fs_mark_super_dirty(fs);
26919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
27019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
27119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
27219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ext2fs_update_dynamic_rev(fs);
27319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ext2fs_mark_super_dirty(fs);
27419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
27519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
2763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	print_resource_track(ctx, _("Pass 2"), &rtrack, fs->io);
27819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
27919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
28019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define MAX_DEPTH 32000
28119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int htree_depth(struct dx_dir_info *dx_dir,
28219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		       struct dx_dirblock_info *dx_db)
28319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
28419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	depth = 0;
28519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
28619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
28719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dx_db = &dx_dir->dx_block[dx_db->parent];
28819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		depth++;
28919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
29019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return depth;
29119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
29219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
29319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int dict_de_cmp(const void *a, const void *b)
29419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
29519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	const struct ext2_dir_entry *de_a, *de_b;
29619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	a_len, b_len;
29719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
29819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	de_a = (const struct ext2_dir_entry *) a;
29919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	a_len = de_a->name_len & 0xFF;
30019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	de_b = (const struct ext2_dir_entry *) b;
30119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	b_len = de_b->name_len & 0xFF;
30219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
30319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (a_len != b_len)
30419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return (a_len - b_len);
30519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
30619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return strncmp(de_a->name, de_b->name, a_len);
30719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
30819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
30919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
31019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This is special sort function that makes sure that directory blocks
31119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * with a dirblock of zero are sorted to the beginning of the list.
31219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This guarantees that the root node of the htree directories are
31319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * processed first, so we know what hash version to use.
31419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
31519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b)
31619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
31719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	const struct ext2_db_entry *db_a =
31819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		(const struct ext2_db_entry *) a;
31919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	const struct ext2_db_entry *db_b =
32019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		(const struct ext2_db_entry *) b;
32119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
32219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (db_a->blockcnt && !db_b->blockcnt)
32319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 1;
32419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
32519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!db_a->blockcnt && db_b->blockcnt)
32619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return -1;
3273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
32819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (db_a->blk != db_b->blk)
32919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return (int) (db_a->blk - db_b->blk);
3303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
33119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (db_a->ino != db_b->ino)
33219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return (int) (db_a->ino - db_b->ino);
33319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
33419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return (int) (db_a->blockcnt - db_b->blockcnt);
33519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
33619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
33719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
33819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
33919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Make sure the first entry in the directory is '.', and that the
34019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * directory entry is sane.
34119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
34219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int check_dot(e2fsck_t ctx,
34319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		     struct ext2_dir_entry *dirent,
34419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		     ext2_ino_t ino, struct problem_context *pctx)
34519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
34619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_dir_entry *nextdir;
3473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	unsigned int	rec_len, new_len;
34819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	status = 0;
34919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	created = 0;
35019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	problem = 0;
3513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
35219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!dirent->inode)
35319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		problem = PR_2_MISSING_DOT;
35419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else if (((dirent->name_len & 0xFF) != 1) ||
35519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 (dirent->name[0] != '.'))
35619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		problem = PR_2_1ST_NOT_DOT;
35719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else if (dirent->name[1] != '\0')
35819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		problem = PR_2_DOT_NULL_TERM;
3593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
3603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	(void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len);
36119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (problem) {
36219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fix_problem(ctx, problem, pctx)) {
3633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (rec_len < 12)
3643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				rec_len = dirent->rec_len = 12;
36519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dirent->inode = ino;
36619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dirent->name_len = 1;
36719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dirent->name[0] = '.';
36819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dirent->name[1] = '\0';
36919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			status = 1;
37019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			created = 1;
37119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
37219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
37319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (dirent->inode != ino) {
37419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
37519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dirent->inode = ino;
37619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			status = 1;
37719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
37819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
3793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (rec_len > 12) {
3803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		new_len = rec_len - 12;
38119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (new_len > 12) {
38219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (created ||
38319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			    fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
38419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				nextdir = (struct ext2_dir_entry *)
38519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					((char *) dirent + 12);
38619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dirent->rec_len = 12;
3873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				(void) ext2fs_set_rec_len(ctx->fs, new_len,
3883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt							  nextdir);
38919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				nextdir->inode = 0;
39019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				nextdir->name_len = 0;
39119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				status = 1;
39219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
39319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
39419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
39519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return status;
39619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
39719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
39819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
39919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Make sure the second entry in the directory is '..', and that the
40019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * directory entry is sane.  We do not check the inode number of '..'
40119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * here; this gets done in pass 3.
40219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
40319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int check_dotdot(e2fsck_t ctx,
40419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			struct ext2_dir_entry *dirent,
40519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ext2_ino_t ino, struct problem_context *pctx)
40619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
4073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int	rec_len, problem = 0;
4083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
40919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!dirent->inode)
41019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		problem = PR_2_MISSING_DOT_DOT;
41119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else if (((dirent->name_len & 0xFF) != 2) ||
41219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 (dirent->name[0] != '.') ||
41319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 (dirent->name[1] != '.'))
41419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		problem = PR_2_2ND_NOT_DOT_DOT;
41519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else if (dirent->name[2] != '\0')
41619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		problem = PR_2_DOT_DOT_NULL_TERM;
41719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
4183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	(void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len);
41919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (problem) {
42019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fix_problem(ctx, problem, pctx)) {
4213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (rec_len < 12)
42219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dirent->rec_len = 12;
42319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			/*
42419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * Note: we don't have the parent inode just
42519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * yet, so we will fill it in with the root
42619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * inode.  This will get fixed in pass 3.
42719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 */
42819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dirent->inode = EXT2_ROOT_INO;
42919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dirent->name_len = 2;
43019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dirent->name[0] = '.';
43119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dirent->name[1] = '.';
43219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dirent->name[2] = '\0';
43319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return 1;
4343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
43519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 0;
43619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
43719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (e2fsck_dir_info_set_dotdot(ctx, ino, dirent->inode)) {
43819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fix_problem(ctx, PR_2_NO_DIRINFO, pctx);
43919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return -1;
44019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
44119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 0;
44219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
44319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
44419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
44519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Check to make sure a directory entry doesn't contain any illegal
44619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * characters.
44719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
44819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int check_name(e2fsck_t ctx,
44919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		      struct ext2_dir_entry *dirent,
4503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		      ext2_ino_t dir_ino EXT2FS_ATTR((unused)),
45119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		      struct problem_context *pctx)
45219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
45319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	i;
45419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	fixup = -1;
45519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	ret = 0;
4563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
45719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
45819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
45919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (fixup < 0) {
46019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
46119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
46219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (fixup) {
46319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dirent->name[i] = '.';
46419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				ret = 1;
46519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
46619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
46719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
46819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return ret;
46919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
47019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
47119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
47219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Check the directory filetype (if present)
47319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
47419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic _INLINE_ int check_filetype(e2fsck_t ctx,
47519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				   struct ext2_dir_entry *dirent,
47619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				   ext2_ino_t dir_ino EXT2FS_ATTR((unused)),
47719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				   struct problem_context *pctx)
47819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
47919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	filetype = dirent->name_len >> 8;
48019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	should_be = EXT2_FT_UNKNOWN;
48119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_inode	inode;
48219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
48319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!(ctx->fs->super->s_feature_incompat &
48419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	      EXT2_FEATURE_INCOMPAT_FILETYPE)) {
48519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (filetype == 0 ||
48619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
48719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return 0;
48819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dirent->name_len = dirent->name_len & 0xFF;
48919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 1;
49019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
49119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
49219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
49319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		should_be = EXT2_FT_DIR;
49419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	} else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
49519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					    dirent->inode)) {
49619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		should_be = EXT2_FT_REG_FILE;
49719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	} else if (ctx->inode_bad_map &&
49819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		   ext2fs_test_inode_bitmap(ctx->inode_bad_map,
49919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					    dirent->inode))
50019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		should_be = 0;
50119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else {
50219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		e2fsck_read_inode(ctx, dirent->inode, &inode,
50319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				  "check_filetype");
50419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		should_be = ext2_file_type(inode.i_mode);
50519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
50619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (filetype == should_be)
50719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 0;
50819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pctx->num = should_be;
50919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
51019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
51119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			pctx) == 0)
51219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 0;
5133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
51419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
51519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 1;
51619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
51719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
51819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef ENABLE_HTREE
51919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void parse_int_node(ext2_filsys fs,
52019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   struct ext2_db_entry *db,
52119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   struct check_dir_struct *cd,
52219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   struct dx_dir_info	*dx_dir,
52319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   char *block_buf)
52419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
52519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct 		ext2_dx_root_info  *root;
52619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct 		ext2_dx_entry *ent;
52719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct		ext2_dx_countlimit *limit;
52819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct dx_dirblock_info	*dx_db;
52919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int		i, expect_limit, count;
53019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t		blk;
53119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_dirhash_t	min_hash = 0xffffffff;
53219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_dirhash_t	max_hash = 0;
53319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_dirhash_t	hash = 0, prev_hash;
53419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
53519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (db->blockcnt == 0) {
53619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		root = (struct ext2_dx_root_info *) (block_buf + 24);
5373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
53819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef DX_DEBUG
53919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		printf("Root node dump:\n");
54019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		printf("\t Reserved zero: %u\n", root->reserved_zero);
54119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		printf("\t Hash Version: %d\n", root->hash_version);
54219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		printf("\t Info length: %d\n", root->info_length);
54319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		printf("\t Indirect levels: %d\n", root->indirect_levels);
54419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		printf("\t Flags: %d\n", root->unused_flags);
54519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
54619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
54719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
54819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	} else {
54919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ent = (struct ext2_dx_entry *) (block_buf+8);
55019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
55119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	limit = (struct ext2_dx_countlimit *) ent;
55219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
55319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef DX_DEBUG
5543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	printf("Number of entries (count): %d\n",
55519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	       ext2fs_le16_to_cpu(limit->count));
5563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	printf("Number of entries (limit): %d\n",
55719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	       ext2fs_le16_to_cpu(limit->limit));
55819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
55919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
56019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	count = ext2fs_le16_to_cpu(limit->count);
56119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
56219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		sizeof(struct ext2_dx_entry);
56319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
56419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
56519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
56619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto clear_and_exit;
56719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
56819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (count > expect_limit) {
56919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		cd->pctx.num = count;
57019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
57119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto clear_and_exit;
57219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		count = expect_limit;
57319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
5743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
57519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	for (i=0; i < count; i++) {
57619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		prev_hash = hash;
57719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
57819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef DX_DEBUG
57919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		printf("Entry #%d: Hash 0x%08x, block %u\n", i,
58019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		       hash, ext2fs_le32_to_cpu(ent[i].block));
58119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
58219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
58319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		/* Check to make sure the block is valid */
58419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (blk >= (blk_t) dx_dir->numblocks) {
58519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			cd->pctx.blk = blk;
58619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
58719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					&cd->pctx))
58819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				goto clear_and_exit;
58919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			continue;
59019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
59119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (hash < prev_hash &&
59219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
59319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto clear_and_exit;
59419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dx_db = &dx_dir->dx_block[blk];
59519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (dx_db->flags & DX_FLAG_REFERENCED) {
59619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dx_db->flags |= DX_FLAG_DUP_REF;
59719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else {
59819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dx_db->flags |= DX_FLAG_REFERENCED;
59919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dx_db->parent = db->blockcnt;
60019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
60119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (hash < min_hash)
60219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			min_hash = hash;
60319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (hash > max_hash)
60419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			max_hash = hash;
60519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dx_db->node_min_hash = hash;
60619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if ((i+1) < count)
6073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			dx_db->node_max_hash =
60819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
60919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		else {
61019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dx_db->node_max_hash = 0xfffffffe;
61119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dx_db->flags |= DX_FLAG_LAST;
61219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
61319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (i == 0)
61419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dx_db->flags |= DX_FLAG_FIRST;
61519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
61619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef DX_DEBUG
61719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	printf("Blockcnt = %d, min hash 0x%08x, max hash 0x%08x\n",
61819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	       db->blockcnt, min_hash, max_hash);
61919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
62019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	dx_db = &dx_dir->dx_block[db->blockcnt];
62119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	dx_db->min_hash = min_hash;
62219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	dx_db->max_hash = max_hash;
62319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return;
62419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
62519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectclear_and_exit:
62619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	clear_htree(cd->ctx, cd->pctx.ino);
62719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	dx_dir->numblocks = 0;
62819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
62919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif /* ENABLE_HTREE */
63019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
63119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
63219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Given a busted directory, try to salvage it somehow.
6333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
63419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
63519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void salvage_directory(ext2_filsys fs,
63619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      struct ext2_dir_entry *dirent,
63719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      struct ext2_dir_entry *prev,
63819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      unsigned int *offset)
63919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
64019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	char	*cp = (char *) dirent;
6413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int left;
6423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	unsigned int rec_len, prev_rec_len;
64319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	unsigned int name_len = dirent->name_len & 0xFF;
64419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
6453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	(void) ext2fs_get_rec_len(fs, dirent, &rec_len);
6463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	left = fs->blocksize - *offset - rec_len;
6473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
64819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
64919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Special case of directory entry of size 8: copy what's left
65019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * of the directory block up to cover up the invalid hole.
65119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
6523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if ((left >= 12) && (rec_len == 8)) {
65319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		memmove(cp, cp+8, left);
65419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		memset(cp + left, 0, 8);
65519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
65619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
65719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
65819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * If the directory entry overruns the end of the directory
65919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * block, and the name is small enough to fit, then adjust the
66019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * record length.
66119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
66219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if ((left < 0) &&
6633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    ((int) rec_len + left > 8) &&
6643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    (name_len + 8 <= (int) rec_len + left) &&
66519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    dirent->inode <= fs->super->s_inodes_count &&
66619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    strnlen(dirent->name, name_len) == name_len) {
6673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		(void) ext2fs_set_rec_len(fs, (int) rec_len + left, dirent);
66819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
66919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
67019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
67119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * If the record length of the directory entry is a multiple
67219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * of four, and not too big, such that it is valid, let the
67319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * previous directory entry absorb the invalid one.
67419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
6753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (prev && rec_len && (rec_len % 4) == 0 &&
6763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    (*offset + rec_len <= fs->blocksize)) {
6773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		(void) ext2fs_get_rec_len(fs, prev, &prev_rec_len);
6783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		prev_rec_len += rec_len;
6793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		(void) ext2fs_set_rec_len(fs, prev_rec_len, prev);
6803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		*offset += rec_len;
68119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
68219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
68319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
68419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Default salvage method --- kill all of the directory
68519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * entries for the rest of the block.  We will either try to
68619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * absorb it into the previous directory entry, or create a
68719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * new empty directory entry the rest of the directory block.
68819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
68919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (prev) {
6903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		(void) ext2fs_get_rec_len(fs, prev, &prev_rec_len);
6913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		prev_rec_len += fs->blocksize - *offset;
6923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		(void) ext2fs_set_rec_len(fs, prev_rec_len, prev);
69319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		*offset = fs->blocksize;
69419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	} else {
6953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		rec_len = fs->blocksize - *offset;
6963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		(void) ext2fs_set_rec_len(fs, rec_len, dirent);
69719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dirent->name_len = 0;
69819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dirent->inode = 0;
69919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
70019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
70119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
70219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int check_dir_block(ext2_filsys fs,
70319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   struct ext2_db_entry *db,
70419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   void *priv_data)
70519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
70619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 	struct dx_dir_info	*dx_dir;
70719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef ENABLE_HTREE
70819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct dx_dirblock_info	*dx_db = 0;
70919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif /* ENABLE_HTREE */
71019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_dir_entry 	*dirent, *prev;
71119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_dirhash_t		hash;
71219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	unsigned int		offset = 0;
71319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	const char *		old_op;
71419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int			dir_modified = 0;
71519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int			dot_state;
7163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	unsigned int		rec_len;
71719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t			block_nr = db->blk;
71819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_ino_t 		ino = db->ino;
71919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_ino_t 		subdir_parent;
72019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	__u16			links;
72119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct check_dir_struct	*cd;
72219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	char 			*buf;
72319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2fsck_t		ctx;
72419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int			problem;
72519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_dx_root_info *root;
72619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_dx_countlimit *limit;
72719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	static dict_t de_dict;
72819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct problem_context	pctx;
72919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	dups_found = 0;
73019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	ret;
73119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
73219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	cd = (struct check_dir_struct *) priv_data;
73319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	buf = cd->buf;
73419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ctx = cd->ctx;
73519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
7363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART)
73719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return DIRENT_ABORT;
7383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
73919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
74019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return DIRENT_ABORT;
7413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
74219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
7433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * Make sure the inode is still in use (could have been
74419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * deleted in the duplicate/bad blocks pass.
74519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
7463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
74719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 0;
74819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
74919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	cd->pctx.ino = ino;
75019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	cd->pctx.blk = block_nr;
75119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	cd->pctx.blkcount = db->blockcnt;
75219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	cd->pctx.ino2 = 0;
75319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	cd->pctx.dirent = 0;
75419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	cd->pctx.num = 0;
75519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
75619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (db->blk == 0) {
75719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (allocate_dir_block(ctx, db, buf, &cd->pctx))
75819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return 0;
75919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		block_nr = db->blk;
76019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
7613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
76219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (db->blockcnt)
76319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dot_state = 2;
76419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else
76519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dot_state = 0;
76619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
76719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ctx->dirs_to_hash &&
76819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
76919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dups_found++;
77019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
77119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if 0
77219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	printf("In process_dir_block block %lu, #%d, inode %lu\n", block_nr,
77319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	       db->blockcnt, ino);
77419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
7753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
77619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	old_op = ehandler_operation(_("reading directory block"));
77719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
77819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ehandler_operation(0);
77919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
78019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		cd->pctx.errcode = 0; /* We'll handle this ourselves */
78119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (cd->pctx.errcode) {
78219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
78319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ctx->flags |= E2F_FLAG_ABORT;
78419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return DIRENT_ABORT;
78519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
78619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		memset(buf, 0, fs->blocksize);
78719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
78819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef ENABLE_HTREE
78919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
79019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (dx_dir && dx_dir->numblocks) {
79119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (db->blockcnt >= dx_dir->numblocks) {
7923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (fix_problem(ctx, PR_2_UNEXPECTED_HTREE_BLOCK,
79319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					&pctx)) {
79419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				clear_htree(ctx, ino);
79519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dx_dir->numblocks = 0;
79619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dx_db = 0;
79719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				goto out_htree;
79819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
79919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fatal_error(ctx, _("Can not continue."));
80019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
80119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dx_db = &dx_dir->dx_block[db->blockcnt];
80219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dx_db->type = DX_DIRBLOCK_LEAF;
80319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dx_db->phys = block_nr;
80419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dx_db->min_hash = ~0;
80519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dx_db->max_hash = 0;
8063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
80719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dirent = (struct ext2_dir_entry *) buf;
8083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		(void) ext2fs_get_rec_len(fs, dirent, &rec_len);
80919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		limit = (struct ext2_dx_countlimit *) (buf+8);
81019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (db->blockcnt == 0) {
81119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			root = (struct ext2_dx_root_info *) (buf + 24);
81219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dx_db->type = DX_DIRBLOCK_ROOT;
81319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
81419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if ((root->reserved_zero ||
81519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     root->info_length < 8 ||
81619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     root->indirect_levels > 1) &&
81719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			    fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
81819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				clear_htree(ctx, ino);
81919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dx_dir->numblocks = 0;
82019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dx_db = 0;
82119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
82219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dx_dir->hashversion = root->hash_version;
82319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if ((dx_dir->hashversion <= EXT2_HASH_TEA) &&
82419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			    (fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH))
82519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dx_dir->hashversion += 3;
82619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dx_dir->depth = root->indirect_levels + 1;
82719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else if ((dirent->inode == 0) &&
8283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			   (rec_len == fs->blocksize) &&
82919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   (dirent->name_len == 0) &&
8303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			   (ext2fs_le16_to_cpu(limit->limit) ==
8313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			    ((fs->blocksize-8) /
83219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     sizeof(struct ext2_dx_entry))))
83319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dx_db->type = DX_DIRBLOCK_NODE;
83419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
83519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectout_htree:
83619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif /* ENABLE_HTREE */
83719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
83819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
83919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	prev = 0;
84019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	do {
8413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		int group;
8423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ext2_ino_t first_unused_inode;
8433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
84419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		problem = 0;
84519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dirent = (struct ext2_dir_entry *) (buf + offset);
8463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		(void) ext2fs_get_rec_len(fs, dirent, &rec_len);
84719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		cd->pctx.dirent = dirent;
84819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		cd->pctx.num = offset;
8493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (((offset + rec_len) > fs->blocksize) ||
8503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    (rec_len < 12) ||
8513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    ((rec_len % 4) != 0) ||
8523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    (((dirent->name_len & (unsigned) 0xFF)+8) > rec_len)) {
85319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
85419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				salvage_directory(fs, dirent, prev, &offset);
85519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dir_modified++;
85619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				continue;
85719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			} else
85819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				goto abort_free_dict;
85919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
86019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
86119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
86219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dirent->name_len = EXT2_NAME_LEN;
86319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dir_modified++;
86419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
86519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
86619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
86719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (dot_state == 0) {
86819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (check_dot(ctx, dirent, ino, &cd->pctx))
86919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dir_modified++;
87019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else if (dot_state == 1) {
87119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ret = check_dotdot(ctx, dirent, ino, &cd->pctx);
87219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (ret < 0)
87319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				goto abort_free_dict;
87419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (ret)
87519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dir_modified++;
87619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else if (dirent->inode == ino) {
87719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			problem = PR_2_LINK_DOT;
87819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
87919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dirent->inode = 0;
88019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dir_modified++;
88119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				goto next;
88219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
88319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
8843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (!dirent->inode)
88519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto next;
8863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
88719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		/*
88819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * Make sure the inode listed is a legal one.
8893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		 */
89019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (((dirent->inode != EXT2_ROOT_INO) &&
89119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		     (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
89219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    (dirent->inode > fs->super->s_inodes_count)) {
89319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			problem = PR_2_BAD_INO;
89419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else if (ctx->inode_bb_map &&
89519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   (ext2fs_test_inode_bitmap(ctx->inode_bb_map,
89619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						     dirent->inode))) {
89719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			/*
89819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * If the inode is in a bad block, offer to
89919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * clear it.
90019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 */
90119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			problem = PR_2_BB_INODE;
90219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else if ((dot_state > 1) &&
90319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   ((dirent->name_len & 0xFF) == 1) &&
90419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   (dirent->name[0] == '.')) {
90519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			/*
90619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * If there's a '.' entry in anything other
90719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * than the first directory entry, it's a
90819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * duplicate entry that should be removed.
90919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 */
91019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			problem = PR_2_DUP_DOT;
91119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else if ((dot_state > 1) &&
91219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   ((dirent->name_len & 0xFF) == 2) &&
9133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			   (dirent->name[0] == '.') &&
91419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   (dirent->name[1] == '.')) {
91519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			/*
91619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * If there's a '..' entry in anything other
91719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * than the second directory entry, it's a
91819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * duplicate entry that should be removed.
91919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 */
92019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			problem = PR_2_DUP_DOT_DOT;
92119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else if ((dot_state > 1) &&
92219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   (dirent->inode == EXT2_ROOT_INO)) {
92319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			/*
92419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * Don't allow links to the root directory.
92519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * We check this specially to make sure we
92619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * catch this error case even if the root
92719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * directory hasn't been created yet.
92819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 */
92919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			problem = PR_2_LINK_ROOT;
93019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else if ((dot_state > 1) &&
93119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   (dirent->name_len & 0xFF) == 0) {
93219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			/*
93319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * Don't allow zero-length directory names.
93419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 */
93519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			problem = PR_2_NULL_NAME;
93619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
93719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
93819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (problem) {
93919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (fix_problem(ctx, problem, &cd->pctx)) {
94019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dirent->inode = 0;
94119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dir_modified++;
94219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				goto next;
94319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			} else {
94419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				ext2fs_unmark_valid(fs);
94519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				if (problem == PR_2_BAD_INO)
94619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					goto next;
94719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
94819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
94919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
95019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		/*
95119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * If the inode was marked as having bad fields in
95219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * pass1, process it and offer to fix/clear it.
95319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * (We wait until now so that we can display the
95419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * pathname to the user.)
95519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 */
95619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (ctx->inode_bad_map &&
95719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    ext2fs_test_inode_bitmap(ctx->inode_bad_map,
95819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					     dirent->inode)) {
95919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (e2fsck_process_bad_inode(ctx, ino,
96019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						     dirent->inode,
96119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						     buf + fs->blocksize)) {
96219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dirent->inode = 0;
96319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dir_modified++;
96419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				goto next;
96519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
96619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
96719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				return DIRENT_ABORT;
96819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
96919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
9703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		group = ext2fs_group_of_ino(fs, dirent->inode);
9713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		first_unused_inode = group * fs->super->s_inodes_per_group +
9723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					1 + fs->super->s_inodes_per_group -
9733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					fs->group_desc[group].bg_itable_unused;
9743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		cd->pctx.group = group;
9753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
9763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		/*
9773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		 * Check if the inode was missed out because
9783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		 * _INODE_UNINIT flag was set or bg_itable_unused was
9793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		 * incorrect.  If so, clear the _INODE_UNINIT flag and
9803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		 * restart e2fsck.  In the future it would be nice if
9813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		 * we could call a function in pass1.c that checks the
9823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		 * newly visible inodes.
9833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		 */
9843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (fs->group_desc[group].bg_flags & EXT2_BG_INODE_UNINIT) {
9853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			pctx.num = dirent->inode;
9863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (fix_problem(ctx, PR_2_INOREF_BG_INO_UNINIT,
9873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					&cd->pctx)){
9883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				fs->group_desc[group].bg_flags &=
9893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					~EXT2_BG_INODE_UNINIT;
9903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				ext2fs_mark_super_dirty(fs);
9913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				ctx->flags |= E2F_FLAG_RESTART_LATER;
9923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			} else {
9933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				ext2fs_unmark_valid(fs);
9943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				if (problem == PR_2_BAD_INO)
9953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					goto next;
9963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			}
9973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		} else if (dirent->inode >= first_unused_inode) {
9983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			pctx.num = dirent->inode;
9993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (fix_problem(ctx, PR_2_INOREF_IN_UNUSED, &cd->pctx)){
10003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				fs->group_desc[group].bg_itable_unused = 0;
10013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				ext2fs_mark_super_dirty(fs);
10023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				ctx->flags |= E2F_FLAG_RESTART_LATER;
10033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			} else {
10043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				ext2fs_unmark_valid(fs);
10053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				if (problem == PR_2_BAD_INO)
10063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					goto next;
10073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			}
10083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
10093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10108558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall		/*
10118558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall		 * Offer to clear unused inodes; if we are going to be
10128558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall		 * restarting the scan due to bg_itable_unused being
10138558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall		 * wrong, then don't clear any inodes to avoid zapping
10148558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall		 * inodes that were skipped during pass1 due to an
10158558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall		 * incorrect bg_itable_unused; we'll get any real
10168558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall		 * problems after we restart.
10178558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall		 */
10188558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall		if (!(ctx->flags & E2F_FLAG_RESTART_LATER) &&
10198558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall		    !(ext2fs_test_inode_bitmap(ctx->inode_used_map,
10208558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall					       dirent->inode)))
10213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			problem = PR_2_UNUSED_INODE;
10223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (problem) {
10243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (fix_problem(ctx, problem, &cd->pctx)) {
10253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				dirent->inode = 0;
10263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				dir_modified++;
10273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				goto next;
10283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			} else {
10293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				ext2fs_unmark_valid(fs);
10303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				if (problem == PR_2_BAD_INO)
10313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					goto next;
10323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			}
10333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
10343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
103519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (check_name(ctx, dirent, ino, &cd->pctx))
103619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dir_modified++;
103719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
103819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (check_filetype(ctx, dirent, ino, &cd->pctx))
103919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dir_modified++;
104019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
104119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef ENABLE_HTREE
104219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (dx_db) {
104319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ext2fs_dirhash(dx_dir->hashversion, dirent->name,
104419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				       (dirent->name_len & 0xFF),
104519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				       fs->super->s_hash_seed, &hash, 0);
104619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (hash < dx_db->min_hash)
104719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dx_db->min_hash = hash;
104819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (hash > dx_db->max_hash)
104919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				dx_db->max_hash = hash;
105019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
105119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
105219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
105319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		/*
105419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * If this is a directory, then mark its parent in its
105519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * dir_info structure.  If the parent field is already
105619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * filled in, then this directory has more than one
105719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * hard link.  We assume the first link is correct,
105819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * and ask the user if he/she wants to clear this one.
105919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 */
106019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if ((dot_state > 1) &&
106119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
106219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					      dirent->inode))) {
106319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (e2fsck_dir_info_get_parent(ctx, dirent->inode,
106419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						       &subdir_parent)) {
106519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				cd->pctx.ino = dirent->inode;
106619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
106719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				goto abort_free_dict;
106819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
106919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (subdir_parent) {
107019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				cd->pctx.ino2 = subdir_parent;
107119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				if (fix_problem(ctx, PR_2_LINK_DIR,
107219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						&cd->pctx)) {
107319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					dirent->inode = 0;
107419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					dir_modified++;
107519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					goto next;
107619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				}
107719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				cd->pctx.ino2 = 0;
107819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			} else {
10793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				(void) e2fsck_dir_info_set_parent(ctx,
108019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						  dirent->inode, ino);
108119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
108219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
108319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
108419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (dups_found) {
108519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			;
108619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else if (dict_lookup(&de_dict, dirent)) {
108719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			clear_problem_context(&pctx);
108819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			pctx.ino = ino;
108919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			pctx.dirent = dirent;
109019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
109119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (!ctx->dirs_to_hash)
109219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
109319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (ctx->dirs_to_hash)
109419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
109519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dups_found++;
109619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else
109719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dict_alloc_insert(&de_dict, dirent, dirent);
10983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
109919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_icount_increment(ctx->inode_count, dirent->inode,
110019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					&links);
110119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (links > 1)
110219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ctx->fs_links_count++;
110319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ctx->fs_total_count++;
110419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	next:
110519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		prev = dirent;
11063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (dir_modified)
11073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			(void) ext2fs_get_rec_len(fs, dirent, &rec_len);
11083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		offset += rec_len;
110919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dot_state++;
111019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	} while (offset < fs->blocksize);
111119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if 0
111219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	printf("\n");
111319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
111419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef ENABLE_HTREE
111519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (dx_db) {
111619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef DX_DEBUG
111719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		printf("db_block %d, type %d, min_hash 0x%0x, max_hash 0x%0x\n",
111819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		       db->blockcnt, dx_db->type,
111919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		       dx_db->min_hash, dx_db->max_hash);
112019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
112119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		cd->pctx.dir = cd->pctx.ino;
112219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
112319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    (dx_db->type == DX_DIRBLOCK_NODE))
112419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			parse_int_node(fs, db, cd, dx_dir, buf);
112519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
112619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif /* ENABLE_HTREE */
112719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (offset != fs->blocksize) {
11283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		cd->pctx.num = rec_len - fs->blocksize + offset;
112919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
113019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dirent->rec_len = cd->pctx.num;
113119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			dir_modified++;
113219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
113319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
113419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (dir_modified) {
113519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
113619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (cd->pctx.errcode) {
113719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
113819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					 &cd->pctx))
113919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				goto abort_free_dict;
114019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
114119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_mark_changed(fs);
114219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
114319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	dict_free_nodes(&de_dict);
114419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 0;
114519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectabort_free_dict:
114619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ctx->flags |= E2F_FLAG_ABORT;
11473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	dict_free_nodes(&de_dict);
114819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return DIRENT_ABORT;
114919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
115019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
115119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
115219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function is called to deallocate a block, and is an interator
115319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * functioned called by deallocate inode via ext2fs_iterate_block().
115419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
115519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int deallocate_inode_block(ext2_filsys fs,
115619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				  blk_t	*block_nr,
115719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				  e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
115819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				  blk_t ref_block EXT2FS_ATTR((unused)),
115919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				  int ref_offset EXT2FS_ATTR((unused)),
116019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				  void *priv_data)
116119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
116219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2fsck_t	ctx = (e2fsck_t) priv_data;
11633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
116419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (HOLE_BLKADDR(*block_nr))
116519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 0;
116619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if ((*block_nr < fs->super->s_first_data_block) ||
116719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    (*block_nr >= fs->super->s_blocks_count))
116819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 0;
116919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
117019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_block_alloc_stats(fs, *block_nr, -1);
117119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 0;
117219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
11733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
117419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
117519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This fuction deallocates an inode
117619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
117719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
117819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
117919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_filsys fs = ctx->fs;
118019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_inode	inode;
118119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct problem_context	pctx;
118219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	__u32			count;
11833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
118419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
11853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	e2fsck_clear_inode(ctx, ino, &inode, 0, "deallocate_inode");
118619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	clear_problem_context(&pctx);
118719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pctx.ino = ino;
118819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
118919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
119019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Fix up the bitmaps...
119119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
119219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2fsck_read_bitmaps(ctx);
119319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
119419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
119519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (inode.i_file_acl &&
119619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
119719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
119819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						   block_buf, -1, &count);
119919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
120019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			pctx.errcode = 0;
120119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			count = 1;
120219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
120319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (pctx.errcode) {
120419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			pctx.blk = inode.i_file_acl;
120519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
120619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ctx->flags |= E2F_FLAG_ABORT;
120719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return;
120819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
120919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (count == 0) {
121019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ext2fs_unmark_block_bitmap(ctx->block_found_map,
121119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						   inode.i_file_acl);
121219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
121319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
121419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		inode.i_file_acl = 0;
121519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
121619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
121719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!ext2fs_inode_has_valid_blocks(&inode))
121819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
121919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
122019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (LINUX_S_ISREG(inode.i_mode) &&
122119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    (inode.i_size_high || inode.i_size & 0x80000000UL))
122219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ctx->large_files--;
122319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
122419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
122519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					    deallocate_inode_block, ctx);
122619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (pctx.errcode) {
122719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
122819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ctx->flags |= E2F_FLAG_ABORT;
122919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
123019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
123119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
123219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
123319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
123419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This fuction clears the htree flag on an inode
123519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
123619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
123719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
123819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_inode	inode;
12393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
124019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
124119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
124219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
124319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ctx->dirs_to_hash)
124419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
124519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
124619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
124719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
124819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectextern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
124919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				    ext2_ino_t ino, char *buf)
125019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
125119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_filsys fs = ctx->fs;
125219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_inode	inode;
125319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int			inode_modified = 0;
125419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int			not_fixed = 0;
125519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	unsigned char		*frag, *fsize;
125619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct problem_context	pctx;
125719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	problem = 0;
125819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
125919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
126019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
126119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	clear_problem_context(&pctx);
126219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pctx.ino = ino;
126319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pctx.dir = dir;
126419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pctx.inode = &inode;
126519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
126619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (inode.i_file_acl &&
126719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
126819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
126919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			inode.i_file_acl = 0;
127019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			inode_modified++;
127119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else
127219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			not_fixed++;
127319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
127419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
127519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
127619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
127719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
127819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    !(LINUX_S_ISSOCK(inode.i_mode)))
127919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		problem = PR_2_BAD_MODE;
128019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else if (LINUX_S_ISCHR(inode.i_mode)
128119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 && !e2fsck_pass1_check_device_inode(fs, &inode))
128219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		problem = PR_2_BAD_CHAR_DEV;
128319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else if (LINUX_S_ISBLK(inode.i_mode)
128419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 && !e2fsck_pass1_check_device_inode(fs, &inode))
128519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		problem = PR_2_BAD_BLOCK_DEV;
128619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else if (LINUX_S_ISFIFO(inode.i_mode)
128719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 && !e2fsck_pass1_check_device_inode(fs, &inode))
128819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		problem = PR_2_BAD_FIFO;
128919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else if (LINUX_S_ISSOCK(inode.i_mode)
129019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 && !e2fsck_pass1_check_device_inode(fs, &inode))
129119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		problem = PR_2_BAD_SOCKET;
129219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else if (LINUX_S_ISLNK(inode.i_mode)
12933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		 && !e2fsck_pass1_check_symlink(fs, ino, &inode, buf)) {
129419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		problem = PR_2_INVALID_SYMLINK;
129519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
129619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
129719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (problem) {
129819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fix_problem(ctx, problem, &pctx)) {
129919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			deallocate_inode(ctx, ino, 0);
130019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
130119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				return 0;
130219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return 1;
130319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else
130419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			not_fixed++;
130519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		problem = 0;
130619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
13073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
130819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (inode.i_faddr) {
130919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
131019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			inode.i_faddr = 0;
131119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			inode_modified++;
131219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else
131319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			not_fixed++;
131419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
131519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
131619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	switch (fs->super->s_creator_os) {
131719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    case EXT2_OS_HURD:
131819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		frag = &inode.osd2.hurd2.h_i_frag;
131919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fsize = &inode.osd2.hurd2.h_i_fsize;
132019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		break;
132119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    default:
132219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		frag = fsize = 0;
132319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
132419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (frag && *frag) {
132519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.num = *frag;
132619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
132719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			*frag = 0;
132819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			inode_modified++;
132919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else
133019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			not_fixed++;
133119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.num = 0;
133219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
133319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (fsize && *fsize) {
133419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.num = *fsize;
133519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
133619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			*fsize = 0;
133719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			inode_modified++;
133819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else
133919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			not_fixed++;
134019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.num = 0;
134119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
134219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
134319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if ((fs->super->s_creator_os == EXT2_OS_LINUX) &&
13443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    !(fs->super->s_feature_ro_compat &
134519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	      EXT4_FEATURE_RO_COMPAT_HUGE_FILE) &&
134619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    (inode.osd2.linux2.l_i_blocks_hi != 0)) {
134719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.num = inode.osd2.linux2.l_i_blocks_hi;
134819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fix_problem(ctx, PR_2_BLOCKS_HI_ZERO, &pctx)) {
134919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			inode.osd2.linux2.l_i_blocks_hi = 0;
135019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			inode_modified++;
135119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
135219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
135319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
13543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!(fs->super->s_feature_incompat &
13553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	     EXT4_FEATURE_INCOMPAT_64BIT) &&
13563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    inode.osd2.linux2.l_i_file_acl_high != 0) {
13573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		pctx.num = inode.osd2.linux2.l_i_file_acl_high;
13583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (fix_problem(ctx, PR_2_I_FILE_ACL_HI_ZERO, &pctx)) {
13593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			inode.osd2.linux2.l_i_file_acl_high = 0;
13603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			inode_modified++;
13613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		} else
13623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			not_fixed++;
13633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
13643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
136519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (inode.i_file_acl &&
136619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    ((inode.i_file_acl < fs->super->s_first_data_block) ||
136719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	     (inode.i_file_acl >= fs->super->s_blocks_count))) {
136819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
136919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			inode.i_file_acl = 0;
137019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			inode_modified++;
137119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else
137219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			not_fixed++;
137319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
137419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (inode.i_dir_acl &&
137519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    LINUX_S_ISDIR(inode.i_mode)) {
137619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
137719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			inode.i_dir_acl = 0;
137819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			inode_modified++;
137919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else
138019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			not_fixed++;
138119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
138219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
138319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (inode_modified)
138419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
138519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!not_fixed && ctx->inode_bad_map)
138619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
138719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 0;
138819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
138919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
139019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
139119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
139219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * allocate_dir_block --- this function allocates a new directory
139319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 	block for a particular inode; this is done if a directory has
139419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 	a "hole" in it, or if a directory has a illegal block number
139519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 	that was zeroed out and now needs to be replaced.
139619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
139719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int allocate_dir_block(e2fsck_t ctx,
139819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      struct ext2_db_entry *db,
13993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			      char *buf EXT2FS_ATTR((unused)),
140019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      struct problem_context *pctx)
140119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
140219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_filsys fs = ctx->fs;
140319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t			blk;
140419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	char			*block;
140519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_inode	inode;
140619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
140719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
140819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 1;
140919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
141019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
141119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Read the inode and block bitmaps in; we'll be messing with
141219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * them.
141319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
141419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2fsck_read_bitmaps(ctx);
14153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
141619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
141719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * First, find a free block
141819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
141919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
142019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (pctx->errcode) {
142119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx->str = "ext2fs_new_block";
142219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
142319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 1;
142419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
142519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
142619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_mark_block_bitmap(fs->block_map, blk);
142719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_mark_bb_dirty(fs);
142819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
142919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
143019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Now let's create the actual data block for the inode
143119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
143219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (db->blockcnt)
143319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
143419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else
143519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
143619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						     EXT2_ROOT_INO, &block);
143719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
143819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (pctx->errcode) {
143919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx->str = "ext2fs_new_dir_block";
144019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
144119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 1;
144219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
144319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
144419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
144519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_free_mem(&block);
144619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (pctx->errcode) {
144719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx->str = "ext2fs_write_dir_block";
144819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
144919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 1;
145019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
145119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
145219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
145319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Update the inode block count
145419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
145519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
14563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	ext2fs_iblk_add_blocks(fs, &inode, 1);
145719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
145819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		inode.i_size = (db->blockcnt+1) * fs->blocksize;
145919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
146019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
146119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
146219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Finally, update the block pointers for the inode
146319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
146419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	db->blk = blk;
14653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	pctx->errcode = ext2fs_bmap(fs, db->ino, &inode, 0, BMAP_SET,
14663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				    db->blockcnt, &blk);
146719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (pctx->errcode) {
146819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx->str = "ext2fs_block_iterate";
146919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
147019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 1;
147119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
147219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
147319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 0;
147419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
1475