119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * dir_iterate.c --- ext2fs directory iteration operations
33984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Copyright (C) 1993, 1994, 1994, 1995, 1996, 1997 Theodore Ts'o.
519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %Begin-Header%
78558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * This file may be redistributed under the terms of the GNU Library
88558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * General Public License, version 2.
919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %End-Header%
1019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
1119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdio.h>
1319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <string.h>
1419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_UNISTD_H
1519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <unistd.h>
1619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
1719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_ERRNO_H
1819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <errno.h>
1919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
2019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ext2_fs.h"
2219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ext2fsP.h"
2319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define EXT4_MAX_REC_LEN		((1<<16)-1)
253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterrcode_t ext2fs_get_rec_len(ext2_filsys fs,
273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			     struct ext2_dir_entry *dirent,
283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			     unsigned int *rec_len)
293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	unsigned int len = dirent->rec_len;
313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
328558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall	if (fs->blocksize < 65536)
338558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall		*rec_len = len;
348558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall	else if (len == EXT4_MAX_REC_LEN || len == 0)
353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		*rec_len = fs->blocksize;
363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	else
373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		*rec_len = (len & 65532) | ((len & 3) << 16);
383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return 0;
393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterrcode_t ext2fs_set_rec_len(ext2_filsys fs,
423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			     unsigned int len,
433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			     struct ext2_dir_entry *dirent)
443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if ((len > fs->blocksize) || (fs->blocksize > (1 << 18)) || (len & 3))
463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EINVAL;
473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (len < 65536) {
483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		dirent->rec_len = len;
493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return 0;
503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (len == fs->blocksize) {
523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (fs->blocksize == 65536)
533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			dirent->rec_len = EXT4_MAX_REC_LEN;
543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		else
553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			dirent->rec_len = 0;
563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else
573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		dirent->rec_len = (len & 65532) | ((len >> 16) & 3);
583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return 0;
593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
6219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function checks to see whether or not a potential deleted
6319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * directory entry looks valid.  What we do is check the deleted entry
6419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * and each successive entry to make sure that they all look valid and
6519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * that the last deleted entry ends at the beginning of the next
6619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * undeleted entry.  Returns 1 if the deleted entry looks valid, zero
6719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * if not valid.
6819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic int ext2fs_validate_entry(ext2_filsys fs, char *buf,
703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				 unsigned int offset,
713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				 unsigned int final_offset)
7219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
7319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_dir_entry *dirent;
743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	unsigned int rec_len;
753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define DIRENT_MIN_LENGTH 12
763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	while ((offset < final_offset) &&
783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	       (offset <= fs->blocksize - DIRENT_MIN_LENGTH)) {
7919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dirent = (struct ext2_dir_entry *)(buf + offset);
803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (ext2fs_get_rec_len(fs, dirent, &rec_len))
813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			return 0;
823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		offset += rec_len;
833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if ((rec_len < 8) ||
843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    ((rec_len % 4) != 0) ||
853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    ((((unsigned) dirent->name_len & 0xFF)+8) > rec_len))
8619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return 0;
8719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
8819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return (offset == final_offset);
8919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
9019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
9119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_dir_iterate2(ext2_filsys fs,
9219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      ext2_ino_t dir,
9319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      int flags,
9419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      char *block_buf,
9519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      int (*func)(ext2_ino_t	dir,
9619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  int		entry,
9719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  struct ext2_dir_entry *dirent,
9819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  int	offset,
9919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  int	blocksize,
10019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  char	*buf,
10119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  void	*priv_data),
10219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      void *priv_data)
10319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
10419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct		dir_context	ctx;
10519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval;
1063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
10819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
10919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = ext2fs_check_directory(fs, dir);
11019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval)
11119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return retval;
1123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ctx.dir = dir;
11419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ctx.flags = flags;
11519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (block_buf)
11619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ctx.buf = block_buf;
11719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else {
11819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = ext2fs_get_mem(fs->blocksize, &ctx.buf);
11919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval)
12019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return retval;
12119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
12219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ctx.func = func;
12319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ctx.priv_data = priv_data;
12419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ctx.errcode = 0;
1253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_READ_ONLY, 0,
12619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				       ext2fs_process_dir_block, &ctx);
12719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!block_buf)
12819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_free_mem(&ctx.buf);
12919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval)
13019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return retval;
13119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return ctx.errcode;
13219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
13319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
13419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstruct xlate {
13519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int (*func)(struct ext2_dir_entry *dirent,
13619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    int		offset,
13719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    int		blocksize,
13819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    char	*buf,
13919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    void	*priv_data);
14019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	void *real_private;
14119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project};
14219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
14319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int xlate_func(ext2_ino_t dir EXT2FS_ATTR((unused)),
14419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		      int entry EXT2FS_ATTR((unused)),
14519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		      struct ext2_dir_entry *dirent, int offset,
14619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		      int blocksize, char *buf, void *priv_data)
14719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
14819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct xlate *xl = (struct xlate *) priv_data;
14919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
15019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return (*xl->func)(dirent, offset, blocksize, buf, xl->real_private);
15119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
15219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtextern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
15419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      ext2_ino_t dir,
15519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      int flags,
15619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      char *block_buf,
15719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      int (*func)(struct ext2_dir_entry *dirent,
15819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  int	offset,
15919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  int	blocksize,
16019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  char	*buf,
16119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  void	*priv_data),
16219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      void *priv_data)
16319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
16419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct xlate xl;
1653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	xl.real_private = priv_data;
16719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	xl.func = func;
16819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
16919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return ext2fs_dir_iterate2(fs, dir, flags, block_buf,
17019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				   xlate_func, &xl);
17119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
17219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
17319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
17419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
17519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Helper function which is private to this module.  Used by
17619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate()
17719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
17819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectint ext2fs_process_dir_block(ext2_filsys fs,
17919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     blk_t	*blocknr,
18019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     e2_blkcnt_t blockcnt,
18119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     blk_t	ref_block EXT2FS_ATTR((unused)),
18219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     int	ref_offset EXT2FS_ATTR((unused)),
18319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     void	*priv_data)
18419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
18519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct dir_context *ctx = (struct dir_context *) priv_data;
18619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	unsigned int	offset = 0;
18719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	unsigned int	next_real_entry = 0;
18819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int		ret = 0;
18919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int		changed = 0;
19019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int		do_abort = 0;
1913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	unsigned int	rec_len, size;
1923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int		entry;
19319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_dir_entry *dirent;
19419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
19519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (blockcnt < 0)
19619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 0;
19719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
19819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	entry = blockcnt ? DIRENT_OTHER_FILE : DIRENT_DOT_FILE;
1993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
20019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ctx->errcode = ext2fs_read_dir_block(fs, *blocknr, ctx->buf);
20119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ctx->errcode)
20219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return BLOCK_ABORT;
20319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
20419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	while (offset < fs->blocksize) {
20519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dirent = (struct ext2_dir_entry *) (ctx->buf + offset);
2063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (ext2fs_get_rec_len(fs, dirent, &rec_len))
2073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			return BLOCK_ABORT;
2083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (((offset + rec_len) > fs->blocksize) ||
2093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    (rec_len < 8) ||
2103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    ((rec_len % 4) != 0) ||
2113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    ((((unsigned) dirent->name_len & 0xFF)+8) > rec_len)) {
21219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ctx->errcode = EXT2_ET_DIR_CORRUPTED;
21319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return BLOCK_ABORT;
21419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
21519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (!dirent->inode &&
21619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    !(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY))
21719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto next;
21819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
21919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ret = (ctx->func)(ctx->dir,
22019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				  (next_real_entry > offset) ?
22119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				  DIRENT_DELETED_FILE : entry,
22219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				  dirent, offset,
22319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				  fs->blocksize, ctx->buf,
22419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				  ctx->priv_data);
22519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (entry < DIRENT_OTHER_FILE)
22619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			entry++;
2273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (ret & DIRENT_CHANGED) {
2293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (ext2fs_get_rec_len(fs, dirent, &rec_len))
2303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				return BLOCK_ABORT;
23119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			changed++;
2323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
23319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (ret & DIRENT_ABORT) {
23419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			do_abort++;
23519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			break;
23619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
2373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtnext:
23819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 		if (next_real_entry == offset)
2393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			next_real_entry += rec_len;
2403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
24119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 		if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) {
24219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			size = ((dirent->name_len & 0xFF) + 11) & ~3;
24319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (rec_len != size)  {
24519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				unsigned int final_offset;
24619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				final_offset = offset + rec_len;
24819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				offset += size;
24919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				while (offset < final_offset &&
2503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				       !ext2fs_validate_entry(fs, ctx->buf,
25119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project							      offset,
25219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project							      final_offset))
25319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					offset += 4;
25419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				continue;
25519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
25619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
2573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		offset += rec_len;
25819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
25919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
26019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (changed) {
26119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ctx->errcode = ext2fs_write_dir_block(fs, *blocknr, ctx->buf);
26219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (ctx->errcode)
26319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return BLOCK_ABORT;
26419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
26519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (do_abort)
26619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return BLOCK_ABORT;
26719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 0;
26819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
26919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
270