diff options
Diffstat (limited to 'e2fsprogs/ext2fs/block.c')
-rw-r--r-- | e2fsprogs/ext2fs/block.c | 438 |
1 files changed, 0 insertions, 438 deletions
diff --git a/e2fsprogs/ext2fs/block.c b/e2fsprogs/ext2fs/block.c deleted file mode 100644 index 0a757b201..000000000 --- a/e2fsprogs/ext2fs/block.c +++ /dev/null | |||
@@ -1,438 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * block.c --- iterate over all blocks in an inode | ||
4 | * | ||
5 | * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. | ||
6 | * | ||
7 | * %Begin-Header% | ||
8 | * This file may be redistributed under the terms of the GNU Public | ||
9 | * License. | ||
10 | * %End-Header% | ||
11 | */ | ||
12 | |||
13 | #include <stdio.h> | ||
14 | #include <string.h> | ||
15 | #if HAVE_UNISTD_H | ||
16 | #include <unistd.h> | ||
17 | #endif | ||
18 | |||
19 | #include "ext2_fs.h" | ||
20 | #include "ext2fs.h" | ||
21 | |||
22 | struct block_context { | ||
23 | ext2_filsys fs; | ||
24 | int (*func)(ext2_filsys fs, | ||
25 | blk_t *blocknr, | ||
26 | e2_blkcnt_t bcount, | ||
27 | blk_t ref_blk, | ||
28 | int ref_offset, | ||
29 | void *priv_data); | ||
30 | e2_blkcnt_t bcount; | ||
31 | int bsize; | ||
32 | int flags; | ||
33 | errcode_t errcode; | ||
34 | char *ind_buf; | ||
35 | char *dind_buf; | ||
36 | char *tind_buf; | ||
37 | void *priv_data; | ||
38 | }; | ||
39 | |||
40 | static int block_iterate_ind(blk_t *ind_block, blk_t ref_block, | ||
41 | int ref_offset, struct block_context *ctx) | ||
42 | { | ||
43 | int ret = 0, changed = 0; | ||
44 | int i, flags, limit, offset; | ||
45 | blk_t *block_nr; | ||
46 | |||
47 | limit = ctx->fs->blocksize >> 2; | ||
48 | if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && | ||
49 | !(ctx->flags & BLOCK_FLAG_DATA_ONLY)) | ||
50 | ret = (*ctx->func)(ctx->fs, ind_block, | ||
51 | BLOCK_COUNT_IND, ref_block, | ||
52 | ref_offset, ctx->priv_data); | ||
53 | if (!*ind_block || (ret & BLOCK_ABORT)) { | ||
54 | ctx->bcount += limit; | ||
55 | return ret; | ||
56 | } | ||
57 | if (*ind_block >= ctx->fs->super->s_blocks_count || | ||
58 | *ind_block < ctx->fs->super->s_first_data_block) { | ||
59 | ctx->errcode = EXT2_ET_BAD_IND_BLOCK; | ||
60 | ret |= BLOCK_ERROR; | ||
61 | return ret; | ||
62 | } | ||
63 | ctx->errcode = ext2fs_read_ind_block(ctx->fs, *ind_block, | ||
64 | ctx->ind_buf); | ||
65 | if (ctx->errcode) { | ||
66 | ret |= BLOCK_ERROR; | ||
67 | return ret; | ||
68 | } | ||
69 | |||
70 | block_nr = (blk_t *) ctx->ind_buf; | ||
71 | offset = 0; | ||
72 | if (ctx->flags & BLOCK_FLAG_APPEND) { | ||
73 | for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) { | ||
74 | flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount, | ||
75 | *ind_block, offset, | ||
76 | ctx->priv_data); | ||
77 | changed |= flags; | ||
78 | if (flags & BLOCK_ABORT) { | ||
79 | ret |= BLOCK_ABORT; | ||
80 | break; | ||
81 | } | ||
82 | offset += sizeof(blk_t); | ||
83 | } | ||
84 | } else { | ||
85 | for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) { | ||
86 | if (*block_nr == 0) | ||
87 | continue; | ||
88 | flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount, | ||
89 | *ind_block, offset, | ||
90 | ctx->priv_data); | ||
91 | changed |= flags; | ||
92 | if (flags & BLOCK_ABORT) { | ||
93 | ret |= BLOCK_ABORT; | ||
94 | break; | ||
95 | } | ||
96 | offset += sizeof(blk_t); | ||
97 | } | ||
98 | } | ||
99 | if (changed & BLOCK_CHANGED) { | ||
100 | ctx->errcode = ext2fs_write_ind_block(ctx->fs, *ind_block, | ||
101 | ctx->ind_buf); | ||
102 | if (ctx->errcode) | ||
103 | ret |= BLOCK_ERROR | BLOCK_ABORT; | ||
104 | } | ||
105 | if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && | ||
106 | !(ctx->flags & BLOCK_FLAG_DATA_ONLY) && | ||
107 | !(ret & BLOCK_ABORT)) | ||
108 | ret |= (*ctx->func)(ctx->fs, ind_block, | ||
109 | BLOCK_COUNT_IND, ref_block, | ||
110 | ref_offset, ctx->priv_data); | ||
111 | return ret; | ||
112 | } | ||
113 | |||
114 | static int block_iterate_dind(blk_t *dind_block, blk_t ref_block, | ||
115 | int ref_offset, struct block_context *ctx) | ||
116 | { | ||
117 | int ret = 0, changed = 0; | ||
118 | int i, flags, limit, offset; | ||
119 | blk_t *block_nr; | ||
120 | |||
121 | limit = ctx->fs->blocksize >> 2; | ||
122 | if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE | | ||
123 | BLOCK_FLAG_DATA_ONLY))) | ||
124 | ret = (*ctx->func)(ctx->fs, dind_block, | ||
125 | BLOCK_COUNT_DIND, ref_block, | ||
126 | ref_offset, ctx->priv_data); | ||
127 | if (!*dind_block || (ret & BLOCK_ABORT)) { | ||
128 | ctx->bcount += limit*limit; | ||
129 | return ret; | ||
130 | } | ||
131 | if (*dind_block >= ctx->fs->super->s_blocks_count || | ||
132 | *dind_block < ctx->fs->super->s_first_data_block) { | ||
133 | ctx->errcode = EXT2_ET_BAD_DIND_BLOCK; | ||
134 | ret |= BLOCK_ERROR; | ||
135 | return ret; | ||
136 | } | ||
137 | ctx->errcode = ext2fs_read_ind_block(ctx->fs, *dind_block, | ||
138 | ctx->dind_buf); | ||
139 | if (ctx->errcode) { | ||
140 | ret |= BLOCK_ERROR; | ||
141 | return ret; | ||
142 | } | ||
143 | |||
144 | block_nr = (blk_t *) ctx->dind_buf; | ||
145 | offset = 0; | ||
146 | if (ctx->flags & BLOCK_FLAG_APPEND) { | ||
147 | for (i = 0; i < limit; i++, block_nr++) { | ||
148 | flags = block_iterate_ind(block_nr, | ||
149 | *dind_block, offset, | ||
150 | ctx); | ||
151 | changed |= flags; | ||
152 | if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { | ||
153 | ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); | ||
154 | break; | ||
155 | } | ||
156 | offset += sizeof(blk_t); | ||
157 | } | ||
158 | } else { | ||
159 | for (i = 0; i < limit; i++, block_nr++) { | ||
160 | if (*block_nr == 0) { | ||
161 | ctx->bcount += limit; | ||
162 | continue; | ||
163 | } | ||
164 | flags = block_iterate_ind(block_nr, | ||
165 | *dind_block, offset, | ||
166 | ctx); | ||
167 | changed |= flags; | ||
168 | if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { | ||
169 | ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); | ||
170 | break; | ||
171 | } | ||
172 | offset += sizeof(blk_t); | ||
173 | } | ||
174 | } | ||
175 | if (changed & BLOCK_CHANGED) { | ||
176 | ctx->errcode = ext2fs_write_ind_block(ctx->fs, *dind_block, | ||
177 | ctx->dind_buf); | ||
178 | if (ctx->errcode) | ||
179 | ret |= BLOCK_ERROR | BLOCK_ABORT; | ||
180 | } | ||
181 | if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && | ||
182 | !(ctx->flags & BLOCK_FLAG_DATA_ONLY) && | ||
183 | !(ret & BLOCK_ABORT)) | ||
184 | ret |= (*ctx->func)(ctx->fs, dind_block, | ||
185 | BLOCK_COUNT_DIND, ref_block, | ||
186 | ref_offset, ctx->priv_data); | ||
187 | return ret; | ||
188 | } | ||
189 | |||
190 | static int block_iterate_tind(blk_t *tind_block, blk_t ref_block, | ||
191 | int ref_offset, struct block_context *ctx) | ||
192 | { | ||
193 | int ret = 0, changed = 0; | ||
194 | int i, flags, limit, offset; | ||
195 | blk_t *block_nr; | ||
196 | |||
197 | limit = ctx->fs->blocksize >> 2; | ||
198 | if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE | | ||
199 | BLOCK_FLAG_DATA_ONLY))) | ||
200 | ret = (*ctx->func)(ctx->fs, tind_block, | ||
201 | BLOCK_COUNT_TIND, ref_block, | ||
202 | ref_offset, ctx->priv_data); | ||
203 | if (!*tind_block || (ret & BLOCK_ABORT)) { | ||
204 | ctx->bcount += limit*limit*limit; | ||
205 | return ret; | ||
206 | } | ||
207 | if (*tind_block >= ctx->fs->super->s_blocks_count || | ||
208 | *tind_block < ctx->fs->super->s_first_data_block) { | ||
209 | ctx->errcode = EXT2_ET_BAD_TIND_BLOCK; | ||
210 | ret |= BLOCK_ERROR; | ||
211 | return ret; | ||
212 | } | ||
213 | ctx->errcode = ext2fs_read_ind_block(ctx->fs, *tind_block, | ||
214 | ctx->tind_buf); | ||
215 | if (ctx->errcode) { | ||
216 | ret |= BLOCK_ERROR; | ||
217 | return ret; | ||
218 | } | ||
219 | |||
220 | block_nr = (blk_t *) ctx->tind_buf; | ||
221 | offset = 0; | ||
222 | if (ctx->flags & BLOCK_FLAG_APPEND) { | ||
223 | for (i = 0; i < limit; i++, block_nr++) { | ||
224 | flags = block_iterate_dind(block_nr, | ||
225 | *tind_block, | ||
226 | offset, ctx); | ||
227 | changed |= flags; | ||
228 | if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { | ||
229 | ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); | ||
230 | break; | ||
231 | } | ||
232 | offset += sizeof(blk_t); | ||
233 | } | ||
234 | } else { | ||
235 | for (i = 0; i < limit; i++, block_nr++) { | ||
236 | if (*block_nr == 0) { | ||
237 | ctx->bcount += limit*limit; | ||
238 | continue; | ||
239 | } | ||
240 | flags = block_iterate_dind(block_nr, | ||
241 | *tind_block, | ||
242 | offset, ctx); | ||
243 | changed |= flags; | ||
244 | if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { | ||
245 | ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); | ||
246 | break; | ||
247 | } | ||
248 | offset += sizeof(blk_t); | ||
249 | } | ||
250 | } | ||
251 | if (changed & BLOCK_CHANGED) { | ||
252 | ctx->errcode = ext2fs_write_ind_block(ctx->fs, *tind_block, | ||
253 | ctx->tind_buf); | ||
254 | if (ctx->errcode) | ||
255 | ret |= BLOCK_ERROR | BLOCK_ABORT; | ||
256 | } | ||
257 | if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && | ||
258 | !(ctx->flags & BLOCK_FLAG_DATA_ONLY) && | ||
259 | !(ret & BLOCK_ABORT)) | ||
260 | ret |= (*ctx->func)(ctx->fs, tind_block, | ||
261 | BLOCK_COUNT_TIND, ref_block, | ||
262 | ref_offset, ctx->priv_data); | ||
263 | |||
264 | return ret; | ||
265 | } | ||
266 | |||
267 | errcode_t ext2fs_block_iterate2(ext2_filsys fs, | ||
268 | ext2_ino_t ino, | ||
269 | int flags, | ||
270 | char *block_buf, | ||
271 | int (*func)(ext2_filsys fs, | ||
272 | blk_t *blocknr, | ||
273 | e2_blkcnt_t blockcnt, | ||
274 | blk_t ref_blk, | ||
275 | int ref_offset, | ||
276 | void *priv_data), | ||
277 | void *priv_data) | ||
278 | { | ||
279 | int i; | ||
280 | int got_inode = 0; | ||
281 | int ret = 0; | ||
282 | blk_t blocks[EXT2_N_BLOCKS]; /* directory data blocks */ | ||
283 | struct ext2_inode inode; | ||
284 | errcode_t retval; | ||
285 | struct block_context ctx; | ||
286 | int limit; | ||
287 | |||
288 | EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | ||
289 | |||
290 | /* | ||
291 | * Check to see if we need to limit large files | ||
292 | */ | ||
293 | if (flags & BLOCK_FLAG_NO_LARGE) { | ||
294 | ctx.errcode = ext2fs_read_inode(fs, ino, &inode); | ||
295 | if (ctx.errcode) | ||
296 | return ctx.errcode; | ||
297 | got_inode = 1; | ||
298 | if (!LINUX_S_ISDIR(inode.i_mode) && | ||
299 | (inode.i_size_high != 0)) | ||
300 | return EXT2_ET_FILE_TOO_BIG; | ||
301 | } | ||
302 | |||
303 | retval = ext2fs_get_blocks(fs, ino, blocks); | ||
304 | if (retval) | ||
305 | return retval; | ||
306 | |||
307 | limit = fs->blocksize >> 2; | ||
308 | |||
309 | ctx.fs = fs; | ||
310 | ctx.func = func; | ||
311 | ctx.priv_data = priv_data; | ||
312 | ctx.flags = flags; | ||
313 | ctx.bcount = 0; | ||
314 | if (block_buf) { | ||
315 | ctx.ind_buf = block_buf; | ||
316 | } else { | ||
317 | retval = ext2fs_get_mem(fs->blocksize * 3, &ctx.ind_buf); | ||
318 | if (retval) | ||
319 | return retval; | ||
320 | } | ||
321 | ctx.dind_buf = ctx.ind_buf + fs->blocksize; | ||
322 | ctx.tind_buf = ctx.dind_buf + fs->blocksize; | ||
323 | |||
324 | /* | ||
325 | * Iterate over the HURD translator block (if present) | ||
326 | */ | ||
327 | if ((fs->super->s_creator_os == EXT2_OS_HURD) && | ||
328 | !(flags & BLOCK_FLAG_DATA_ONLY)) { | ||
329 | ctx.errcode = ext2fs_read_inode(fs, ino, &inode); | ||
330 | if (ctx.errcode) | ||
331 | goto abort_exit; | ||
332 | got_inode = 1; | ||
333 | if (inode.osd1.hurd1.h_i_translator) { | ||
334 | ret |= (*ctx.func)(fs, | ||
335 | &inode.osd1.hurd1.h_i_translator, | ||
336 | BLOCK_COUNT_TRANSLATOR, | ||
337 | 0, 0, priv_data); | ||
338 | if (ret & BLOCK_ABORT) | ||
339 | goto abort_exit; | ||
340 | } | ||
341 | } | ||
342 | |||
343 | /* | ||
344 | * Iterate over normal data blocks | ||
345 | */ | ||
346 | for (i = 0; i < EXT2_NDIR_BLOCKS ; i++, ctx.bcount++) { | ||
347 | if (blocks[i] || (flags & BLOCK_FLAG_APPEND)) { | ||
348 | ret |= (*ctx.func)(fs, &blocks[i], | ||
349 | ctx.bcount, 0, i, priv_data); | ||
350 | if (ret & BLOCK_ABORT) | ||
351 | goto abort_exit; | ||
352 | } | ||
353 | } | ||
354 | if (*(blocks + EXT2_IND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) { | ||
355 | ret |= block_iterate_ind(blocks + EXT2_IND_BLOCK, | ||
356 | 0, EXT2_IND_BLOCK, &ctx); | ||
357 | if (ret & BLOCK_ABORT) | ||
358 | goto abort_exit; | ||
359 | } else | ||
360 | ctx.bcount += limit; | ||
361 | if (*(blocks + EXT2_DIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) { | ||
362 | ret |= block_iterate_dind(blocks + EXT2_DIND_BLOCK, | ||
363 | 0, EXT2_DIND_BLOCK, &ctx); | ||
364 | if (ret & BLOCK_ABORT) | ||
365 | goto abort_exit; | ||
366 | } else | ||
367 | ctx.bcount += limit * limit; | ||
368 | if (*(blocks + EXT2_TIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) { | ||
369 | ret |= block_iterate_tind(blocks + EXT2_TIND_BLOCK, | ||
370 | 0, EXT2_TIND_BLOCK, &ctx); | ||
371 | if (ret & BLOCK_ABORT) | ||
372 | goto abort_exit; | ||
373 | } | ||
374 | |||
375 | abort_exit: | ||
376 | if (ret & BLOCK_CHANGED) { | ||
377 | if (!got_inode) { | ||
378 | retval = ext2fs_read_inode(fs, ino, &inode); | ||
379 | if (retval) | ||
380 | return retval; | ||
381 | } | ||
382 | for (i=0; i < EXT2_N_BLOCKS; i++) | ||
383 | inode.i_block[i] = blocks[i]; | ||
384 | retval = ext2fs_write_inode(fs, ino, &inode); | ||
385 | if (retval) | ||
386 | return retval; | ||
387 | } | ||
388 | |||
389 | if (!block_buf) | ||
390 | ext2fs_free_mem(&ctx.ind_buf); | ||
391 | |||
392 | return (ret & BLOCK_ERROR) ? ctx.errcode : 0; | ||
393 | } | ||
394 | |||
395 | /* | ||
396 | * Emulate the old ext2fs_block_iterate function! | ||
397 | */ | ||
398 | |||
399 | struct xlate { | ||
400 | int (*func)(ext2_filsys fs, | ||
401 | blk_t *blocknr, | ||
402 | int bcount, | ||
403 | void *priv_data); | ||
404 | void *real_private; | ||
405 | }; | ||
406 | |||
407 | #ifdef __TURBOC__ | ||
408 | # pragma argsused | ||
409 | #endif | ||
410 | static int xlate_func(ext2_filsys fs, blk_t *blocknr, e2_blkcnt_t blockcnt, | ||
411 | blk_t ref_block EXT2FS_ATTR((unused)), | ||
412 | int ref_offset EXT2FS_ATTR((unused)), | ||
413 | void *priv_data) | ||
414 | { | ||
415 | struct xlate *xl = (struct xlate *) priv_data; | ||
416 | |||
417 | return (*xl->func)(fs, blocknr, (int) blockcnt, xl->real_private); | ||
418 | } | ||
419 | |||
420 | errcode_t ext2fs_block_iterate(ext2_filsys fs, | ||
421 | ext2_ino_t ino, | ||
422 | int flags, | ||
423 | char *block_buf, | ||
424 | int (*func)(ext2_filsys fs, | ||
425 | blk_t *blocknr, | ||
426 | int blockcnt, | ||
427 | void *priv_data), | ||
428 | void *priv_data) | ||
429 | { | ||
430 | struct xlate xl; | ||
431 | |||
432 | xl.real_private = priv_data; | ||
433 | xl.func = func; | ||
434 | |||
435 | return ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_NO_LARGE | flags, | ||
436 | block_buf, xlate_func, &xl); | ||
437 | } | ||
438 | |||