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%
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%
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
323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (len == EXT4_MAX_REC_LEN || len == 0)
333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		*rec_len = fs->blocksize;
343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	else
353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		*rec_len = (len & 65532) | ((len & 3) << 16);
363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return 0;
373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterrcode_t ext2fs_set_rec_len(ext2_filsys fs,
403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			     unsigned int len,
413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			     struct ext2_dir_entry *dirent)
423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if ((len > fs->blocksize) || (fs->blocksize > (1 << 18)) || (len & 3))
443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EINVAL;
453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (len < 65536) {
463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		dirent->rec_len = len;
473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return 0;
483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (len == fs->blocksize) {
503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (fs->blocksize == 65536)
513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			dirent->rec_len = EXT4_MAX_REC_LEN;
523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		else
533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			dirent->rec_len = 0;
543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else
553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		dirent->rec_len = (len & 65532) | ((len >> 16) & 3);
563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return 0;
573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
6019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function checks to see whether or not a potential deleted
6119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * directory entry looks valid.  What we do is check the deleted entry
6219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * and each successive entry to make sure that they all look valid and
6319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * that the last deleted entry ends at the beginning of the next
6419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * undeleted entry.  Returns 1 if the deleted entry looks valid, zero
6519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * if not valid.
6619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic int ext2fs_validate_entry(ext2_filsys fs, char *buf,
683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				 unsigned int offset,
693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				 unsigned int final_offset)
7019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
7119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_dir_entry *dirent;
723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	unsigned int rec_len;
733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define DIRENT_MIN_LENGTH 12
743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	while ((offset < final_offset) &&
763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	       (offset <= fs->blocksize - DIRENT_MIN_LENGTH)) {
7719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dirent = (struct ext2_dir_entry *)(buf + offset);
783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (ext2fs_get_rec_len(fs, dirent, &rec_len))
793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			return 0;
803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		offset += rec_len;
813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if ((rec_len < 8) ||
823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    ((rec_len % 4) != 0) ||
833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    ((((unsigned) dirent->name_len & 0xFF)+8) > rec_len))
8419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return 0;
8519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
8619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return (offset == final_offset);
8719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
8819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
8919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_dir_iterate2(ext2_filsys fs,
9019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      ext2_ino_t dir,
9119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      int flags,
9219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      char *block_buf,
9319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      int (*func)(ext2_ino_t	dir,
9419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  int		entry,
9519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  struct ext2_dir_entry *dirent,
9619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  int	offset,
9719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  int	blocksize,
9819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  char	*buf,
9919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  void	*priv_data),
10019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      void *priv_data)
10119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
10219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct		dir_context	ctx;
10319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval;
1043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
10619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
10719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = ext2fs_check_directory(fs, dir);
10819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval)
10919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return retval;
1103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ctx.dir = dir;
11219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ctx.flags = flags;
11319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (block_buf)
11419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ctx.buf = block_buf;
11519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else {
11619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = ext2fs_get_mem(fs->blocksize, &ctx.buf);
11719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval)
11819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return retval;
11919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
12019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ctx.func = func;
12119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ctx.priv_data = priv_data;
12219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ctx.errcode = 0;
1233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_READ_ONLY, 0,
12419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				       ext2fs_process_dir_block, &ctx);
12519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!block_buf)
12619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_free_mem(&ctx.buf);
12719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval)
12819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return retval;
12919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return ctx.errcode;
13019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
13119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
13219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstruct xlate {
13319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int (*func)(struct ext2_dir_entry *dirent,
13419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    int		offset,
13519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    int		blocksize,
13619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    char	*buf,
13719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    void	*priv_data);
13819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	void *real_private;
13919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project};
14019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
14119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int xlate_func(ext2_ino_t dir EXT2FS_ATTR((unused)),
14219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		      int entry EXT2FS_ATTR((unused)),
14319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		      struct ext2_dir_entry *dirent, int offset,
14419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		      int blocksize, char *buf, void *priv_data)
14519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
14619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct xlate *xl = (struct xlate *) priv_data;
14719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
14819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return (*xl->func)(dirent, offset, blocksize, buf, xl->real_private);
14919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
15019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtextern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
15219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      ext2_ino_t dir,
15319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      int flags,
15419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      char *block_buf,
15519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      int (*func)(struct ext2_dir_entry *dirent,
15619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  int	offset,
15719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  int	blocksize,
15819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  char	*buf,
15919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  void	*priv_data),
16019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      void *priv_data)
16119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
16219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct xlate xl;
1633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	xl.real_private = priv_data;
16519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	xl.func = func;
16619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
16719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return ext2fs_dir_iterate2(fs, dir, flags, block_buf,
16819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				   xlate_func, &xl);
16919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
17019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
17119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
17219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
17319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Helper function which is private to this module.  Used by
17419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate()
17519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
17619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectint ext2fs_process_dir_block(ext2_filsys fs,
17719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     blk_t	*blocknr,
17819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     e2_blkcnt_t blockcnt,
17919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     blk_t	ref_block EXT2FS_ATTR((unused)),
18019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     int	ref_offset EXT2FS_ATTR((unused)),
18119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     void	*priv_data)
18219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
18319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct dir_context *ctx = (struct dir_context *) priv_data;
18419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	unsigned int	offset = 0;
18519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	unsigned int	next_real_entry = 0;
18619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int		ret = 0;
18719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int		changed = 0;
18819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int		do_abort = 0;
1893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	unsigned int	rec_len, size;
1903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int		entry;
19119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_dir_entry *dirent;
19219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
19319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (blockcnt < 0)
19419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 0;
19519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
19619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	entry = blockcnt ? DIRENT_OTHER_FILE : DIRENT_DOT_FILE;
1973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ctx->errcode = ext2fs_read_dir_block(fs, *blocknr, ctx->buf);
19919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ctx->errcode)
20019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return BLOCK_ABORT;
20119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
20219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	while (offset < fs->blocksize) {
20319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dirent = (struct ext2_dir_entry *) (ctx->buf + offset);
2043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (ext2fs_get_rec_len(fs, dirent, &rec_len))
2053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			return BLOCK_ABORT;
2063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (((offset + rec_len) > fs->blocksize) ||
2073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    (rec_len < 8) ||
2083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    ((rec_len % 4) != 0) ||
2093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    ((((unsigned) dirent->name_len & 0xFF)+8) > rec_len)) {
21019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ctx->errcode = EXT2_ET_DIR_CORRUPTED;
21119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return BLOCK_ABORT;
21219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
21319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (!dirent->inode &&
21419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    !(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY))
21519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto next;
21619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
21719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ret = (ctx->func)(ctx->dir,
21819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				  (next_real_entry > offset) ?
21919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				  DIRENT_DELETED_FILE : entry,
22019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				  dirent, offset,
22119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				  fs->blocksize, ctx->buf,
22219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				  ctx->priv_data);
22319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (entry < DIRENT_OTHER_FILE)
22419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			entry++;
2253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (ret & DIRENT_CHANGED) {
2273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (ext2fs_get_rec_len(fs, dirent, &rec_len))
2283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				return BLOCK_ABORT;
22919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			changed++;
2303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
23119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (ret & DIRENT_ABORT) {
23219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			do_abort++;
23319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			break;
23419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
2353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtnext:
23619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 		if (next_real_entry == offset)
2373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			next_real_entry += rec_len;
2383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
23919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 		if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) {
24019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			size = ((dirent->name_len & 0xFF) + 11) & ~3;
24119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (rec_len != size)  {
24319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				unsigned int final_offset;
24419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				final_offset = offset + rec_len;
24619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				offset += size;
24719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				while (offset < final_offset &&
2483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				       !ext2fs_validate_entry(fs, ctx->buf,
24919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project							      offset,
25019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project							      final_offset))
25119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					offset += 4;
25219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				continue;
25319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
25419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
2553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		offset += rec_len;
25619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
25719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
25819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (changed) {
25919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ctx->errcode = ext2fs_write_dir_block(fs, *blocknr, ctx->buf);
26019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (ctx->errcode)
26119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return BLOCK_ABORT;
26219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
26319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (do_abort)
26419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return BLOCK_ABORT;
26519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 0;
26619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
26719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
268