1 /*
2 * inode.c --- utility routines to read and write inodes
3 *
4 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
5 *
6 * %Begin-Header%
7 * This file may be redistributed under the terms of the GNU Library
8 * General Public License, version 2.
9 * %End-Header%
10 */
11
12 #include "config.h"
13 #include <stdio.h>
14 #include <string.h>
15 #if HAVE_UNISTD_H
16 #include <unistd.h>
17 #endif
18 #if HAVE_ERRNO_H
19 #include <errno.h>
20 #endif
21 #include <time.h>
22 #if HAVE_SYS_STAT_H
23 #include <sys/stat.h>
24 #endif
25 #if HAVE_SYS_TYPES_H
26 #include <sys/types.h>
27 #endif
28
29 #include "ext2_fs.h"
30 #include "ext2fsP.h"
31 #include "e2image.h"
32
33 #define IBLOCK_STATUS_CSUMS_OK 1
34 #define IBLOCK_STATUS_INSANE 2
35 #define SCAN_BLOCK_STATUS(scan) ((scan)->temp_buffer + (scan)->inode_size)
36
37 struct ext2_struct_inode_scan {
38 errcode_t magic;
39 ext2_filsys fs;
40 ext2_ino_t current_inode;
41 blk64_t current_block;
42 dgrp_t current_group;
43 ext2_ino_t inodes_left;
44 blk_t blocks_left;
45 dgrp_t groups_left;
46 blk_t inode_buffer_blocks;
47 char * inode_buffer;
48 int inode_size;
49 char * ptr;
50 int bytes_left;
51 char *temp_buffer;
52 errcode_t (*done_group)(ext2_filsys fs,
53 ext2_inode_scan scan,
54 dgrp_t group,
55 void * priv_data);
56 void * done_group_data;
57 int bad_block_ptr;
58 int scan_flags;
59 int reserved[6];
60 };
61
62 /*
63 * This routine flushes the icache, if it exists.
64 */
ext2fs_flush_icache(ext2_filsys fs)65 errcode_t ext2fs_flush_icache(ext2_filsys fs)
66 {
67 unsigned i;
68
69 if (!fs->icache)
70 return 0;
71
72 for (i=0; i < fs->icache->cache_size; i++)
73 fs->icache->cache[i].ino = 0;
74
75 fs->icache->buffer_blk = 0;
76 return 0;
77 }
78
79 /*
80 * Free the inode cache structure
81 */
ext2fs_free_inode_cache(struct ext2_inode_cache * icache)82 void ext2fs_free_inode_cache(struct ext2_inode_cache *icache)
83 {
84 unsigned i;
85
86 if (--icache->refcount)
87 return;
88 if (icache->buffer)
89 ext2fs_free_mem(&icache->buffer);
90 for (i = 0; i < icache->cache_size; i++)
91 ext2fs_free_mem(&icache->cache[i].inode);
92 if (icache->cache)
93 ext2fs_free_mem(&icache->cache);
94 icache->buffer_blk = 0;
95 ext2fs_free_mem(&icache);
96 }
97
ext2fs_create_inode_cache(ext2_filsys fs,unsigned int cache_size)98 errcode_t ext2fs_create_inode_cache(ext2_filsys fs, unsigned int cache_size)
99 {
100 unsigned i;
101 errcode_t retval;
102
103 if (fs->icache)
104 return 0;
105 retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache), &fs->icache);
106 if (retval)
107 return retval;
108
109 memset(fs->icache, 0, sizeof(struct ext2_inode_cache));
110 retval = ext2fs_get_mem(fs->blocksize, &fs->icache->buffer);
111 if (retval)
112 goto errout;
113
114 fs->icache->buffer_blk = 0;
115 fs->icache->cache_last = -1;
116 fs->icache->cache_size = cache_size;
117 fs->icache->refcount = 1;
118 retval = ext2fs_get_array(fs->icache->cache_size,
119 sizeof(struct ext2_inode_cache_ent),
120 &fs->icache->cache);
121 if (retval)
122 goto errout;
123
124 for (i = 0; i < fs->icache->cache_size; i++) {
125 retval = ext2fs_get_mem(EXT2_INODE_SIZE(fs->super),
126 &fs->icache->cache[i].inode);
127 if (retval)
128 goto errout;
129 }
130
131 ext2fs_flush_icache(fs);
132 return 0;
133 errout:
134 ext2fs_free_inode_cache(fs->icache);
135 fs->icache = 0;
136 return retval;
137 }
138
ext2fs_open_inode_scan(ext2_filsys fs,int buffer_blocks,ext2_inode_scan * ret_scan)139 errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
140 ext2_inode_scan *ret_scan)
141 {
142 ext2_inode_scan scan;
143 errcode_t retval;
144 errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks);
145
146 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
147
148 if (ext2fs_has_feature_journal_dev(fs->super))
149 return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP;
150
151 if (fs->blocksize < 1024)
152 return EXT2_FILSYS_CORRUPTED; /* Should never happen */
153
154 /*
155 * If fs->badblocks isn't set, then set it --- since the inode
156 * scanning functions require it.
157 */
158 if (fs->badblocks == 0) {
159 /*
160 * Temporarily save fs->get_blocks and set it to zero,
161 * for compatibility with old e2fsck's.
162 */
163 save_get_blocks = fs->get_blocks;
164 fs->get_blocks = 0;
165 retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
166 if (retval && fs->badblocks) {
167 ext2fs_badblocks_list_free(fs->badblocks);
168 fs->badblocks = 0;
169 }
170 fs->get_blocks = save_get_blocks;
171 }
172
173 retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan), &scan);
174 if (retval)
175 return retval;
176 memset(scan, 0, sizeof(struct ext2_struct_inode_scan));
177
178 scan->magic = EXT2_ET_MAGIC_INODE_SCAN;
179 scan->fs = fs;
180 scan->inode_size = EXT2_INODE_SIZE(fs->super);
181 scan->bytes_left = 0;
182 scan->current_group = 0;
183 scan->groups_left = fs->group_desc_count - 1;
184 scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks :
185 EXT2_INODE_SCAN_DEFAULT_BUFFER_BLOCKS;
186 scan->current_block = ext2fs_inode_table_loc(scan->fs,
187 scan->current_group);
188 if (scan->current_block &&
189 ((scan->current_block < fs->super->s_first_data_block) ||
190 (scan->current_block + fs->inode_blocks_per_group - 1 >=
191 ext2fs_blocks_count(fs->super)))) {
192 ext2fs_free_mem(&scan);
193 return EXT2_ET_GDESC_BAD_INODE_TABLE;
194 }
195
196 scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
197 scan->blocks_left = scan->fs->inode_blocks_per_group;
198 if (ext2fs_has_group_desc_csum(fs)) {
199 __u32 unused = ext2fs_bg_itable_unused(fs, scan->current_group);
200 if (scan->inodes_left > unused)
201 scan->inodes_left -= unused;
202 else
203 scan->inodes_left = 0;
204 scan->blocks_left =
205 (scan->inodes_left +
206 (fs->blocksize / scan->inode_size - 1)) *
207 scan->inode_size / fs->blocksize;
208 }
209 retval = io_channel_alloc_buf(fs->io, scan->inode_buffer_blocks,
210 &scan->inode_buffer);
211 scan->done_group = 0;
212 scan->done_group_data = 0;
213 scan->bad_block_ptr = 0;
214 if (retval) {
215 ext2fs_free_mem(&scan);
216 return retval;
217 }
218 retval = ext2fs_get_mem(scan->inode_size + scan->inode_buffer_blocks,
219 &scan->temp_buffer);
220 if (retval) {
221 ext2fs_free_mem(&scan->inode_buffer);
222 ext2fs_free_mem(&scan);
223 return retval;
224 }
225 memset(SCAN_BLOCK_STATUS(scan), 0, scan->inode_buffer_blocks);
226 if (scan->fs->badblocks && scan->fs->badblocks->num)
227 scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS;
228 if (ext2fs_has_group_desc_csum(fs))
229 scan->scan_flags |= EXT2_SF_DO_LAZY;
230 *ret_scan = scan;
231 return 0;
232 }
233
ext2fs_close_inode_scan(ext2_inode_scan scan)234 void ext2fs_close_inode_scan(ext2_inode_scan scan)
235 {
236 if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
237 return;
238
239 ext2fs_free_mem(&scan->inode_buffer);
240 scan->inode_buffer = NULL;
241 ext2fs_free_mem(&scan->temp_buffer);
242 scan->temp_buffer = NULL;
243 ext2fs_free_mem(&scan);
244 return;
245 }
246
ext2fs_set_inode_callback(ext2_inode_scan scan,errcode_t (* done_group)(ext2_filsys fs,ext2_inode_scan scan,dgrp_t group,void * priv_data),void * done_group_data)247 void ext2fs_set_inode_callback(ext2_inode_scan scan,
248 errcode_t (*done_group)(ext2_filsys fs,
249 ext2_inode_scan scan,
250 dgrp_t group,
251 void * priv_data),
252 void *done_group_data)
253 {
254 if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
255 return;
256
257 scan->done_group = done_group;
258 scan->done_group_data = done_group_data;
259 }
260
ext2fs_inode_scan_flags(ext2_inode_scan scan,int set_flags,int clear_flags)261 int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
262 int clear_flags)
263 {
264 int old_flags;
265
266 if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
267 return 0;
268
269 old_flags = scan->scan_flags;
270 scan->scan_flags &= ~clear_flags;
271 scan->scan_flags |= set_flags;
272 return old_flags;
273 }
274
275 /*
276 * This function is called by ext2fs_get_next_inode when it needs to
277 * get ready to read in a new blockgroup.
278 */
get_next_blockgroup(ext2_inode_scan scan)279 static errcode_t get_next_blockgroup(ext2_inode_scan scan)
280 {
281 ext2_filsys fs = scan->fs;
282
283 scan->current_group++;
284 scan->groups_left--;
285
286 scan->current_block = ext2fs_inode_table_loc(scan->fs,
287 scan->current_group);
288 scan->current_inode = scan->current_group *
289 EXT2_INODES_PER_GROUP(fs->super);
290
291 scan->bytes_left = 0;
292 scan->inodes_left = EXT2_INODES_PER_GROUP(fs->super);
293 scan->blocks_left = fs->inode_blocks_per_group;
294 if (ext2fs_has_group_desc_csum(fs)) {
295 __u32 unused = ext2fs_bg_itable_unused(fs, scan->current_group);
296 if (scan->inodes_left > unused)
297 scan->inodes_left -= unused;
298 else
299 scan->inodes_left = 0;
300 scan->blocks_left =
301 (scan->inodes_left +
302 (fs->blocksize / scan->inode_size - 1)) *
303 scan->inode_size / fs->blocksize;
304 }
305 if (scan->current_block &&
306 ((scan->current_block < fs->super->s_first_data_block) ||
307 (scan->current_block + fs->inode_blocks_per_group - 1 >=
308 ext2fs_blocks_count(fs->super))))
309 return EXT2_ET_GDESC_BAD_INODE_TABLE;
310 return 0;
311 }
312
ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,int group)313 errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
314 int group)
315 {
316 scan->current_group = group - 1;
317 scan->groups_left = scan->fs->group_desc_count - group;
318 scan->bad_block_ptr = 0;
319 return get_next_blockgroup(scan);
320 }
321
322 /*
323 * This function is called by get_next_blocks() to check for bad
324 * blocks in the inode table.
325 *
326 * This function assumes that badblocks_list->list is sorted in
327 * increasing order.
328 */
check_for_inode_bad_blocks(ext2_inode_scan scan,blk64_t * num_blocks)329 static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan,
330 blk64_t *num_blocks)
331 {
332 blk64_t blk = scan->current_block;
333 badblocks_list bb = scan->fs->badblocks;
334
335 /*
336 * If the inode table is missing, then obviously there are no
337 * bad blocks. :-)
338 */
339 if (blk == 0)
340 return 0;
341
342 /* Make sure bad_block_ptr is still valid */
343 if (scan->bad_block_ptr >= bb->num) {
344 scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
345 return 0;
346 }
347
348 /*
349 * If the current block is greater than the bad block listed
350 * in the bad block list, then advance the pointer until this
351 * is no longer the case. If we run out of bad blocks, then
352 * we don't need to do any more checking!
353 */
354 while (blk > bb->list[scan->bad_block_ptr]) {
355 if (++scan->bad_block_ptr >= bb->num) {
356 scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
357 return 0;
358 }
359 }
360
361 /*
362 * If the current block is equal to the bad block listed in
363 * the bad block list, then handle that one block specially.
364 * (We could try to handle runs of bad blocks, but that
365 * only increases CPU efficiency by a small amount, at the
366 * expense of a huge expense of code complexity, and for an
367 * uncommon case at that.)
368 */
369 if (blk == bb->list[scan->bad_block_ptr]) {
370 scan->scan_flags |= EXT2_SF_BAD_INODE_BLK;
371 *num_blocks = 1;
372 if (++scan->bad_block_ptr >= bb->num)
373 scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
374 return 0;
375 }
376
377 /*
378 * If there is a bad block in the range that we're about to
379 * read in, adjust the number of blocks to read so that we we
380 * don't read in the bad block. (Then the next block to read
381 * will be the bad block, which is handled in the above case.)
382 */
383 if ((blk + *num_blocks) > bb->list[scan->bad_block_ptr])
384 *num_blocks = (int) (bb->list[scan->bad_block_ptr] - blk);
385
386 return 0;
387 }
388
block_map_looks_insane(ext2_filsys fs,struct ext2_inode_large * inode)389 static int block_map_looks_insane(ext2_filsys fs,
390 struct ext2_inode_large *inode)
391 {
392 unsigned int i, bad;
393
394 /* We're only interested in block mapped files, dirs, and symlinks */
395 if ((inode->i_flags & EXT4_INLINE_DATA_FL) ||
396 (inode->i_flags & EXT4_EXTENTS_FL))
397 return 0;
398 if (!LINUX_S_ISREG(inode->i_mode) &&
399 !LINUX_S_ISLNK(inode->i_mode) &&
400 !LINUX_S_ISDIR(inode->i_mode))
401 return 0;
402 if (LINUX_S_ISLNK(inode->i_mode) &&
403 EXT2_I_SIZE(inode) <= sizeof(inode->i_block))
404 return 0;
405
406 /* Unused inodes probably aren't insane */
407 if (inode->i_links_count == 0)
408 return 0;
409
410 /* See if more than half the block maps are insane */
411 for (i = 0, bad = 0; i < EXT2_N_BLOCKS; i++)
412 if (inode->i_block[i] != 0 &&
413 (inode->i_block[i] < fs->super->s_first_data_block ||
414 inode->i_block[i] >= ext2fs_blocks_count(fs->super)))
415 bad++;
416 return bad > EXT2_N_BLOCKS / 2;
417 }
418
extent_head_looks_insane(struct ext2_inode_large * inode)419 static int extent_head_looks_insane(struct ext2_inode_large *inode)
420 {
421 if (!(inode->i_flags & EXT4_EXTENTS_FL) ||
422 ext2fs_extent_header_verify(inode->i_block,
423 sizeof(inode->i_block)) == 0)
424 return 0;
425 return 1;
426 }
427
428 /*
429 * Check all the inodes that we just read into the buffer. Record what we
430 * find here -- currently, we can observe that all checksums are ok; more
431 * than half the inodes are insane; or no conclusions at all.
432 */
check_inode_block_sanity(ext2_inode_scan scan,blk64_t num_blocks)433 static void check_inode_block_sanity(ext2_inode_scan scan, blk64_t num_blocks)
434 {
435 ext2_ino_t ino, inodes_to_scan;
436 unsigned int badness, checksum_failures;
437 unsigned int inodes_in_buf, inodes_per_block;
438 char *p;
439 struct ext2_inode_large *inode;
440 char *block_status;
441 unsigned int blk, bad_csum;
442
443 if (!(scan->scan_flags & EXT2_SF_WARN_GARBAGE_INODES))
444 return;
445
446 inodes_to_scan = scan->inodes_left;
447 inodes_in_buf = num_blocks * scan->fs->blocksize / scan->inode_size;
448 if (inodes_to_scan > inodes_in_buf)
449 inodes_to_scan = inodes_in_buf;
450
451 p = (char *) scan->inode_buffer;
452 ino = scan->current_inode + 1;
453 checksum_failures = badness = 0;
454 block_status = SCAN_BLOCK_STATUS(scan);
455 memset(block_status, 0, scan->inode_buffer_blocks);
456 inodes_per_block = EXT2_INODES_PER_BLOCK(scan->fs->super);
457
458 if (inodes_per_block < 2)
459 return;
460
461 #ifdef WORDS_BIGENDIAN
462 if (ext2fs_get_mem(EXT2_INODE_SIZE(scan->fs->super), &inode))
463 return;
464 #endif
465
466 while (inodes_to_scan > 0) {
467 blk = (p - (char *)scan->inode_buffer) / scan->fs->blocksize;
468 bad_csum = ext2fs_inode_csum_verify(scan->fs, ino,
469 (struct ext2_inode_large *) p) == 0;
470
471 #ifdef WORDS_BIGENDIAN
472 ext2fs_swap_inode_full(scan->fs,
473 (struct ext2_inode_large *) inode,
474 (struct ext2_inode_large *) p,
475 0, EXT2_INODE_SIZE(scan->fs->super));
476 #else
477 inode = (struct ext2_inode_large *) p;
478 #endif
479
480 /* Is this inode insane? */
481 if (bad_csum) {
482 checksum_failures++;
483 badness++;
484 } else if (extent_head_looks_insane(inode) ||
485 block_map_looks_insane(scan->fs, inode))
486 badness++;
487
488 /* If more than half are insane, declare the whole block bad */
489 if (badness > inodes_per_block / 2) {
490 unsigned int ino_adj;
491
492 block_status[blk] |= IBLOCK_STATUS_INSANE;
493 ino_adj = inodes_per_block -
494 ((ino - 1) % inodes_per_block);
495 if (ino_adj > inodes_to_scan)
496 ino_adj = inodes_to_scan;
497 inodes_to_scan -= ino_adj;
498 p += scan->inode_size * ino_adj;
499 ino += ino_adj;
500 checksum_failures = badness = 0;
501 continue;
502 }
503
504 if ((ino % inodes_per_block) == 0) {
505 if (checksum_failures == 0)
506 block_status[blk] |= IBLOCK_STATUS_CSUMS_OK;
507 checksum_failures = badness = 0;
508 }
509 inodes_to_scan--;
510 p += scan->inode_size;
511 ino++;
512 };
513
514 #ifdef WORDS_BIGENDIAN
515 ext2fs_free_mem(&inode);
516 #endif
517 }
518
519 /*
520 * This function is called by ext2fs_get_next_inode when it needs to
521 * read in more blocks from the current blockgroup's inode table.
522 */
get_next_blocks(ext2_inode_scan scan)523 static errcode_t get_next_blocks(ext2_inode_scan scan)
524 {
525 blk64_t num_blocks;
526 errcode_t retval;
527
528 /*
529 * Figure out how many blocks to read; we read at most
530 * inode_buffer_blocks, and perhaps less if there aren't that
531 * many blocks left to read.
532 */
533 num_blocks = scan->inode_buffer_blocks;
534 if (num_blocks > scan->blocks_left)
535 num_blocks = scan->blocks_left;
536
537 /*
538 * If the past block "read" was a bad block, then mark the
539 * left-over extra bytes as also being bad.
540 */
541 if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) {
542 if (scan->bytes_left)
543 scan->scan_flags |= EXT2_SF_BAD_EXTRA_BYTES;
544 scan->scan_flags &= ~EXT2_SF_BAD_INODE_BLK;
545 }
546
547 /*
548 * Do inode bad block processing, if necessary.
549 */
550 if (scan->scan_flags & EXT2_SF_CHK_BADBLOCKS) {
551 retval = check_for_inode_bad_blocks(scan, &num_blocks);
552 if (retval)
553 return retval;
554 }
555
556 if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) ||
557 (scan->current_block == 0)) {
558 memset(scan->inode_buffer, 0,
559 (size_t) num_blocks * scan->fs->blocksize);
560 } else {
561 retval = io_channel_read_blk64(scan->fs->io,
562 scan->current_block,
563 (int) num_blocks,
564 scan->inode_buffer);
565 if (retval)
566 return EXT2_ET_NEXT_INODE_READ;
567 }
568 check_inode_block_sanity(scan, num_blocks);
569
570 scan->ptr = scan->inode_buffer;
571 scan->bytes_left = num_blocks * scan->fs->blocksize;
572
573 scan->blocks_left -= num_blocks;
574 if (scan->current_block)
575 scan->current_block += num_blocks;
576
577 return 0;
578 }
579
580 #if 0
581 /*
582 * Returns 1 if the entire inode_buffer has a non-zero size and
583 * contains all zeros. (Not just deleted inodes, since that means
584 * that part of the inode table was used at one point; we want all
585 * zeros, which means that the inode table is pristine.)
586 */
587 static inline int is_empty_scan(ext2_inode_scan scan)
588 {
589 int i;
590
591 if (scan->bytes_left == 0)
592 return 0;
593
594 for (i=0; i < scan->bytes_left; i++)
595 if (scan->ptr[i])
596 return 0;
597 return 1;
598 }
599 #endif
600
ext2fs_get_next_inode_full(ext2_inode_scan scan,ext2_ino_t * ino,struct ext2_inode * inode,int bufsize)601 errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, ext2_ino_t *ino,
602 struct ext2_inode *inode, int bufsize)
603 {
604 errcode_t retval;
605 int extra_bytes = 0;
606 int length;
607 struct ext2_inode_large *iptr = (struct ext2_inode_large *)inode;
608 char *iblock_status;
609 unsigned int iblk;
610
611 EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN);
612 length = EXT2_INODE_SIZE(scan->fs->super);
613 iblock_status = SCAN_BLOCK_STATUS(scan);
614
615 /*
616 * Do we need to start reading a new block group?
617 */
618 if (scan->inodes_left <= 0) {
619 force_new_group:
620 if (scan->done_group) {
621 retval = (scan->done_group)
622 (scan->fs, scan, scan->current_group,
623 scan->done_group_data);
624 if (retval)
625 return retval;
626 }
627 if (scan->groups_left <= 0) {
628 *ino = 0;
629 return 0;
630 }
631 retval = get_next_blockgroup(scan);
632 if (retval)
633 return retval;
634 }
635 /*
636 * These checks are done outside the above if statement so
637 * they can be done for block group #0.
638 */
639 if ((scan->scan_flags & EXT2_SF_DO_LAZY) &&
640 (ext2fs_bg_flags_test(scan->fs, scan->current_group, EXT2_BG_INODE_UNINIT)
641 ))
642 goto force_new_group;
643 if (scan->inodes_left == 0)
644 goto force_new_group;
645 if (scan->current_block == 0) {
646 if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) {
647 goto force_new_group;
648 } else
649 return EXT2_ET_MISSING_INODE_TABLE;
650 }
651
652
653 /*
654 * Have we run out of space in the inode buffer? If so, we
655 * need to read in more blocks.
656 */
657 if (scan->bytes_left < scan->inode_size) {
658 if (scan->bytes_left)
659 memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left);
660 extra_bytes = scan->bytes_left;
661
662 retval = get_next_blocks(scan);
663 if (retval)
664 return retval;
665 #if 0
666 /*
667 * XXX test Need check for used inode somehow.
668 * (Note: this is hard.)
669 */
670 if (is_empty_scan(scan))
671 goto force_new_group;
672 #endif
673 }
674
675 if (bufsize < length) {
676 retval = ext2fs_get_mem(length, &iptr);
677 if (retval)
678 return retval;
679 }
680
681 retval = 0;
682 iblk = scan->current_inode % EXT2_INODES_PER_GROUP(scan->fs->super) /
683 EXT2_INODES_PER_BLOCK(scan->fs->super) %
684 scan->inode_buffer_blocks;
685 if (extra_bytes) {
686 memcpy(scan->temp_buffer+extra_bytes, scan->ptr,
687 scan->inode_size - extra_bytes);
688 scan->ptr += scan->inode_size - extra_bytes;
689 scan->bytes_left -= scan->inode_size - extra_bytes;
690
691 /* Verify the inode checksum. */
692 if (!(iblock_status[iblk] & IBLOCK_STATUS_CSUMS_OK) &&
693 !(scan->fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
694 !ext2fs_inode_csum_verify(scan->fs, scan->current_inode + 1,
695 (struct ext2_inode_large *)scan->temp_buffer))
696 retval = EXT2_ET_INODE_CSUM_INVALID;
697
698 #ifdef WORDS_BIGENDIAN
699 memset(iptr, 0, length);
700 ext2fs_swap_inode_full(scan->fs,
701 (struct ext2_inode_large *) iptr,
702 (struct ext2_inode_large *) scan->temp_buffer,
703 0, length);
704 #else
705 memcpy(iptr, scan->temp_buffer, length);
706 #endif
707 if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES)
708 retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
709 scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES;
710 } else {
711 /* Verify the inode checksum. */
712 if (!(iblock_status[iblk] & IBLOCK_STATUS_CSUMS_OK) &&
713 !(scan->fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
714 !ext2fs_inode_csum_verify(scan->fs, scan->current_inode + 1,
715 (struct ext2_inode_large *)scan->ptr))
716 retval = EXT2_ET_INODE_CSUM_INVALID;
717
718 #ifdef WORDS_BIGENDIAN
719 memset(iptr, 0, length);
720 ext2fs_swap_inode_full(scan->fs,
721 (struct ext2_inode_large *) iptr,
722 (struct ext2_inode_large *) scan->ptr,
723 0, length);
724 #else
725 memcpy(iptr, scan->ptr, length);
726 #endif
727 scan->ptr += scan->inode_size;
728 scan->bytes_left -= scan->inode_size;
729 if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK)
730 retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
731 }
732 if ((iblock_status[iblk] & IBLOCK_STATUS_INSANE) &&
733 (retval == 0 || retval == EXT2_ET_INODE_CSUM_INVALID))
734 retval = EXT2_ET_INODE_IS_GARBAGE;
735
736 scan->inodes_left--;
737 scan->current_inode++;
738 *ino = scan->current_inode;
739 if (iptr != (struct ext2_inode_large *)inode) {
740 memcpy(inode, iptr, bufsize);
741 ext2fs_free_mem(&iptr);
742 }
743 return retval;
744 }
745
ext2fs_get_next_inode(ext2_inode_scan scan,ext2_ino_t * ino,struct ext2_inode * inode)746 errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino,
747 struct ext2_inode *inode)
748 {
749 return ext2fs_get_next_inode_full(scan, ino, inode,
750 sizeof(struct ext2_inode));
751 }
752
753 /*
754 * Functions to read and write a single inode.
755 */
ext2fs_read_inode2(ext2_filsys fs,ext2_ino_t ino,struct ext2_inode * inode,int bufsize,int flags)756 errcode_t ext2fs_read_inode2(ext2_filsys fs, ext2_ino_t ino,
757 struct ext2_inode * inode, int bufsize,
758 int flags)
759 {
760 blk64_t block_nr;
761 dgrp_t group;
762 unsigned long block, offset;
763 char *ptr;
764 errcode_t retval;
765 unsigned i;
766 int clen, inodes_per_block;
767 io_channel io;
768 int length = EXT2_INODE_SIZE(fs->super);
769 struct ext2_inode_large *iptr;
770 int cache_slot, fail_csum;
771
772 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
773
774 if (ext2fs_has_feature_journal_dev(fs->super))
775 return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP;
776
777 if (fs->blocksize < 1024)
778 return EXT2_FILSYS_CORRUPTED; /* Should never happen */
779
780 /* Check to see if user has an override function */
781 if (fs->read_inode &&
782 ((bufsize == sizeof(struct ext2_inode)) ||
783 (EXT2_INODE_SIZE(fs->super) == sizeof(struct ext2_inode)))) {
784 retval = (fs->read_inode)(fs, ino, inode);
785 if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
786 return retval;
787 }
788 if ((ino == 0) || (ino > fs->super->s_inodes_count))
789 return EXT2_ET_BAD_INODE_NUM;
790 /* Create inode cache if not present */
791 if (!fs->icache) {
792 retval = ext2fs_create_inode_cache(fs, 4);
793 if (retval)
794 return retval;
795 }
796 /* Check to see if it's in the inode cache */
797 for (i = 0; i < fs->icache->cache_size; i++) {
798 if (fs->icache->cache[i].ino == ino) {
799 memcpy(inode, fs->icache->cache[i].inode,
800 (bufsize > length) ? length : bufsize);
801 return 0;
802 }
803 }
804 if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
805 inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super);
806 block_nr = ext2fs_le32_to_cpu(fs->image_header->offset_inode) / fs->blocksize;
807 block_nr += (ino - 1) / inodes_per_block;
808 offset = ((ino - 1) % inodes_per_block) *
809 EXT2_INODE_SIZE(fs->super);
810 io = fs->image_io;
811 } else {
812 group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
813 if (group > fs->group_desc_count)
814 return EXT2_ET_BAD_INODE_NUM;
815 offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
816 EXT2_INODE_SIZE(fs->super);
817 block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
818 block_nr = ext2fs_inode_table_loc(fs, group);
819 if (!block_nr)
820 return EXT2_ET_MISSING_INODE_TABLE;
821 if ((block_nr < fs->super->s_first_data_block) ||
822 (block_nr + fs->inode_blocks_per_group - 1 >=
823 ext2fs_blocks_count(fs->super)))
824 return EXT2_ET_GDESC_BAD_INODE_TABLE;
825 block_nr += block;
826 io = fs->io;
827 }
828 offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
829
830 cache_slot = (fs->icache->cache_last + 1) % fs->icache->cache_size;
831 iptr = (struct ext2_inode_large *)fs->icache->cache[cache_slot].inode;
832
833 ptr = (char *) iptr;
834 while (length) {
835 clen = length;
836 if ((offset + length) > fs->blocksize)
837 clen = fs->blocksize - offset;
838
839 if (block_nr != fs->icache->buffer_blk) {
840 retval = io_channel_read_blk64(io, block_nr, 1,
841 fs->icache->buffer);
842 if (retval)
843 return retval;
844 fs->icache->buffer_blk = block_nr;
845 }
846
847 memcpy(ptr, ((char *) fs->icache->buffer) + (unsigned) offset,
848 clen);
849
850 offset = 0;
851 length -= clen;
852 ptr += clen;
853 block_nr++;
854 }
855 length = EXT2_INODE_SIZE(fs->super);
856
857 /* Verify the inode checksum. */
858 fail_csum = !ext2fs_inode_csum_verify(fs, ino, iptr);
859
860 #ifdef WORDS_BIGENDIAN
861 ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) iptr,
862 (struct ext2_inode_large *) iptr,
863 0, length);
864 #endif
865
866 /* Update the inode cache bookkeeping */
867 if (!fail_csum) {
868 fs->icache->cache_last = cache_slot;
869 fs->icache->cache[cache_slot].ino = ino;
870 }
871 memcpy(inode, iptr, (bufsize > length) ? length : bufsize);
872
873 if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
874 !(flags & READ_INODE_NOCSUM) && fail_csum)
875 return EXT2_ET_INODE_CSUM_INVALID;
876
877 return 0;
878 }
879
ext2fs_read_inode_full(ext2_filsys fs,ext2_ino_t ino,struct ext2_inode * inode,int bufsize)880 errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
881 struct ext2_inode * inode, int bufsize)
882 {
883 return ext2fs_read_inode2(fs, ino, inode, bufsize, 0);
884 }
885
ext2fs_read_inode(ext2_filsys fs,ext2_ino_t ino,struct ext2_inode * inode)886 errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino,
887 struct ext2_inode * inode)
888 {
889 return ext2fs_read_inode2(fs, ino, inode,
890 sizeof(struct ext2_inode), 0);
891 }
892
ext2fs_write_inode2(ext2_filsys fs,ext2_ino_t ino,struct ext2_inode * inode,int bufsize,int flags)893 errcode_t ext2fs_write_inode2(ext2_filsys fs, ext2_ino_t ino,
894 struct ext2_inode * inode, int bufsize,
895 int flags)
896 {
897 blk64_t block_nr;
898 dgrp_t group;
899 unsigned long block, offset;
900 errcode_t retval = 0;
901 struct ext2_inode_large *w_inode;
902 char *ptr;
903 unsigned i;
904 int clen;
905 int length = EXT2_INODE_SIZE(fs->super);
906
907 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
908
909 if (ext2fs_has_feature_journal_dev(fs->super))
910 return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP;
911
912 /* Check to see if user provided an override function */
913 if (fs->write_inode) {
914 retval = (fs->write_inode)(fs, ino, inode);
915 if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
916 return retval;
917 }
918
919 if ((ino == 0) || (ino > fs->super->s_inodes_count))
920 return EXT2_ET_BAD_INODE_NUM;
921
922 /* Prepare our shadow buffer for read/modify/byteswap/write */
923 retval = ext2fs_get_mem(length, &w_inode);
924 if (retval)
925 return retval;
926
927 if (bufsize < length) {
928 retval = ext2fs_read_inode2(fs, ino,
929 (struct ext2_inode *)w_inode,
930 length, READ_INODE_NOCSUM);
931 if (retval)
932 goto errout;
933 }
934
935 /* Check to see if the inode cache needs to be updated */
936 if (fs->icache) {
937 for (i=0; i < fs->icache->cache_size; i++) {
938 if (fs->icache->cache[i].ino == ino) {
939 memcpy(fs->icache->cache[i].inode, inode,
940 (bufsize > length) ? length : bufsize);
941 break;
942 }
943 }
944 } else {
945 retval = ext2fs_create_inode_cache(fs, 4);
946 if (retval)
947 goto errout;
948 }
949 memcpy(w_inode, inode, (bufsize > length) ? length : bufsize);
950
951 if (!(fs->flags & EXT2_FLAG_RW)) {
952 retval = EXT2_ET_RO_FILSYS;
953 goto errout;
954 }
955
956 #ifdef WORDS_BIGENDIAN
957 ext2fs_swap_inode_full(fs, w_inode, w_inode, 1, length);
958 #endif
959
960 if ((flags & WRITE_INODE_NOCSUM) == 0) {
961 retval = ext2fs_inode_csum_set(fs, ino, w_inode);
962 if (retval)
963 goto errout;
964 }
965
966 group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
967 offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
968 EXT2_INODE_SIZE(fs->super);
969 block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
970 block_nr = ext2fs_inode_table_loc(fs, (unsigned) group);
971 if (!block_nr) {
972 retval = EXT2_ET_MISSING_INODE_TABLE;
973 goto errout;
974 }
975 if ((block_nr < fs->super->s_first_data_block) ||
976 (block_nr + fs->inode_blocks_per_group - 1 >=
977 ext2fs_blocks_count(fs->super))) {
978 retval = EXT2_ET_GDESC_BAD_INODE_TABLE;
979 goto errout;
980 }
981 block_nr += block;
982
983 offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
984
985 ptr = (char *) w_inode;
986
987 while (length) {
988 clen = length;
989 if ((offset + length) > fs->blocksize)
990 clen = fs->blocksize - offset;
991
992 if (fs->icache->buffer_blk != block_nr) {
993 retval = io_channel_read_blk64(fs->io, block_nr, 1,
994 fs->icache->buffer);
995 if (retval)
996 goto errout;
997 fs->icache->buffer_blk = block_nr;
998 }
999
1000
1001 memcpy((char *) fs->icache->buffer + (unsigned) offset,
1002 ptr, clen);
1003
1004 retval = io_channel_write_blk64(fs->io, block_nr, 1,
1005 fs->icache->buffer);
1006 if (retval)
1007 goto errout;
1008
1009 offset = 0;
1010 ptr += clen;
1011 length -= clen;
1012 block_nr++;
1013 }
1014
1015 fs->flags |= EXT2_FLAG_CHANGED;
1016 errout:
1017 ext2fs_free_mem(&w_inode);
1018 return retval;
1019 }
1020
ext2fs_write_inode_full(ext2_filsys fs,ext2_ino_t ino,struct ext2_inode * inode,int bufsize)1021 errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
1022 struct ext2_inode * inode, int bufsize)
1023 {
1024 return ext2fs_write_inode2(fs, ino, inode, bufsize, 0);
1025 }
1026
ext2fs_write_inode(ext2_filsys fs,ext2_ino_t ino,struct ext2_inode * inode)1027 errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
1028 struct ext2_inode *inode)
1029 {
1030 return ext2fs_write_inode2(fs, ino, inode,
1031 sizeof(struct ext2_inode), 0);
1032 }
1033
1034 /*
1035 * This function should be called when writing a new inode. It makes
1036 * sure that extra part of large inodes is initialized properly.
1037 */
ext2fs_write_new_inode(ext2_filsys fs,ext2_ino_t ino,struct ext2_inode * inode)1038 errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino,
1039 struct ext2_inode *inode)
1040 {
1041 struct ext2_inode *buf;
1042 int size = EXT2_INODE_SIZE(fs->super);
1043 struct ext2_inode_large *large_inode;
1044 errcode_t retval;
1045 __u32 t = fs->now ? fs->now : time(NULL);
1046
1047 if (!inode->i_ctime)
1048 inode->i_ctime = t;
1049 if (!inode->i_mtime)
1050 inode->i_mtime = t;
1051 if (!inode->i_atime)
1052 inode->i_atime = t;
1053
1054 if (size == sizeof(struct ext2_inode))
1055 return ext2fs_write_inode_full(fs, ino, inode,
1056 sizeof(struct ext2_inode));
1057
1058 buf = malloc(size);
1059 if (!buf)
1060 return ENOMEM;
1061
1062 memset(buf, 0, size);
1063 *buf = *inode;
1064
1065 large_inode = (struct ext2_inode_large *) buf;
1066 large_inode->i_extra_isize = sizeof(struct ext2_inode_large) -
1067 EXT2_GOOD_OLD_INODE_SIZE;
1068 if (!large_inode->i_crtime)
1069 large_inode->i_crtime = t;
1070
1071 retval = ext2fs_write_inode_full(fs, ino, buf, size);
1072 free(buf);
1073 return retval;
1074 }
1075
1076
ext2fs_get_blocks(ext2_filsys fs,ext2_ino_t ino,blk_t * blocks)1077 errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks)
1078 {
1079 struct ext2_inode inode;
1080 int i;
1081 errcode_t retval;
1082
1083 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
1084
1085 if (ino > fs->super->s_inodes_count)
1086 return EXT2_ET_BAD_INODE_NUM;
1087
1088 if (fs->get_blocks) {
1089 if (!(*fs->get_blocks)(fs, ino, blocks))
1090 return 0;
1091 }
1092 retval = ext2fs_read_inode(fs, ino, &inode);
1093 if (retval)
1094 return retval;
1095 for (i=0; i < EXT2_N_BLOCKS; i++)
1096 blocks[i] = inode.i_block[i];
1097 return 0;
1098 }
1099
ext2fs_check_directory(ext2_filsys fs,ext2_ino_t ino)1100 errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino)
1101 {
1102 struct ext2_inode inode;
1103 errcode_t retval;
1104
1105 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
1106
1107 if (ino > fs->super->s_inodes_count)
1108 return EXT2_ET_BAD_INODE_NUM;
1109
1110 if (fs->check_directory) {
1111 retval = (fs->check_directory)(fs, ino);
1112 if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
1113 return retval;
1114 }
1115 retval = ext2fs_read_inode(fs, ino, &inode);
1116 if (retval)
1117 return retval;
1118 if (!LINUX_S_ISDIR(inode.i_mode))
1119 return EXT2_ET_NO_DIRECTORY;
1120 return 0;
1121 }
1122
1123