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