121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o/* 221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * dir_iterate.c --- ext2fs directory iteration operations 3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Copyright (C) 1993, 1994, 1994, 1995, 1996, 1997 Theodore Ts'o. 521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * 621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %Begin-Header% 7543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library 8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2. 921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %End-Header% 1021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o */ 1121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 1221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include <stdio.h> 1321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include <string.h> 144cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#if HAVE_UNISTD_H 1521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include <unistd.h> 164cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#endif 1721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#if HAVE_ERRNO_H 1821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include <errno.h> 1921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#endif 2021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 21b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h" 2221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include "ext2fsP.h" 2321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 248a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o#define EXT4_MAX_REC_LEN ((1<<16)-1) 258a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o 268a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'oerrcode_t ext2fs_get_rec_len(ext2_filsys fs, 278a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o struct ext2_dir_entry *dirent, 288a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o unsigned int *rec_len) 298a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o{ 308a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o unsigned int len = dirent->rec_len; 318a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o 32a4fdf09414e04e9ecb995aa0af2f525d335987aeTheodore Ts'o if (fs->blocksize < 65536) 33a4fdf09414e04e9ecb995aa0af2f525d335987aeTheodore Ts'o *rec_len = len; 34a4fdf09414e04e9ecb995aa0af2f525d335987aeTheodore Ts'o else if (len == EXT4_MAX_REC_LEN || len == 0) 358a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o *rec_len = fs->blocksize; 368a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o else 378a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o *rec_len = (len & 65532) | ((len & 3) << 16); 388a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o return 0; 398a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o} 408a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o 418a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'oerrcode_t ext2fs_set_rec_len(ext2_filsys fs, 428a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o unsigned int len, 438a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o struct ext2_dir_entry *dirent) 448a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o{ 458a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o if ((len > fs->blocksize) || (fs->blocksize > (1 << 18)) || (len & 3)) 468a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o return EINVAL; 478a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o if (len < 65536) { 488a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o dirent->rec_len = len; 498a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o return 0; 508a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o } 518a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o if (len == fs->blocksize) { 528a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o if (fs->blocksize == 65536) 538a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o dirent->rec_len = EXT4_MAX_REC_LEN; 548a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o else 558a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o dirent->rec_len = 0; 568a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o } else 578a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o dirent->rec_len = (len & 65532) | ((len >> 16) & 3); 588a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o return 0; 598a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o} 608a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o 618bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o/* 628bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o * This function checks to see whether or not a potential deleted 638bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o * directory entry looks valid. What we do is check the deleted entry 648bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o * and each successive entry to make sure that they all look valid and 658bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o * that the last deleted entry ends at the beginning of the next 668bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o * undeleted entry. Returns 1 if the deleted entry looks valid, zero 678bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o * if not valid. 688bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o */ 696a8da46d284721e95f893d4f229a2bec473797e1Nic Casestatic int ext2fs_validate_entry(ext2_filsys fs, char *buf, 706a8da46d284721e95f893d4f229a2bec473797e1Nic Case unsigned int offset, 716a8da46d284721e95f893d4f229a2bec473797e1Nic Case unsigned int final_offset) 728bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o{ 738bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o struct ext2_dir_entry *dirent; 748a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o unsigned int rec_len; 756a8da46d284721e95f893d4f229a2bec473797e1Nic Case#define DIRENT_MIN_LENGTH 12 76efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 776a8da46d284721e95f893d4f229a2bec473797e1Nic Case while ((offset < final_offset) && 786a8da46d284721e95f893d4f229a2bec473797e1Nic Case (offset <= fs->blocksize - DIRENT_MIN_LENGTH)) { 798bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o dirent = (struct ext2_dir_entry *)(buf + offset); 808a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o if (ext2fs_get_rec_len(fs, dirent, &rec_len)) 818a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o return 0; 825dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o offset += rec_len; 835dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if ((rec_len < 8) || 845dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o ((rec_len % 4) != 0) || 8525c7e0c3042cb92a71d25cb3c2709a55b9f120a6Theodore Ts'o ((((unsigned) dirent->name_len & 0xFF)+8) > rec_len)) 868bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o return 0; 878bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o } 888bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o return (offset == final_offset); 898bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o} 908bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o 918bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'oerrcode_t ext2fs_dir_iterate2(ext2_filsys fs, 928bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o ext2_ino_t dir, 938bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o int flags, 948bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o char *block_buf, 958bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o int (*func)(ext2_ino_t dir, 968bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o int entry, 978bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o struct ext2_dir_entry *dirent, 988bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o int offset, 998bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o int blocksize, 1008bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o char *buf, 1018bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o void *priv_data), 1028bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o void *priv_data) 10321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o{ 10421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct dir_context ctx; 10521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o errcode_t retval; 106efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 10721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 10821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 10921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o retval = ext2fs_check_directory(fs, dir); 11021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (retval) 11121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return retval; 112efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 11321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o ctx.dir = dir; 11421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o ctx.flags = flags; 11521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (block_buf) 11621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o ctx.buf = block_buf; 11721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o else { 118c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o retval = ext2fs_get_mem(fs->blocksize, &ctx.buf); 1197b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 1207b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 12121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 12221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o ctx.func = func; 123b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o ctx.priv_data = priv_data; 12421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o ctx.errcode = 0; 125e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_READ_ONLY, 0, 12636a43d675ef61d0f5d5b2ad62d2e670c408d14acTheodore Ts'o ext2fs_process_dir_block, &ctx); 12721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (!block_buf) 128c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&ctx.buf); 12921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (retval) 13021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return retval; 13121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return ctx.errcode; 13221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o} 13321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 1348bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'ostruct xlate { 1358bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o int (*func)(struct ext2_dir_entry *dirent, 1368bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o int offset, 1378bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o int blocksize, 1388bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o char *buf, 1398bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o void *priv_data); 1408bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o void *real_private; 1418bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o}; 1428bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o 143544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic int xlate_func(ext2_ino_t dir EXT2FS_ATTR((unused)), 144544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int entry EXT2FS_ATTR((unused)), 1458bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o struct ext2_dir_entry *dirent, int offset, 1468bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o int blocksize, char *buf, void *priv_data) 1478bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o{ 1488bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o struct xlate *xl = (struct xlate *) priv_data; 1498bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o 1508bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o return (*xl->func)(dirent, offset, blocksize, buf, xl->real_private); 1518bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o} 1528bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o 153e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t ext2fs_dir_iterate(ext2_filsys fs, 154e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_ino_t dir, 155e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int flags, 156e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char *block_buf, 157e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int (*func)(struct ext2_dir_entry *dirent, 158e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int offset, 159e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int blocksize, 160e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char *buf, 161e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall void *priv_data), 162e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall void *priv_data) 1638bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o{ 1648bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o struct xlate xl; 165efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1668bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o xl.real_private = priv_data; 1678bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o xl.func = func; 1688bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o 1698bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o return ext2fs_dir_iterate2(fs, dir, flags, block_buf, 1708bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o xlate_func, &xl); 1718bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o} 1728bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o 1738bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o 17421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o/* 17521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Helper function which is private to this module. Used by 17621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate() 17721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o */ 178544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'oint ext2fs_process_dir_block(ext2_filsys fs, 179e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t *blocknr, 180544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o e2_blkcnt_t blockcnt, 181e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t ref_block EXT2FS_ATTR((unused)), 182544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int ref_offset EXT2FS_ATTR((unused)), 183544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o void *priv_data) 18421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o{ 185b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o struct dir_context *ctx = (struct dir_context *) priv_data; 186544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int offset = 0; 187544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int next_real_entry = 0; 18821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o int ret = 0; 18921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o int changed = 0; 19021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o int do_abort = 0; 19125c7e0c3042cb92a71d25cb3c2709a55b9f120a6Theodore Ts'o unsigned int rec_len, size; 19225c7e0c3042cb92a71d25cb3c2709a55b9f120a6Theodore Ts'o int entry; 19321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct ext2_dir_entry *dirent; 19421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 19521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (blockcnt < 0) 19621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return 0; 19721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 19836a43d675ef61d0f5d5b2ad62d2e670c408d14acTheodore Ts'o entry = blockcnt ? DIRENT_OTHER_FILE : DIRENT_DOT_FILE; 199efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 200e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ctx->errcode = ext2fs_read_dir_block3(fs, *blocknr, ctx->buf, 0); 20121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (ctx->errcode) 20221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return BLOCK_ABORT; 20321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 20421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o while (offset < fs->blocksize) { 20521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dirent = (struct ext2_dir_entry *) (ctx->buf + offset); 2068a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o if (ext2fs_get_rec_len(fs, dirent, &rec_len)) 2078a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o return BLOCK_ABORT; 2085dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (((offset + rec_len) > fs->blocksize) || 2095dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o (rec_len < 8) || 2105dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o ((rec_len % 4) != 0) || 21125c7e0c3042cb92a71d25cb3c2709a55b9f120a6Theodore Ts'o ((((unsigned) dirent->name_len & 0xFF)+8) > rec_len)) { 212813bbb25a24ebba5177da18be413ea742efe5a8aTheodore Ts'o ctx->errcode = EXT2_ET_DIR_CORRUPTED; 213813bbb25a24ebba5177da18be413ea742efe5a8aTheodore Ts'o return BLOCK_ABORT; 214813bbb25a24ebba5177da18be413ea742efe5a8aTheodore Ts'o } 21521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (!dirent->inode && 21621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o !(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY)) 21721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o goto next; 21821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 2198bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o ret = (ctx->func)(ctx->dir, 2208bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o (next_real_entry > offset) ? 2218bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o DIRENT_DELETED_FILE : entry, 2228bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o dirent, offset, 2238bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o fs->blocksize, ctx->buf, 2248bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o ctx->priv_data); 2258bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o if (entry < DIRENT_OTHER_FILE) 2268bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o entry++; 227efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 2285dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (ret & DIRENT_CHANGED) { 2298a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o if (ext2fs_get_rec_len(fs, dirent, &rec_len)) 2308a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o return BLOCK_ABORT; 23121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o changed++; 2325dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o } 23321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (ret & DIRENT_ABORT) { 23421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o do_abort++; 23521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o break; 23621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 237efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'onext: 2388bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o if (next_real_entry == offset) 2395dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o next_real_entry += rec_len; 240efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 2418bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) { 2428bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o size = ((dirent->name_len & 0xFF) + 11) & ~3; 2438bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o 2445dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (rec_len != size) { 245544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int final_offset; 246544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o 2475dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o final_offset = offset + rec_len; 2488bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o offset += size; 2498bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o while (offset < final_offset && 2505dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o !ext2fs_validate_entry(fs, ctx->buf, 2518bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o offset, 2528bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o final_offset)) 2538bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o offset += 4; 2548bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o continue; 2558bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o } 2568bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o } 2575dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o offset += rec_len; 25821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 25921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 26021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (changed) { 261e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ctx->errcode = ext2fs_write_dir_block3(fs, *blocknr, ctx->buf, 262e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 0); 26321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (ctx->errcode) 26421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return BLOCK_ABORT; 26521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 26621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (do_abort) 26721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return BLOCK_ABORT; 26821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o return 0; 26921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o} 27021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 271