1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker * dir_iterate.c --- ext2fs directory iteration operations
3*6a54128fSAndroid Build Coastguard Worker *
4*6a54128fSAndroid Build Coastguard Worker * Copyright (C) 1993, 1994, 1994, 1995, 1996, 1997 Theodore Ts'o.
5*6a54128fSAndroid Build Coastguard Worker *
6*6a54128fSAndroid Build Coastguard Worker * %Begin-Header%
7*6a54128fSAndroid Build Coastguard Worker * This file may be redistributed under the terms of the GNU Library
8*6a54128fSAndroid Build Coastguard Worker * General Public License, version 2.
9*6a54128fSAndroid Build Coastguard Worker * %End-Header%
10*6a54128fSAndroid Build Coastguard Worker */
11*6a54128fSAndroid Build Coastguard Worker
12*6a54128fSAndroid Build Coastguard Worker #include "config.h"
13*6a54128fSAndroid Build Coastguard Worker #include <stdio.h>
14*6a54128fSAndroid Build Coastguard Worker #include <string.h>
15*6a54128fSAndroid Build Coastguard Worker #if HAVE_UNISTD_H
16*6a54128fSAndroid Build Coastguard Worker #include <unistd.h>
17*6a54128fSAndroid Build Coastguard Worker #endif
18*6a54128fSAndroid Build Coastguard Worker #if HAVE_ERRNO_H
19*6a54128fSAndroid Build Coastguard Worker #include <errno.h>
20*6a54128fSAndroid Build Coastguard Worker #endif
21*6a54128fSAndroid Build Coastguard Worker
22*6a54128fSAndroid Build Coastguard Worker #include "ext2_fs.h"
23*6a54128fSAndroid Build Coastguard Worker #include "ext2fsP.h"
24*6a54128fSAndroid Build Coastguard Worker
25*6a54128fSAndroid Build Coastguard Worker #define EXT4_MAX_REC_LEN ((1<<16)-1)
26*6a54128fSAndroid Build Coastguard Worker
ext2fs_get_rec_len(ext2_filsys fs,struct ext2_dir_entry * dirent,unsigned int * rec_len)27*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_get_rec_len(ext2_filsys fs,
28*6a54128fSAndroid Build Coastguard Worker struct ext2_dir_entry *dirent,
29*6a54128fSAndroid Build Coastguard Worker unsigned int *rec_len)
30*6a54128fSAndroid Build Coastguard Worker {
31*6a54128fSAndroid Build Coastguard Worker unsigned int len = dirent->rec_len;
32*6a54128fSAndroid Build Coastguard Worker
33*6a54128fSAndroid Build Coastguard Worker if (fs->blocksize < 65536)
34*6a54128fSAndroid Build Coastguard Worker *rec_len = len;
35*6a54128fSAndroid Build Coastguard Worker else if (len == EXT4_MAX_REC_LEN || len == 0)
36*6a54128fSAndroid Build Coastguard Worker *rec_len = fs->blocksize;
37*6a54128fSAndroid Build Coastguard Worker else
38*6a54128fSAndroid Build Coastguard Worker *rec_len = (len & 65532) | ((len & 3) << 16);
39*6a54128fSAndroid Build Coastguard Worker return 0;
40*6a54128fSAndroid Build Coastguard Worker }
41*6a54128fSAndroid Build Coastguard Worker
ext2fs_set_rec_len(ext2_filsys fs,unsigned int len,struct ext2_dir_entry * dirent)42*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_set_rec_len(ext2_filsys fs,
43*6a54128fSAndroid Build Coastguard Worker unsigned int len,
44*6a54128fSAndroid Build Coastguard Worker struct ext2_dir_entry *dirent)
45*6a54128fSAndroid Build Coastguard Worker {
46*6a54128fSAndroid Build Coastguard Worker if ((len > fs->blocksize) || (fs->blocksize > (1 << 18)) || (len & 3))
47*6a54128fSAndroid Build Coastguard Worker return EINVAL;
48*6a54128fSAndroid Build Coastguard Worker if (len < 65536) {
49*6a54128fSAndroid Build Coastguard Worker dirent->rec_len = len;
50*6a54128fSAndroid Build Coastguard Worker return 0;
51*6a54128fSAndroid Build Coastguard Worker }
52*6a54128fSAndroid Build Coastguard Worker if (len == fs->blocksize) {
53*6a54128fSAndroid Build Coastguard Worker if (fs->blocksize == 65536)
54*6a54128fSAndroid Build Coastguard Worker dirent->rec_len = EXT4_MAX_REC_LEN;
55*6a54128fSAndroid Build Coastguard Worker else
56*6a54128fSAndroid Build Coastguard Worker dirent->rec_len = 0;
57*6a54128fSAndroid Build Coastguard Worker } else
58*6a54128fSAndroid Build Coastguard Worker dirent->rec_len = (len & 65532) | ((len >> 16) & 3);
59*6a54128fSAndroid Build Coastguard Worker return 0;
60*6a54128fSAndroid Build Coastguard Worker }
61*6a54128fSAndroid Build Coastguard Worker
62*6a54128fSAndroid Build Coastguard Worker /*
63*6a54128fSAndroid Build Coastguard Worker * This function checks to see whether or not a potential deleted
64*6a54128fSAndroid Build Coastguard Worker * directory entry looks valid. What we do is check the deleted entry
65*6a54128fSAndroid Build Coastguard Worker * and each successive entry to make sure that they all look valid and
66*6a54128fSAndroid Build Coastguard Worker * that the last deleted entry ends at the beginning of the next
67*6a54128fSAndroid Build Coastguard Worker * undeleted entry. Returns 1 if the deleted entry looks valid, zero
68*6a54128fSAndroid Build Coastguard Worker * if not valid.
69*6a54128fSAndroid Build Coastguard Worker */
ext2fs_validate_entry(ext2_filsys fs,char * buf,unsigned int offset,unsigned int final_offset)70*6a54128fSAndroid Build Coastguard Worker static int ext2fs_validate_entry(ext2_filsys fs, char *buf,
71*6a54128fSAndroid Build Coastguard Worker unsigned int offset,
72*6a54128fSAndroid Build Coastguard Worker unsigned int final_offset)
73*6a54128fSAndroid Build Coastguard Worker {
74*6a54128fSAndroid Build Coastguard Worker struct ext2_dir_entry *dirent;
75*6a54128fSAndroid Build Coastguard Worker unsigned int rec_len;
76*6a54128fSAndroid Build Coastguard Worker #define DIRENT_MIN_LENGTH 12
77*6a54128fSAndroid Build Coastguard Worker
78*6a54128fSAndroid Build Coastguard Worker while ((offset < final_offset) &&
79*6a54128fSAndroid Build Coastguard Worker (offset <= fs->blocksize - DIRENT_MIN_LENGTH)) {
80*6a54128fSAndroid Build Coastguard Worker dirent = (struct ext2_dir_entry *)(buf + offset);
81*6a54128fSAndroid Build Coastguard Worker if (ext2fs_get_rec_len(fs, dirent, &rec_len))
82*6a54128fSAndroid Build Coastguard Worker return 0;
83*6a54128fSAndroid Build Coastguard Worker offset += rec_len;
84*6a54128fSAndroid Build Coastguard Worker if ((rec_len < 8) ||
85*6a54128fSAndroid Build Coastguard Worker ((rec_len % 4) != 0) ||
86*6a54128fSAndroid Build Coastguard Worker ((ext2fs_dirent_name_len(dirent)+8) > (int) rec_len))
87*6a54128fSAndroid Build Coastguard Worker return 0;
88*6a54128fSAndroid Build Coastguard Worker }
89*6a54128fSAndroid Build Coastguard Worker return (offset == final_offset);
90*6a54128fSAndroid Build Coastguard Worker }
91*6a54128fSAndroid Build Coastguard Worker
ext2fs_dir_iterate2(ext2_filsys fs,ext2_ino_t dir,int flags,char * block_buf,int (* func)(ext2_ino_t dir,int entry,struct ext2_dir_entry * dirent,int offset,int blocksize,char * buf,void * priv_data),void * priv_data)92*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_dir_iterate2(ext2_filsys fs,
93*6a54128fSAndroid Build Coastguard Worker ext2_ino_t dir,
94*6a54128fSAndroid Build Coastguard Worker int flags,
95*6a54128fSAndroid Build Coastguard Worker char *block_buf,
96*6a54128fSAndroid Build Coastguard Worker int (*func)(ext2_ino_t dir,
97*6a54128fSAndroid Build Coastguard Worker int entry,
98*6a54128fSAndroid Build Coastguard Worker struct ext2_dir_entry *dirent,
99*6a54128fSAndroid Build Coastguard Worker int offset,
100*6a54128fSAndroid Build Coastguard Worker int blocksize,
101*6a54128fSAndroid Build Coastguard Worker char *buf,
102*6a54128fSAndroid Build Coastguard Worker void *priv_data),
103*6a54128fSAndroid Build Coastguard Worker void *priv_data)
104*6a54128fSAndroid Build Coastguard Worker {
105*6a54128fSAndroid Build Coastguard Worker struct dir_context ctx;
106*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
107*6a54128fSAndroid Build Coastguard Worker
108*6a54128fSAndroid Build Coastguard Worker EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
109*6a54128fSAndroid Build Coastguard Worker
110*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_check_directory(fs, dir);
111*6a54128fSAndroid Build Coastguard Worker if (retval)
112*6a54128fSAndroid Build Coastguard Worker return retval;
113*6a54128fSAndroid Build Coastguard Worker
114*6a54128fSAndroid Build Coastguard Worker ctx.dir = dir;
115*6a54128fSAndroid Build Coastguard Worker ctx.flags = flags;
116*6a54128fSAndroid Build Coastguard Worker if (block_buf)
117*6a54128fSAndroid Build Coastguard Worker ctx.buf = block_buf;
118*6a54128fSAndroid Build Coastguard Worker else {
119*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_get_mem(fs->blocksize, &ctx.buf);
120*6a54128fSAndroid Build Coastguard Worker if (retval)
121*6a54128fSAndroid Build Coastguard Worker return retval;
122*6a54128fSAndroid Build Coastguard Worker }
123*6a54128fSAndroid Build Coastguard Worker ctx.func = func;
124*6a54128fSAndroid Build Coastguard Worker ctx.priv_data = priv_data;
125*6a54128fSAndroid Build Coastguard Worker ctx.errcode = 0;
126*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_READ_ONLY, 0,
127*6a54128fSAndroid Build Coastguard Worker ext2fs_process_dir_block, &ctx);
128*6a54128fSAndroid Build Coastguard Worker if (!block_buf)
129*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&ctx.buf);
130*6a54128fSAndroid Build Coastguard Worker if (retval == EXT2_ET_INLINE_DATA_CANT_ITERATE) {
131*6a54128fSAndroid Build Coastguard Worker (void) ext2fs_inline_data_dir_iterate(fs, dir, &ctx);
132*6a54128fSAndroid Build Coastguard Worker retval = 0;
133*6a54128fSAndroid Build Coastguard Worker }
134*6a54128fSAndroid Build Coastguard Worker if (retval)
135*6a54128fSAndroid Build Coastguard Worker return retval;
136*6a54128fSAndroid Build Coastguard Worker return ctx.errcode;
137*6a54128fSAndroid Build Coastguard Worker }
138*6a54128fSAndroid Build Coastguard Worker
139*6a54128fSAndroid Build Coastguard Worker struct xlate {
140*6a54128fSAndroid Build Coastguard Worker int (*func)(struct ext2_dir_entry *dirent,
141*6a54128fSAndroid Build Coastguard Worker int offset,
142*6a54128fSAndroid Build Coastguard Worker int blocksize,
143*6a54128fSAndroid Build Coastguard Worker char *buf,
144*6a54128fSAndroid Build Coastguard Worker void *priv_data);
145*6a54128fSAndroid Build Coastguard Worker void *real_private;
146*6a54128fSAndroid Build Coastguard Worker };
147*6a54128fSAndroid Build Coastguard Worker
xlate_func(ext2_ino_t dir EXT2FS_ATTR ((unused)),int entry EXT2FS_ATTR ((unused)),struct ext2_dir_entry * dirent,int offset,int blocksize,char * buf,void * priv_data)148*6a54128fSAndroid Build Coastguard Worker static int xlate_func(ext2_ino_t dir EXT2FS_ATTR((unused)),
149*6a54128fSAndroid Build Coastguard Worker int entry EXT2FS_ATTR((unused)),
150*6a54128fSAndroid Build Coastguard Worker struct ext2_dir_entry *dirent, int offset,
151*6a54128fSAndroid Build Coastguard Worker int blocksize, char *buf, void *priv_data)
152*6a54128fSAndroid Build Coastguard Worker {
153*6a54128fSAndroid Build Coastguard Worker struct xlate *xl = (struct xlate *) priv_data;
154*6a54128fSAndroid Build Coastguard Worker
155*6a54128fSAndroid Build Coastguard Worker return (*xl->func)(dirent, offset, blocksize, buf, xl->real_private);
156*6a54128fSAndroid Build Coastguard Worker }
157*6a54128fSAndroid Build Coastguard Worker
ext2fs_dir_iterate(ext2_filsys fs,ext2_ino_t dir,int flags,char * block_buf,int (* func)(struct ext2_dir_entry * dirent,int offset,int blocksize,char * buf,void * priv_data),void * priv_data)158*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_dir_iterate(ext2_filsys fs,
159*6a54128fSAndroid Build Coastguard Worker ext2_ino_t dir,
160*6a54128fSAndroid Build Coastguard Worker int flags,
161*6a54128fSAndroid Build Coastguard Worker char *block_buf,
162*6a54128fSAndroid Build Coastguard Worker int (*func)(struct ext2_dir_entry *dirent,
163*6a54128fSAndroid Build Coastguard Worker int offset,
164*6a54128fSAndroid Build Coastguard Worker int blocksize,
165*6a54128fSAndroid Build Coastguard Worker char *buf,
166*6a54128fSAndroid Build Coastguard Worker void *priv_data),
167*6a54128fSAndroid Build Coastguard Worker void *priv_data)
168*6a54128fSAndroid Build Coastguard Worker {
169*6a54128fSAndroid Build Coastguard Worker struct xlate xl;
170*6a54128fSAndroid Build Coastguard Worker
171*6a54128fSAndroid Build Coastguard Worker xl.real_private = priv_data;
172*6a54128fSAndroid Build Coastguard Worker xl.func = func;
173*6a54128fSAndroid Build Coastguard Worker
174*6a54128fSAndroid Build Coastguard Worker return ext2fs_dir_iterate2(fs, dir, flags, block_buf,
175*6a54128fSAndroid Build Coastguard Worker xlate_func, &xl);
176*6a54128fSAndroid Build Coastguard Worker }
177*6a54128fSAndroid Build Coastguard Worker
178*6a54128fSAndroid Build Coastguard Worker
179*6a54128fSAndroid Build Coastguard Worker /*
180*6a54128fSAndroid Build Coastguard Worker * Helper function which is private to this module. Used by
181*6a54128fSAndroid Build Coastguard Worker * ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate()
182*6a54128fSAndroid Build Coastguard Worker */
ext2fs_process_dir_block(ext2_filsys fs,blk64_t * blocknr,e2_blkcnt_t blockcnt,blk64_t ref_block EXT2FS_ATTR ((unused)),int ref_offset EXT2FS_ATTR ((unused)),void * priv_data)183*6a54128fSAndroid Build Coastguard Worker int ext2fs_process_dir_block(ext2_filsys fs,
184*6a54128fSAndroid Build Coastguard Worker blk64_t *blocknr,
185*6a54128fSAndroid Build Coastguard Worker e2_blkcnt_t blockcnt,
186*6a54128fSAndroid Build Coastguard Worker blk64_t ref_block EXT2FS_ATTR((unused)),
187*6a54128fSAndroid Build Coastguard Worker int ref_offset EXT2FS_ATTR((unused)),
188*6a54128fSAndroid Build Coastguard Worker void *priv_data)
189*6a54128fSAndroid Build Coastguard Worker {
190*6a54128fSAndroid Build Coastguard Worker struct dir_context *ctx = (struct dir_context *) priv_data;
191*6a54128fSAndroid Build Coastguard Worker unsigned int offset = 0;
192*6a54128fSAndroid Build Coastguard Worker unsigned int next_real_entry = 0;
193*6a54128fSAndroid Build Coastguard Worker int ret = 0;
194*6a54128fSAndroid Build Coastguard Worker int changed = 0;
195*6a54128fSAndroid Build Coastguard Worker int do_abort = 0;
196*6a54128fSAndroid Build Coastguard Worker unsigned int rec_len, size, buflen;
197*6a54128fSAndroid Build Coastguard Worker int entry;
198*6a54128fSAndroid Build Coastguard Worker struct ext2_dir_entry *dirent;
199*6a54128fSAndroid Build Coastguard Worker int csum_size = 0;
200*6a54128fSAndroid Build Coastguard Worker int inline_data;
201*6a54128fSAndroid Build Coastguard Worker errcode_t retval = 0;
202*6a54128fSAndroid Build Coastguard Worker
203*6a54128fSAndroid Build Coastguard Worker if (blockcnt < 0)
204*6a54128fSAndroid Build Coastguard Worker return 0;
205*6a54128fSAndroid Build Coastguard Worker
206*6a54128fSAndroid Build Coastguard Worker entry = blockcnt ? DIRENT_OTHER_FILE : DIRENT_DOT_FILE;
207*6a54128fSAndroid Build Coastguard Worker
208*6a54128fSAndroid Build Coastguard Worker /* If a dir has inline data, we don't need to read block */
209*6a54128fSAndroid Build Coastguard Worker inline_data = !!(ctx->flags & DIRENT_FLAG_INCLUDE_INLINE_DATA);
210*6a54128fSAndroid Build Coastguard Worker if (!inline_data) {
211*6a54128fSAndroid Build Coastguard Worker ctx->errcode = ext2fs_read_dir_block4(fs, *blocknr, ctx->buf, 0,
212*6a54128fSAndroid Build Coastguard Worker ctx->dir);
213*6a54128fSAndroid Build Coastguard Worker if (ctx->errcode)
214*6a54128fSAndroid Build Coastguard Worker return BLOCK_ABORT;
215*6a54128fSAndroid Build Coastguard Worker /* If we handle a normal dir, we traverse the entire block */
216*6a54128fSAndroid Build Coastguard Worker buflen = fs->blocksize;
217*6a54128fSAndroid Build Coastguard Worker } else {
218*6a54128fSAndroid Build Coastguard Worker buflen = ctx->buflen;
219*6a54128fSAndroid Build Coastguard Worker }
220*6a54128fSAndroid Build Coastguard Worker
221*6a54128fSAndroid Build Coastguard Worker if (ext2fs_has_feature_metadata_csum(fs->super))
222*6a54128fSAndroid Build Coastguard Worker csum_size = sizeof(struct ext2_dir_entry_tail);
223*6a54128fSAndroid Build Coastguard Worker
224*6a54128fSAndroid Build Coastguard Worker if (buflen < 8) {
225*6a54128fSAndroid Build Coastguard Worker ctx->errcode = EXT2_ET_DIR_CORRUPTED;
226*6a54128fSAndroid Build Coastguard Worker return BLOCK_ABORT;
227*6a54128fSAndroid Build Coastguard Worker }
228*6a54128fSAndroid Build Coastguard Worker while (offset < buflen - 8) {
229*6a54128fSAndroid Build Coastguard Worker dirent = (struct ext2_dir_entry *) (ctx->buf + offset);
230*6a54128fSAndroid Build Coastguard Worker if (ext2fs_get_rec_len(fs, dirent, &rec_len))
231*6a54128fSAndroid Build Coastguard Worker return BLOCK_ABORT;
232*6a54128fSAndroid Build Coastguard Worker if (((offset + rec_len) > buflen) ||
233*6a54128fSAndroid Build Coastguard Worker (rec_len < 8) ||
234*6a54128fSAndroid Build Coastguard Worker ((rec_len % 4) != 0) ||
235*6a54128fSAndroid Build Coastguard Worker ((ext2fs_dirent_name_len(dirent)+8) > (int) rec_len)) {
236*6a54128fSAndroid Build Coastguard Worker ctx->errcode = EXT2_ET_DIR_CORRUPTED;
237*6a54128fSAndroid Build Coastguard Worker return BLOCK_ABORT;
238*6a54128fSAndroid Build Coastguard Worker }
239*6a54128fSAndroid Build Coastguard Worker if (!dirent->inode) {
240*6a54128fSAndroid Build Coastguard Worker /*
241*6a54128fSAndroid Build Coastguard Worker * We just need to check metadata_csum when this
242*6a54128fSAndroid Build Coastguard Worker * dir hasn't inline data. That means that 'buflen'
243*6a54128fSAndroid Build Coastguard Worker * should be blocksize.
244*6a54128fSAndroid Build Coastguard Worker */
245*6a54128fSAndroid Build Coastguard Worker if (!inline_data &&
246*6a54128fSAndroid Build Coastguard Worker (offset == buflen - csum_size) &&
247*6a54128fSAndroid Build Coastguard Worker (dirent->rec_len == csum_size) &&
248*6a54128fSAndroid Build Coastguard Worker (dirent->name_len == EXT2_DIR_NAME_LEN_CSUM)) {
249*6a54128fSAndroid Build Coastguard Worker if (!(ctx->flags & DIRENT_FLAG_INCLUDE_CSUM))
250*6a54128fSAndroid Build Coastguard Worker goto next;
251*6a54128fSAndroid Build Coastguard Worker entry = DIRENT_CHECKSUM;
252*6a54128fSAndroid Build Coastguard Worker } else if (!(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY))
253*6a54128fSAndroid Build Coastguard Worker goto next;
254*6a54128fSAndroid Build Coastguard Worker }
255*6a54128fSAndroid Build Coastguard Worker
256*6a54128fSAndroid Build Coastguard Worker ret = (ctx->func)(ctx->dir,
257*6a54128fSAndroid Build Coastguard Worker (next_real_entry > offset) ?
258*6a54128fSAndroid Build Coastguard Worker DIRENT_DELETED_FILE : entry,
259*6a54128fSAndroid Build Coastguard Worker dirent, offset,
260*6a54128fSAndroid Build Coastguard Worker buflen, ctx->buf,
261*6a54128fSAndroid Build Coastguard Worker ctx->priv_data);
262*6a54128fSAndroid Build Coastguard Worker if (entry < DIRENT_OTHER_FILE)
263*6a54128fSAndroid Build Coastguard Worker entry++;
264*6a54128fSAndroid Build Coastguard Worker
265*6a54128fSAndroid Build Coastguard Worker if (ret & DIRENT_CHANGED) {
266*6a54128fSAndroid Build Coastguard Worker if (ext2fs_get_rec_len(fs, dirent, &rec_len))
267*6a54128fSAndroid Build Coastguard Worker return BLOCK_ABORT;
268*6a54128fSAndroid Build Coastguard Worker changed++;
269*6a54128fSAndroid Build Coastguard Worker }
270*6a54128fSAndroid Build Coastguard Worker if (ret & DIRENT_ABORT) {
271*6a54128fSAndroid Build Coastguard Worker do_abort++;
272*6a54128fSAndroid Build Coastguard Worker break;
273*6a54128fSAndroid Build Coastguard Worker }
274*6a54128fSAndroid Build Coastguard Worker next:
275*6a54128fSAndroid Build Coastguard Worker if (next_real_entry == offset)
276*6a54128fSAndroid Build Coastguard Worker next_real_entry += rec_len;
277*6a54128fSAndroid Build Coastguard Worker
278*6a54128fSAndroid Build Coastguard Worker if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) {
279*6a54128fSAndroid Build Coastguard Worker size = (ext2fs_dirent_name_len(dirent) + 11) & ~3;
280*6a54128fSAndroid Build Coastguard Worker
281*6a54128fSAndroid Build Coastguard Worker if (rec_len != size) {
282*6a54128fSAndroid Build Coastguard Worker unsigned int final_offset;
283*6a54128fSAndroid Build Coastguard Worker
284*6a54128fSAndroid Build Coastguard Worker final_offset = offset + rec_len;
285*6a54128fSAndroid Build Coastguard Worker offset += size;
286*6a54128fSAndroid Build Coastguard Worker while (offset < final_offset &&
287*6a54128fSAndroid Build Coastguard Worker !ext2fs_validate_entry(fs, ctx->buf,
288*6a54128fSAndroid Build Coastguard Worker offset,
289*6a54128fSAndroid Build Coastguard Worker final_offset))
290*6a54128fSAndroid Build Coastguard Worker offset += 4;
291*6a54128fSAndroid Build Coastguard Worker continue;
292*6a54128fSAndroid Build Coastguard Worker }
293*6a54128fSAndroid Build Coastguard Worker }
294*6a54128fSAndroid Build Coastguard Worker offset += rec_len;
295*6a54128fSAndroid Build Coastguard Worker }
296*6a54128fSAndroid Build Coastguard Worker
297*6a54128fSAndroid Build Coastguard Worker if (changed) {
298*6a54128fSAndroid Build Coastguard Worker if (!inline_data) {
299*6a54128fSAndroid Build Coastguard Worker ctx->errcode = ext2fs_write_dir_block4(fs, *blocknr,
300*6a54128fSAndroid Build Coastguard Worker ctx->buf,
301*6a54128fSAndroid Build Coastguard Worker 0, ctx->dir);
302*6a54128fSAndroid Build Coastguard Worker if (ctx->errcode)
303*6a54128fSAndroid Build Coastguard Worker return BLOCK_ABORT;
304*6a54128fSAndroid Build Coastguard Worker } else {
305*6a54128fSAndroid Build Coastguard Worker /*
306*6a54128fSAndroid Build Coastguard Worker * return BLOCK_INLINE_DATA_CHANGED to notify caller
307*6a54128fSAndroid Build Coastguard Worker * that inline data has been changed.
308*6a54128fSAndroid Build Coastguard Worker */
309*6a54128fSAndroid Build Coastguard Worker retval = BLOCK_INLINE_DATA_CHANGED;
310*6a54128fSAndroid Build Coastguard Worker }
311*6a54128fSAndroid Build Coastguard Worker }
312*6a54128fSAndroid Build Coastguard Worker if (do_abort)
313*6a54128fSAndroid Build Coastguard Worker return retval | BLOCK_ABORT;
314*6a54128fSAndroid Build Coastguard Worker return retval;
315*6a54128fSAndroid Build Coastguard Worker }
316