]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blob - lib/ext2fs/inode.c
Merge branch 'maint' into next
[thirdparty/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 struct ext2_struct_inode_scan {
34 errcode_t magic;
35 ext2_filsys fs;
36 ext2_ino_t current_inode;
37 blk64_t current_block;
38 dgrp_t current_group;
39 ext2_ino_t inodes_left;
40 blk_t blocks_left;
41 dgrp_t groups_left;
42 blk_t inode_buffer_blocks;
43 char * inode_buffer;
44 int inode_size;
45 char * ptr;
46 int bytes_left;
47 char *temp_buffer;
48 errcode_t (*done_group)(ext2_filsys fs,
49 ext2_inode_scan scan,
50 dgrp_t group,
51 void * priv_data);
52 void * done_group_data;
53 int bad_block_ptr;
54 int scan_flags;
55 int reserved[6];
56 };
57
58 /*
59 * This routine flushes the icache, if it exists.
60 */
61 errcode_t ext2fs_flush_icache(ext2_filsys fs)
62 {
63 int i;
64
65 if (!fs->icache)
66 return 0;
67
68 for (i=0; i < fs->icache->cache_size; i++)
69 fs->icache->cache[i].ino = 0;
70
71 fs->icache->buffer_blk = 0;
72 return 0;
73 }
74
75 /*
76 * Free the inode cache structure
77 */
78 void ext2fs_free_inode_cache(struct ext2_inode_cache *icache)
79 {
80 int i;
81
82 if (--icache->refcount)
83 return;
84 if (icache->buffer)
85 ext2fs_free_mem(&icache->buffer);
86 for (i = 0; i < icache->cache_size; i++)
87 ext2fs_free_mem(&icache->cache[i].inode);
88 if (icache->cache)
89 ext2fs_free_mem(&icache->cache);
90 icache->buffer_blk = 0;
91 ext2fs_free_mem(&icache);
92 }
93
94 static errcode_t create_icache(ext2_filsys fs)
95 {
96 int i;
97 errcode_t retval;
98
99 if (fs->icache)
100 return 0;
101 retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache), &fs->icache);
102 if (retval)
103 return retval;
104
105 memset(fs->icache, 0, sizeof(struct ext2_inode_cache));
106 retval = ext2fs_get_mem(fs->blocksize, &fs->icache->buffer);
107 if (retval)
108 goto errout;
109
110 fs->icache->buffer_blk = 0;
111 fs->icache->cache_last = -1;
112 fs->icache->cache_size = 4;
113 fs->icache->refcount = 1;
114 retval = ext2fs_get_array(fs->icache->cache_size,
115 sizeof(struct ext2_inode_cache_ent),
116 &fs->icache->cache);
117 if (retval)
118 goto errout;
119
120 for (i = 0; i < fs->icache->cache_size; i++) {
121 retval = ext2fs_get_mem(EXT2_INODE_SIZE(fs->super),
122 &fs->icache->cache[i].inode);
123 if (retval)
124 goto errout;
125 }
126
127 ext2fs_flush_icache(fs);
128 return 0;
129 errout:
130 ext2fs_free_inode_cache(fs->icache);
131 fs->icache = 0;
132 return retval;
133 }
134
135 errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
136 ext2_inode_scan *ret_scan)
137 {
138 ext2_inode_scan scan;
139 errcode_t retval;
140 errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks);
141
142 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
143
144 /*
145 * If fs->badblocks isn't set, then set it --- since the inode
146 * scanning functions require it.
147 */
148 if (fs->badblocks == 0) {
149 /*
150 * Temporarly save fs->get_blocks and set it to zero,
151 * for compatibility with old e2fsck's.
152 */
153 save_get_blocks = fs->get_blocks;
154 fs->get_blocks = 0;
155 retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
156 if (retval && fs->badblocks) {
157 ext2fs_badblocks_list_free(fs->badblocks);
158 fs->badblocks = 0;
159 }
160 fs->get_blocks = save_get_blocks;
161 }
162
163 retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan), &scan);
164 if (retval)
165 return retval;
166 memset(scan, 0, sizeof(struct ext2_struct_inode_scan));
167
168 scan->magic = EXT2_ET_MAGIC_INODE_SCAN;
169 scan->fs = fs;
170 scan->inode_size = EXT2_INODE_SIZE(fs->super);
171 scan->bytes_left = 0;
172 scan->current_group = 0;
173 scan->groups_left = fs->group_desc_count - 1;
174 scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8;
175 scan->current_block = ext2fs_inode_table_loc(scan->fs,
176 scan->current_group);
177 scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
178 scan->blocks_left = scan->fs->inode_blocks_per_group;
179 if (ext2fs_has_group_desc_csum(fs)) {
180 scan->inodes_left -=
181 ext2fs_bg_itable_unused(fs, scan->current_group);
182 scan->blocks_left =
183 (scan->inodes_left +
184 (fs->blocksize / scan->inode_size - 1)) *
185 scan->inode_size / fs->blocksize;
186 }
187 retval = io_channel_alloc_buf(fs->io, scan->inode_buffer_blocks,
188 &scan->inode_buffer);
189 scan->done_group = 0;
190 scan->done_group_data = 0;
191 scan->bad_block_ptr = 0;
192 if (retval) {
193 ext2fs_free_mem(&scan);
194 return retval;
195 }
196 retval = ext2fs_get_mem(scan->inode_size, &scan->temp_buffer);
197 if (retval) {
198 ext2fs_free_mem(&scan->inode_buffer);
199 ext2fs_free_mem(&scan);
200 return retval;
201 }
202 if (scan->fs->badblocks && scan->fs->badblocks->num)
203 scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS;
204 if (ext2fs_has_group_desc_csum(fs))
205 scan->scan_flags |= EXT2_SF_DO_LAZY;
206 *ret_scan = scan;
207 return 0;
208 }
209
210 void ext2fs_close_inode_scan(ext2_inode_scan scan)
211 {
212 if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
213 return;
214
215 ext2fs_free_mem(&scan->inode_buffer);
216 scan->inode_buffer = NULL;
217 ext2fs_free_mem(&scan->temp_buffer);
218 scan->temp_buffer = NULL;
219 ext2fs_free_mem(&scan);
220 return;
221 }
222
223 void ext2fs_set_inode_callback(ext2_inode_scan scan,
224 errcode_t (*done_group)(ext2_filsys fs,
225 ext2_inode_scan scan,
226 dgrp_t group,
227 void * priv_data),
228 void *done_group_data)
229 {
230 if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
231 return;
232
233 scan->done_group = done_group;
234 scan->done_group_data = done_group_data;
235 }
236
237 int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
238 int clear_flags)
239 {
240 int old_flags;
241
242 if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
243 return 0;
244
245 old_flags = scan->scan_flags;
246 scan->scan_flags &= ~clear_flags;
247 scan->scan_flags |= set_flags;
248 return old_flags;
249 }
250
251 /*
252 * This function is called by ext2fs_get_next_inode when it needs to
253 * get ready to read in a new blockgroup.
254 */
255 static errcode_t get_next_blockgroup(ext2_inode_scan scan)
256 {
257 ext2_filsys fs = scan->fs;
258
259 scan->current_group++;
260 scan->groups_left--;
261
262 scan->current_block = ext2fs_inode_table_loc(scan->fs,
263 scan->current_group);
264 scan->current_inode = scan->current_group *
265 EXT2_INODES_PER_GROUP(fs->super);
266
267 scan->bytes_left = 0;
268 scan->inodes_left = EXT2_INODES_PER_GROUP(fs->super);
269 scan->blocks_left = fs->inode_blocks_per_group;
270 if (ext2fs_has_group_desc_csum(fs)) {
271 scan->inodes_left -=
272 ext2fs_bg_itable_unused(fs, scan->current_group);
273 scan->blocks_left =
274 (scan->inodes_left +
275 (fs->blocksize / scan->inode_size - 1)) *
276 scan->inode_size / fs->blocksize;
277 }
278
279 return 0;
280 }
281
282 errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
283 int group)
284 {
285 scan->current_group = group - 1;
286 scan->groups_left = scan->fs->group_desc_count - group;
287 return get_next_blockgroup(scan);
288 }
289
290 /*
291 * This function is called by get_next_blocks() to check for bad
292 * blocks in the inode table.
293 *
294 * This function assumes that badblocks_list->list is sorted in
295 * increasing order.
296 */
297 static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan,
298 blk64_t *num_blocks)
299 {
300 blk64_t blk = scan->current_block;
301 badblocks_list bb = scan->fs->badblocks;
302
303 /*
304 * If the inode table is missing, then obviously there are no
305 * bad blocks. :-)
306 */
307 if (blk == 0)
308 return 0;
309
310 /*
311 * If the current block is greater than the bad block listed
312 * in the bad block list, then advance the pointer until this
313 * is no longer the case. If we run out of bad blocks, then
314 * we don't need to do any more checking!
315 */
316 while (blk > bb->list[scan->bad_block_ptr]) {
317 if (++scan->bad_block_ptr >= bb->num) {
318 scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
319 return 0;
320 }
321 }
322
323 /*
324 * If the current block is equal to the bad block listed in
325 * the bad block list, then handle that one block specially.
326 * (We could try to handle runs of bad blocks, but that
327 * only increases CPU efficiency by a small amount, at the
328 * expense of a huge expense of code complexity, and for an
329 * uncommon case at that.)
330 */
331 if (blk == bb->list[scan->bad_block_ptr]) {
332 scan->scan_flags |= EXT2_SF_BAD_INODE_BLK;
333 *num_blocks = 1;
334 if (++scan->bad_block_ptr >= bb->num)
335 scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
336 return 0;
337 }
338
339 /*
340 * If there is a bad block in the range that we're about to
341 * read in, adjust the number of blocks to read so that we we
342 * don't read in the bad block. (Then the next block to read
343 * will be the bad block, which is handled in the above case.)
344 */
345 if ((blk + *num_blocks) > bb->list[scan->bad_block_ptr])
346 *num_blocks = (int) (bb->list[scan->bad_block_ptr] - blk);
347
348 return 0;
349 }
350
351 /*
352 * This function is called by ext2fs_get_next_inode when it needs to
353 * read in more blocks from the current blockgroup's inode table.
354 */
355 static errcode_t get_next_blocks(ext2_inode_scan scan)
356 {
357 blk64_t num_blocks;
358 errcode_t retval;
359
360 /*
361 * Figure out how many blocks to read; we read at most
362 * inode_buffer_blocks, and perhaps less if there aren't that
363 * many blocks left to read.
364 */
365 num_blocks = scan->inode_buffer_blocks;
366 if (num_blocks > scan->blocks_left)
367 num_blocks = scan->blocks_left;
368
369 /*
370 * If the past block "read" was a bad block, then mark the
371 * left-over extra bytes as also being bad.
372 */
373 if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) {
374 if (scan->bytes_left)
375 scan->scan_flags |= EXT2_SF_BAD_EXTRA_BYTES;
376 scan->scan_flags &= ~EXT2_SF_BAD_INODE_BLK;
377 }
378
379 /*
380 * Do inode bad block processing, if necessary.
381 */
382 if (scan->scan_flags & EXT2_SF_CHK_BADBLOCKS) {
383 retval = check_for_inode_bad_blocks(scan, &num_blocks);
384 if (retval)
385 return retval;
386 }
387
388 if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) ||
389 (scan->current_block == 0)) {
390 memset(scan->inode_buffer, 0,
391 (size_t) num_blocks * scan->fs->blocksize);
392 } else {
393 retval = io_channel_read_blk64(scan->fs->io,
394 scan->current_block,
395 (int) num_blocks,
396 scan->inode_buffer);
397 if (retval)
398 return EXT2_ET_NEXT_INODE_READ;
399 }
400 scan->ptr = scan->inode_buffer;
401 scan->bytes_left = num_blocks * scan->fs->blocksize;
402
403 scan->blocks_left -= num_blocks;
404 if (scan->current_block)
405 scan->current_block += num_blocks;
406 return 0;
407 }
408
409 #if 0
410 /*
411 * Returns 1 if the entire inode_buffer has a non-zero size and
412 * contains all zeros. (Not just deleted inodes, since that means
413 * that part of the inode table was used at one point; we want all
414 * zeros, which means that the inode table is pristine.)
415 */
416 static inline int is_empty_scan(ext2_inode_scan scan)
417 {
418 int i;
419
420 if (scan->bytes_left == 0)
421 return 0;
422
423 for (i=0; i < scan->bytes_left; i++)
424 if (scan->ptr[i])
425 return 0;
426 return 1;
427 }
428 #endif
429
430 errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, ext2_ino_t *ino,
431 struct ext2_inode *inode, int bufsize)
432 {
433 errcode_t retval;
434 int extra_bytes = 0;
435 const int length = EXT2_INODE_SIZE(scan->fs->super);
436 struct ext2_inode_large *iptr = (struct ext2_inode_large *)inode;
437
438 EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN);
439
440 /*
441 * Do we need to start reading a new block group?
442 */
443 if (scan->inodes_left <= 0) {
444 force_new_group:
445 if (scan->done_group) {
446 retval = (scan->done_group)
447 (scan->fs, scan, scan->current_group,
448 scan->done_group_data);
449 if (retval)
450 return retval;
451 }
452 if (scan->groups_left <= 0) {
453 *ino = 0;
454 return 0;
455 }
456 retval = get_next_blockgroup(scan);
457 if (retval)
458 return retval;
459 }
460 /*
461 * These checks are done outside the above if statement so
462 * they can be done for block group #0.
463 */
464 if ((scan->scan_flags & EXT2_SF_DO_LAZY) &&
465 (ext2fs_bg_flags_test(scan->fs, scan->current_group, EXT2_BG_INODE_UNINIT)
466 ))
467 goto force_new_group;
468 if (scan->inodes_left == 0)
469 goto force_new_group;
470 if (scan->current_block == 0) {
471 if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) {
472 goto force_new_group;
473 } else
474 return EXT2_ET_MISSING_INODE_TABLE;
475 }
476
477
478 /*
479 * Have we run out of space in the inode buffer? If so, we
480 * need to read in more blocks.
481 */
482 if (scan->bytes_left < scan->inode_size) {
483 memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left);
484 extra_bytes = scan->bytes_left;
485
486 retval = get_next_blocks(scan);
487 if (retval)
488 return retval;
489 #if 0
490 /*
491 * XXX test Need check for used inode somehow.
492 * (Note: this is hard.)
493 */
494 if (is_empty_scan(scan))
495 goto force_new_group;
496 #endif
497 }
498
499 if (bufsize < length) {
500 retval = ext2fs_get_mem(length, &iptr);
501 if (retval)
502 return retval;
503 }
504
505 retval = 0;
506 if (extra_bytes) {
507 memcpy(scan->temp_buffer+extra_bytes, scan->ptr,
508 scan->inode_size - extra_bytes);
509 scan->ptr += scan->inode_size - extra_bytes;
510 scan->bytes_left -= scan->inode_size - extra_bytes;
511
512 /* Verify the inode checksum. */
513 if (!(scan->fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
514 !ext2fs_inode_csum_verify(scan->fs, scan->current_inode + 1,
515 (struct ext2_inode_large *)scan->temp_buffer))
516 retval = EXT2_ET_INODE_CSUM_INVALID;
517
518 #ifdef WORDS_BIGENDIAN
519 memset(iptr, 0, length);
520 ext2fs_swap_inode_full(scan->fs,
521 (struct ext2_inode_large *) iptr,
522 (struct ext2_inode_large *) scan->temp_buffer,
523 0, length);
524 #else
525 memcpy(iptr, scan->temp_buffer, length);
526 #endif
527 if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES)
528 retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
529 scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES;
530 } else {
531 /* Verify the inode checksum. */
532 if (!(scan->fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
533 !ext2fs_inode_csum_verify(scan->fs, scan->current_inode + 1,
534 (struct ext2_inode_large *)scan->ptr))
535 retval = EXT2_ET_INODE_CSUM_INVALID;
536
537 #ifdef WORDS_BIGENDIAN
538 memset(iptr, 0, length);
539 ext2fs_swap_inode_full(scan->fs,
540 (struct ext2_inode_large *) iptr,
541 (struct ext2_inode_large *) scan->ptr,
542 0, length);
543 #else
544 memcpy(iptr, scan->ptr, length);
545 #endif
546 scan->ptr += scan->inode_size;
547 scan->bytes_left -= scan->inode_size;
548 if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK)
549 retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
550 }
551
552 scan->inodes_left--;
553 scan->current_inode++;
554 *ino = scan->current_inode;
555 if (iptr != (struct ext2_inode_large *)inode) {
556 memcpy(inode, iptr, bufsize);
557 ext2fs_free_mem(&iptr);
558 }
559 return retval;
560 }
561
562 errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino,
563 struct ext2_inode *inode)
564 {
565 return ext2fs_get_next_inode_full(scan, ino, inode,
566 sizeof(struct ext2_inode));
567 }
568
569 /*
570 * Functions to read and write a single inode.
571 */
572 errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
573 struct ext2_inode * inode, int bufsize)
574 {
575 blk64_t block_nr;
576 unsigned long group, block, offset;
577 char *ptr;
578 errcode_t retval;
579 int clen, i, inodes_per_block;
580 io_channel io;
581 int length = EXT2_INODE_SIZE(fs->super);
582 struct ext2_inode_large *iptr;
583 int cache_slot;
584
585 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
586
587 /* Check to see if user has an override function */
588 if (fs->read_inode &&
589 ((bufsize == sizeof(struct ext2_inode)) ||
590 (EXT2_INODE_SIZE(fs->super) == sizeof(struct ext2_inode)))) {
591 retval = (fs->read_inode)(fs, ino, inode);
592 if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
593 return retval;
594 }
595 if ((ino == 0) || (ino > fs->super->s_inodes_count))
596 return EXT2_ET_BAD_INODE_NUM;
597 /* Create inode cache if not present */
598 if (!fs->icache) {
599 retval = create_icache(fs);
600 if (retval)
601 return retval;
602 }
603 /* Check to see if it's in the inode cache */
604 for (i = 0; i < fs->icache->cache_size; i++) {
605 if (fs->icache->cache[i].ino == ino) {
606 memcpy(inode, fs->icache->cache[i].inode,
607 (bufsize > length) ? length : bufsize);
608 return 0;
609 }
610 }
611 if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
612 inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super);
613 block_nr = fs->image_header->offset_inode / fs->blocksize;
614 block_nr += (ino - 1) / inodes_per_block;
615 offset = ((ino - 1) % inodes_per_block) *
616 EXT2_INODE_SIZE(fs->super);
617 io = fs->image_io;
618 } else {
619 group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
620 if (group > fs->group_desc_count)
621 return EXT2_ET_BAD_INODE_NUM;
622 offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
623 EXT2_INODE_SIZE(fs->super);
624 block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
625 if (!ext2fs_inode_table_loc(fs, (unsigned) group))
626 return EXT2_ET_MISSING_INODE_TABLE;
627 block_nr = ext2fs_inode_table_loc(fs, group) +
628 block;
629 io = fs->io;
630 }
631 offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
632
633 cache_slot = (fs->icache->cache_last + 1) % fs->icache->cache_size;
634 iptr = (struct ext2_inode_large *)fs->icache->cache[cache_slot].inode;
635
636 ptr = (char *) iptr;
637 while (length) {
638 clen = length;
639 if ((offset + length) > fs->blocksize)
640 clen = fs->blocksize - offset;
641
642 if (block_nr != fs->icache->buffer_blk) {
643 retval = io_channel_read_blk64(io, block_nr, 1,
644 fs->icache->buffer);
645 if (retval)
646 return retval;
647 fs->icache->buffer_blk = block_nr;
648 }
649
650 memcpy(ptr, ((char *) fs->icache->buffer) + (unsigned) offset,
651 clen);
652
653 offset = 0;
654 length -= clen;
655 ptr += clen;
656 block_nr++;
657 }
658 length = EXT2_INODE_SIZE(fs->super);
659
660 /* Verify the inode checksum. */
661 if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
662 !ext2fs_inode_csum_verify(fs, ino, iptr))
663 return EXT2_ET_INODE_CSUM_INVALID;
664
665 #ifdef WORDS_BIGENDIAN
666 ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) iptr,
667 (struct ext2_inode_large *) iptr,
668 0, length);
669 #endif
670
671 /* Update the inode cache bookkeeping */
672 fs->icache->cache_last = cache_slot;
673 fs->icache->cache[cache_slot].ino = ino;
674 memcpy(inode, iptr, (bufsize > length) ? length : bufsize);
675
676 return 0;
677 }
678
679 errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino,
680 struct ext2_inode * inode)
681 {
682 return ext2fs_read_inode_full(fs, ino, inode,
683 sizeof(struct ext2_inode));
684 }
685
686 errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
687 struct ext2_inode * inode, int bufsize)
688 {
689 blk64_t block_nr;
690 unsigned long group, block, offset;
691 errcode_t retval = 0;
692 struct ext2_inode_large *w_inode;
693 char *ptr;
694 int clen, i;
695 int length = EXT2_INODE_SIZE(fs->super);
696
697 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
698
699 /* Check to see if user provided an override function */
700 if (fs->write_inode) {
701 retval = (fs->write_inode)(fs, ino, inode);
702 if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
703 return retval;
704 }
705
706 if ((ino == 0) || (ino > fs->super->s_inodes_count))
707 return EXT2_ET_BAD_INODE_NUM;
708
709 /* Prepare our shadow buffer for read/modify/byteswap/write */
710 retval = ext2fs_get_mem(length, &w_inode);
711 if (retval)
712 return retval;
713
714 if (bufsize < length) {
715 int old_flags = fs->flags;
716 fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
717 retval = ext2fs_read_inode_full(fs, ino,
718 (struct ext2_inode *)w_inode,
719 length);
720 fs->flags = old_flags;
721 if (retval)
722 goto errout;
723 }
724
725 /* Check to see if the inode cache needs to be updated */
726 if (fs->icache) {
727 for (i=0; i < fs->icache->cache_size; i++) {
728 if (fs->icache->cache[i].ino == ino) {
729 memcpy(fs->icache->cache[i].inode, inode,
730 (bufsize > length) ? length : bufsize);
731 break;
732 }
733 }
734 } else {
735 retval = create_icache(fs);
736 if (retval)
737 goto errout;
738 }
739 memcpy(w_inode, inode, (bufsize > length) ? length : bufsize);
740
741 if (!(fs->flags & EXT2_FLAG_RW)) {
742 retval = EXT2_ET_RO_FILSYS;
743 goto errout;
744 }
745
746 #ifdef WORDS_BIGENDIAN
747 ext2fs_swap_inode_full(fs, w_inode, w_inode, 1, length);
748 #endif
749
750 retval = ext2fs_inode_csum_set(fs, ino, w_inode);
751 if (retval)
752 goto errout;
753
754 group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
755 offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
756 EXT2_INODE_SIZE(fs->super);
757 block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
758 if (!ext2fs_inode_table_loc(fs, (unsigned) group)) {
759 retval = EXT2_ET_MISSING_INODE_TABLE;
760 goto errout;
761 }
762 block_nr = ext2fs_inode_table_loc(fs, (unsigned) group) + block;
763
764 offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
765
766 ptr = (char *) w_inode;
767
768 while (length) {
769 clen = length;
770 if ((offset + length) > fs->blocksize)
771 clen = fs->blocksize - offset;
772
773 if (fs->icache->buffer_blk != block_nr) {
774 retval = io_channel_read_blk64(fs->io, block_nr, 1,
775 fs->icache->buffer);
776 if (retval)
777 goto errout;
778 fs->icache->buffer_blk = block_nr;
779 }
780
781
782 memcpy((char *) fs->icache->buffer + (unsigned) offset,
783 ptr, clen);
784
785 retval = io_channel_write_blk64(fs->io, block_nr, 1,
786 fs->icache->buffer);
787 if (retval)
788 goto errout;
789
790 offset = 0;
791 ptr += clen;
792 length -= clen;
793 block_nr++;
794 }
795
796 fs->flags |= EXT2_FLAG_CHANGED;
797 errout:
798 ext2fs_free_mem(&w_inode);
799 return retval;
800 }
801
802 errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
803 struct ext2_inode *inode)
804 {
805 return ext2fs_write_inode_full(fs, ino, inode,
806 sizeof(struct ext2_inode));
807 }
808
809 /*
810 * This function should be called when writing a new inode. It makes
811 * sure that extra part of large inodes is initialized properly.
812 */
813 errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino,
814 struct ext2_inode *inode)
815 {
816 struct ext2_inode *buf;
817 int size = EXT2_INODE_SIZE(fs->super);
818 struct ext2_inode_large *large_inode;
819 errcode_t retval;
820 __u32 t = fs->now ? fs->now : time(NULL);
821
822 if (!inode->i_ctime)
823 inode->i_ctime = t;
824 if (!inode->i_mtime)
825 inode->i_mtime = t;
826 if (!inode->i_atime)
827 inode->i_atime = t;
828
829 if (size == sizeof(struct ext2_inode))
830 return ext2fs_write_inode_full(fs, ino, inode,
831 sizeof(struct ext2_inode));
832
833 buf = malloc(size);
834 if (!buf)
835 return ENOMEM;
836
837 memset(buf, 0, size);
838 *buf = *inode;
839
840 large_inode = (struct ext2_inode_large *) buf;
841 large_inode->i_extra_isize = sizeof(struct ext2_inode_large) -
842 EXT2_GOOD_OLD_INODE_SIZE;
843 if (!large_inode->i_crtime)
844 large_inode->i_crtime = t;
845
846 retval = ext2fs_write_inode_full(fs, ino, buf, size);
847 free(buf);
848 return retval;
849 }
850
851
852 errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks)
853 {
854 struct ext2_inode inode;
855 int i;
856 errcode_t retval;
857
858 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
859
860 if (ino > fs->super->s_inodes_count)
861 return EXT2_ET_BAD_INODE_NUM;
862
863 if (fs->get_blocks) {
864 if (!(*fs->get_blocks)(fs, ino, blocks))
865 return 0;
866 }
867 retval = ext2fs_read_inode(fs, ino, &inode);
868 if (retval)
869 return retval;
870 for (i=0; i < EXT2_N_BLOCKS; i++)
871 blocks[i] = inode.i_block[i];
872 return 0;
873 }
874
875 errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino)
876 {
877 struct ext2_inode inode;
878 errcode_t retval;
879
880 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
881
882 if (ino > fs->super->s_inodes_count)
883 return EXT2_ET_BAD_INODE_NUM;
884
885 if (fs->check_directory) {
886 retval = (fs->check_directory)(fs, ino);
887 if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
888 return retval;
889 }
890 retval = ext2fs_read_inode(fs, ino, &inode);
891 if (retval)
892 return retval;
893 if (!LINUX_S_ISDIR(inode.i_mode))
894 return EXT2_ET_NO_DIRECTORY;
895 return 0;
896 }
897