3
0

inode.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  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 Public
  8. * License.
  9. * %End-Header%
  10. */
  11. #include <stdio.h>
  12. #include <string.h>
  13. #if HAVE_UNISTD_H
  14. #include <unistd.h>
  15. #endif
  16. #if HAVE_ERRNO_H
  17. #include <errno.h>
  18. #endif
  19. #if HAVE_SYS_STAT_H
  20. #include <sys/stat.h>
  21. #endif
  22. #if HAVE_SYS_TYPES_H
  23. #include <sys/types.h>
  24. #endif
  25. #include "ext2_fs.h"
  26. #include "ext2fsP.h"
  27. #include "e2image.h"
  28. struct ext2_struct_inode_scan {
  29. errcode_t magic;
  30. ext2_filsys fs;
  31. ext2_ino_t current_inode;
  32. blk_t current_block;
  33. dgrp_t current_group;
  34. ext2_ino_t inodes_left;
  35. blk_t blocks_left;
  36. dgrp_t groups_left;
  37. blk_t inode_buffer_blocks;
  38. char * inode_buffer;
  39. int inode_size;
  40. char * ptr;
  41. int bytes_left;
  42. char *temp_buffer;
  43. errcode_t (*done_group)(ext2_filsys fs,
  44. ext2_inode_scan scan,
  45. dgrp_t group,
  46. void * priv_data);
  47. void * done_group_data;
  48. int bad_block_ptr;
  49. int scan_flags;
  50. int reserved[6];
  51. };
  52. /*
  53. * This routine flushes the icache, if it exists.
  54. */
  55. errcode_t ext2fs_flush_icache(ext2_filsys fs)
  56. {
  57. int i;
  58. if (!fs->icache)
  59. return 0;
  60. for (i=0; i < fs->icache->cache_size; i++)
  61. fs->icache->cache[i].ino = 0;
  62. fs->icache->buffer_blk = 0;
  63. return 0;
  64. }
  65. static errcode_t create_icache(ext2_filsys fs)
  66. {
  67. errcode_t retval;
  68. if (fs->icache)
  69. return 0;
  70. retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache), &fs->icache);
  71. if (retval)
  72. return retval;
  73. memset(fs->icache, 0, sizeof(struct ext2_inode_cache));
  74. retval = ext2fs_get_mem(fs->blocksize, &fs->icache->buffer);
  75. if (retval) {
  76. ext2fs_free_mem(&fs->icache);
  77. return retval;
  78. }
  79. fs->icache->buffer_blk = 0;
  80. fs->icache->cache_last = -1;
  81. fs->icache->cache_size = 4;
  82. fs->icache->refcount = 1;
  83. retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache_ent)
  84. * fs->icache->cache_size,
  85. &fs->icache->cache);
  86. if (retval) {
  87. ext2fs_free_mem(&fs->icache->buffer);
  88. ext2fs_free_mem(&fs->icache);
  89. return retval;
  90. }
  91. ext2fs_flush_icache(fs);
  92. return 0;
  93. }
  94. errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
  95. ext2_inode_scan *ret_scan)
  96. {
  97. ext2_inode_scan scan;
  98. errcode_t retval;
  99. errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks);
  100. EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  101. /*
  102. * If fs->badblocks isn't set, then set it --- since the inode
  103. * scanning functions require it.
  104. */
  105. if (fs->badblocks == 0) {
  106. /*
  107. * Temporarly save fs->get_blocks and set it to zero,
  108. * for compatibility with old e2fsck's.
  109. */
  110. save_get_blocks = fs->get_blocks;
  111. fs->get_blocks = 0;
  112. retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
  113. if (retval && fs->badblocks) {
  114. ext2fs_badblocks_list_free(fs->badblocks);
  115. fs->badblocks = 0;
  116. }
  117. fs->get_blocks = save_get_blocks;
  118. }
  119. retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan), &scan);
  120. if (retval)
  121. return retval;
  122. memset(scan, 0, sizeof(struct ext2_struct_inode_scan));
  123. scan->magic = EXT2_ET_MAGIC_INODE_SCAN;
  124. scan->fs = fs;
  125. scan->inode_size = EXT2_INODE_SIZE(fs->super);
  126. scan->bytes_left = 0;
  127. scan->current_group = 0;
  128. scan->groups_left = fs->group_desc_count - 1;
  129. scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8;
  130. scan->current_block = scan->fs->
  131. group_desc[scan->current_group].bg_inode_table;
  132. scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
  133. scan->blocks_left = scan->fs->inode_blocks_per_group;
  134. retval = ext2fs_get_mem((size_t) (scan->inode_buffer_blocks *
  135. fs->blocksize),
  136. &scan->inode_buffer);
  137. scan->done_group = 0;
  138. scan->done_group_data = 0;
  139. scan->bad_block_ptr = 0;
  140. if (retval) {
  141. ext2fs_free_mem(&scan);
  142. return retval;
  143. }
  144. retval = ext2fs_get_mem(scan->inode_size, &scan->temp_buffer);
  145. if (retval) {
  146. ext2fs_free_mem(&scan->inode_buffer);
  147. ext2fs_free_mem(&scan);
  148. return retval;
  149. }
  150. if (scan->fs->badblocks && scan->fs->badblocks->num)
  151. scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS;
  152. *ret_scan = scan;
  153. return 0;
  154. }
  155. void ext2fs_close_inode_scan(ext2_inode_scan scan)
  156. {
  157. if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
  158. return;
  159. ext2fs_free_mem(&scan->inode_buffer);
  160. scan->inode_buffer = NULL;
  161. ext2fs_free_mem(&scan->temp_buffer);
  162. scan->temp_buffer = NULL;
  163. ext2fs_free_mem(&scan);
  164. return;
  165. }
  166. void ext2fs_set_inode_callback(ext2_inode_scan scan,
  167. errcode_t (*done_group)(ext2_filsys fs,
  168. ext2_inode_scan scan,
  169. dgrp_t group,
  170. void * priv_data),
  171. void *done_group_data)
  172. {
  173. if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
  174. return;
  175. scan->done_group = done_group;
  176. scan->done_group_data = done_group_data;
  177. }
  178. int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
  179. int clear_flags)
  180. {
  181. int old_flags;
  182. if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
  183. return 0;
  184. old_flags = scan->scan_flags;
  185. scan->scan_flags &= ~clear_flags;
  186. scan->scan_flags |= set_flags;
  187. return old_flags;
  188. }
  189. /*
  190. * This function is called by ext2fs_get_next_inode when it needs to
  191. * get ready to read in a new blockgroup.
  192. */
  193. static errcode_t get_next_blockgroup(ext2_inode_scan scan)
  194. {
  195. scan->current_group++;
  196. scan->groups_left--;
  197. scan->current_block = scan->fs->
  198. group_desc[scan->current_group].bg_inode_table;
  199. scan->current_inode = scan->current_group *
  200. EXT2_INODES_PER_GROUP(scan->fs->super);
  201. scan->bytes_left = 0;
  202. scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
  203. scan->blocks_left = scan->fs->inode_blocks_per_group;
  204. return 0;
  205. }
  206. errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
  207. int group)
  208. {
  209. scan->current_group = group - 1;
  210. scan->groups_left = scan->fs->group_desc_count - group;
  211. return get_next_blockgroup(scan);
  212. }
  213. /*
  214. * This function is called by get_next_blocks() to check for bad
  215. * blocks in the inode table.
  216. *
  217. * This function assumes that badblocks_list->list is sorted in
  218. * increasing order.
  219. */
  220. static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan,
  221. blk_t *num_blocks)
  222. {
  223. blk_t blk = scan->current_block;
  224. badblocks_list bb = scan->fs->badblocks;
  225. /*
  226. * If the inode table is missing, then obviously there are no
  227. * bad blocks. :-)
  228. */
  229. if (blk == 0)
  230. return 0;
  231. /*
  232. * If the current block is greater than the bad block listed
  233. * in the bad block list, then advance the pointer until this
  234. * is no longer the case. If we run out of bad blocks, then
  235. * we don't need to do any more checking!
  236. */
  237. while (blk > bb->list[scan->bad_block_ptr]) {
  238. if (++scan->bad_block_ptr >= bb->num) {
  239. scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
  240. return 0;
  241. }
  242. }
  243. /*
  244. * If the current block is equal to the bad block listed in
  245. * the bad block list, then handle that one block specially.
  246. * (We could try to handle runs of bad blocks, but that
  247. * only increases CPU efficiency by a small amount, at the
  248. * expense of a huge expense of code complexity, and for an
  249. * uncommon case at that.)
  250. */
  251. if (blk == bb->list[scan->bad_block_ptr]) {
  252. scan->scan_flags |= EXT2_SF_BAD_INODE_BLK;
  253. *num_blocks = 1;
  254. if (++scan->bad_block_ptr >= bb->num)
  255. scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
  256. return 0;
  257. }
  258. /*
  259. * If there is a bad block in the range that we're about to
  260. * read in, adjust the number of blocks to read so that we we
  261. * don't read in the bad block. (Then the next block to read
  262. * will be the bad block, which is handled in the above case.)
  263. */
  264. if ((blk + *num_blocks) > bb->list[scan->bad_block_ptr])
  265. *num_blocks = (int) (bb->list[scan->bad_block_ptr] - blk);
  266. return 0;
  267. }
  268. /*
  269. * This function is called by ext2fs_get_next_inode when it needs to
  270. * read in more blocks from the current blockgroup's inode table.
  271. */
  272. static errcode_t get_next_blocks(ext2_inode_scan scan)
  273. {
  274. blk_t num_blocks;
  275. errcode_t retval;
  276. /*
  277. * Figure out how many blocks to read; we read at most
  278. * inode_buffer_blocks, and perhaps less if there aren't that
  279. * many blocks left to read.
  280. */
  281. num_blocks = scan->inode_buffer_blocks;
  282. if (num_blocks > scan->blocks_left)
  283. num_blocks = scan->blocks_left;
  284. /*
  285. * If the past block "read" was a bad block, then mark the
  286. * left-over extra bytes as also being bad.
  287. */
  288. if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) {
  289. if (scan->bytes_left)
  290. scan->scan_flags |= EXT2_SF_BAD_EXTRA_BYTES;
  291. scan->scan_flags &= ~EXT2_SF_BAD_INODE_BLK;
  292. }
  293. /*
  294. * Do inode bad block processing, if necessary.
  295. */
  296. if (scan->scan_flags & EXT2_SF_CHK_BADBLOCKS) {
  297. retval = check_for_inode_bad_blocks(scan, &num_blocks);
  298. if (retval)
  299. return retval;
  300. }
  301. if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) ||
  302. (scan->current_block == 0)) {
  303. memset(scan->inode_buffer, 0,
  304. (size_t) num_blocks * scan->fs->blocksize);
  305. } else {
  306. retval = io_channel_read_blk(scan->fs->io,
  307. scan->current_block,
  308. (int) num_blocks,
  309. scan->inode_buffer);
  310. if (retval)
  311. return EXT2_ET_NEXT_INODE_READ;
  312. }
  313. scan->ptr = scan->inode_buffer;
  314. scan->bytes_left = num_blocks * scan->fs->blocksize;
  315. scan->blocks_left -= num_blocks;
  316. if (scan->current_block)
  317. scan->current_block += num_blocks;
  318. return 0;
  319. }
  320. #if 0
  321. /*
  322. * Returns 1 if the entire inode_buffer has a non-zero size and
  323. * contains all zeros. (Not just deleted inodes, since that means
  324. * that part of the inode table was used at one point; we want all
  325. * zeros, which means that the inode table is pristine.)
  326. */
  327. static inline int is_empty_scan(ext2_inode_scan scan)
  328. {
  329. int i;
  330. if (scan->bytes_left == 0)
  331. return 0;
  332. for (i=0; i < scan->bytes_left; i++)
  333. if (scan->ptr[i])
  334. return 0;
  335. return 1;
  336. }
  337. #endif
  338. errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, ext2_ino_t *ino,
  339. struct ext2_inode *inode, int bufsize)
  340. {
  341. errcode_t retval;
  342. int extra_bytes = 0;
  343. EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN);
  344. /*
  345. * Do we need to start reading a new block group?
  346. */
  347. if (scan->inodes_left <= 0) {
  348. force_new_group:
  349. if (scan->done_group) {
  350. retval = (scan->done_group)
  351. (scan->fs, scan, scan->current_group,
  352. scan->done_group_data);
  353. if (retval)
  354. return retval;
  355. }
  356. if (scan->groups_left <= 0) {
  357. *ino = 0;
  358. return 0;
  359. }
  360. retval = get_next_blockgroup(scan);
  361. if (retval)
  362. return retval;
  363. }
  364. /*
  365. * This is done outside the above if statement so that the
  366. * check can be done for block group #0.
  367. */
  368. if (scan->current_block == 0) {
  369. if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) {
  370. goto force_new_group;
  371. } else
  372. return EXT2_ET_MISSING_INODE_TABLE;
  373. }
  374. /*
  375. * Have we run out of space in the inode buffer? If so, we
  376. * need to read in more blocks.
  377. */
  378. if (scan->bytes_left < scan->inode_size) {
  379. memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left);
  380. extra_bytes = scan->bytes_left;
  381. retval = get_next_blocks(scan);
  382. if (retval)
  383. return retval;
  384. #if 0
  385. /*
  386. * XXX test Need check for used inode somehow.
  387. * (Note: this is hard.)
  388. */
  389. if (is_empty_scan(scan))
  390. goto force_new_group;
  391. #endif
  392. }
  393. retval = 0;
  394. if (extra_bytes) {
  395. memcpy(scan->temp_buffer+extra_bytes, scan->ptr,
  396. scan->inode_size - extra_bytes);
  397. scan->ptr += scan->inode_size - extra_bytes;
  398. scan->bytes_left -= scan->inode_size - extra_bytes;
  399. #ifdef EXT2FS_ENABLE_SWAPFS
  400. if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) ||
  401. (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
  402. ext2fs_swap_inode_full(scan->fs,
  403. (struct ext2_inode_large *) inode,
  404. (struct ext2_inode_large *) scan->temp_buffer,
  405. 0, bufsize);
  406. else
  407. #endif
  408. *inode = *((struct ext2_inode *) scan->temp_buffer);
  409. if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES)
  410. retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
  411. scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES;
  412. } else {
  413. #ifdef EXT2FS_ENABLE_SWAPFS
  414. if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) ||
  415. (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
  416. ext2fs_swap_inode_full(scan->fs,
  417. (struct ext2_inode_large *) inode,
  418. (struct ext2_inode_large *) scan->ptr,
  419. 0, bufsize);
  420. else
  421. #endif
  422. memcpy(inode, scan->ptr, bufsize);
  423. scan->ptr += scan->inode_size;
  424. scan->bytes_left -= scan->inode_size;
  425. if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK)
  426. retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
  427. }
  428. scan->inodes_left--;
  429. scan->current_inode++;
  430. *ino = scan->current_inode;
  431. return retval;
  432. }
  433. errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino,
  434. struct ext2_inode *inode)
  435. {
  436. return ext2fs_get_next_inode_full(scan, ino, inode,
  437. sizeof(struct ext2_inode));
  438. }
  439. /*
  440. * Functions to read and write a single inode.
  441. */
  442. errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
  443. struct ext2_inode * inode, int bufsize)
  444. {
  445. unsigned long group, block, block_nr, offset;
  446. char *ptr;
  447. errcode_t retval;
  448. int clen, i, inodes_per_block, length;
  449. io_channel io;
  450. EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  451. /* Check to see if user has an override function */
  452. if (fs->read_inode) {
  453. retval = (fs->read_inode)(fs, ino, inode);
  454. if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
  455. return retval;
  456. }
  457. /* Create inode cache if not present */
  458. if (!fs->icache) {
  459. retval = create_icache(fs);
  460. if (retval)
  461. return retval;
  462. }
  463. /* Check to see if it's in the inode cache */
  464. if (bufsize == sizeof(struct ext2_inode)) {
  465. /* only old good inode can be retrieve from the cache */
  466. for (i=0; i < fs->icache->cache_size; i++) {
  467. if (fs->icache->cache[i].ino == ino) {
  468. *inode = fs->icache->cache[i].inode;
  469. return 0;
  470. }
  471. }
  472. }
  473. if ((ino == 0) || (ino > fs->super->s_inodes_count))
  474. return EXT2_ET_BAD_INODE_NUM;
  475. if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
  476. inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super);
  477. block_nr = fs->image_header->offset_inode / fs->blocksize;
  478. block_nr += (ino - 1) / inodes_per_block;
  479. offset = ((ino - 1) % inodes_per_block) *
  480. EXT2_INODE_SIZE(fs->super);
  481. io = fs->image_io;
  482. } else {
  483. group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
  484. offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
  485. EXT2_INODE_SIZE(fs->super);
  486. block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
  487. if (!fs->group_desc[(unsigned)group].bg_inode_table)
  488. return EXT2_ET_MISSING_INODE_TABLE;
  489. block_nr = fs->group_desc[(unsigned)group].bg_inode_table +
  490. block;
  491. io = fs->io;
  492. }
  493. offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
  494. length = EXT2_INODE_SIZE(fs->super);
  495. if (bufsize < length)
  496. length = bufsize;
  497. ptr = (char *) inode;
  498. while (length) {
  499. clen = length;
  500. if ((offset + length) > fs->blocksize)
  501. clen = fs->blocksize - offset;
  502. if (block_nr != fs->icache->buffer_blk) {
  503. retval = io_channel_read_blk(io, block_nr, 1,
  504. fs->icache->buffer);
  505. if (retval)
  506. return retval;
  507. fs->icache->buffer_blk = block_nr;
  508. }
  509. memcpy(ptr, ((char *) fs->icache->buffer) + (unsigned) offset,
  510. clen);
  511. offset = 0;
  512. length -= clen;
  513. ptr += clen;
  514. block_nr++;
  515. }
  516. #ifdef EXT2FS_ENABLE_SWAPFS
  517. if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
  518. (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
  519. ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) inode,
  520. (struct ext2_inode_large *) inode,
  521. 0, length);
  522. #endif
  523. /* Update the inode cache */
  524. fs->icache->cache_last = (fs->icache->cache_last + 1) %
  525. fs->icache->cache_size;
  526. fs->icache->cache[fs->icache->cache_last].ino = ino;
  527. fs->icache->cache[fs->icache->cache_last].inode = *inode;
  528. return 0;
  529. }
  530. errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino,
  531. struct ext2_inode * inode)
  532. {
  533. return ext2fs_read_inode_full(fs, ino, inode,
  534. sizeof(struct ext2_inode));
  535. }
  536. errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
  537. struct ext2_inode * inode, int bufsize)
  538. {
  539. unsigned long group, block, block_nr, offset;
  540. errcode_t retval = 0;
  541. struct ext2_inode_large temp_inode, *w_inode;
  542. char *ptr;
  543. int clen, i, length;
  544. EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  545. /* Check to see if user provided an override function */
  546. if (fs->write_inode) {
  547. retval = (fs->write_inode)(fs, ino, inode);
  548. if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
  549. return retval;
  550. }
  551. /* Check to see if the inode cache needs to be updated */
  552. if (fs->icache) {
  553. for (i=0; i < fs->icache->cache_size; i++) {
  554. if (fs->icache->cache[i].ino == ino) {
  555. fs->icache->cache[i].inode = *inode;
  556. break;
  557. }
  558. }
  559. } else {
  560. retval = create_icache(fs);
  561. if (retval)
  562. return retval;
  563. }
  564. if (!(fs->flags & EXT2_FLAG_RW))
  565. return EXT2_ET_RO_FILSYS;
  566. if ((ino == 0) || (ino > fs->super->s_inodes_count))
  567. return EXT2_ET_BAD_INODE_NUM;
  568. length = bufsize;
  569. if (length < EXT2_INODE_SIZE(fs->super))
  570. length = EXT2_INODE_SIZE(fs->super);
  571. if (length > (int) sizeof(struct ext2_inode_large)) {
  572. w_inode = xmalloc(length);
  573. } else
  574. w_inode = &temp_inode;
  575. memset(w_inode, 0, length);
  576. #ifdef EXT2FS_ENABLE_SWAPFS
  577. if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
  578. (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
  579. ext2fs_swap_inode_full(fs, w_inode,
  580. (struct ext2_inode_large *) inode,
  581. 1, bufsize);
  582. else
  583. #endif
  584. memcpy(w_inode, inode, bufsize);
  585. group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
  586. offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
  587. EXT2_INODE_SIZE(fs->super);
  588. block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
  589. if (!fs->group_desc[(unsigned) group].bg_inode_table)
  590. return EXT2_ET_MISSING_INODE_TABLE;
  591. block_nr = fs->group_desc[(unsigned) group].bg_inode_table + block;
  592. offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
  593. length = EXT2_INODE_SIZE(fs->super);
  594. if (length > bufsize)
  595. length = bufsize;
  596. ptr = (char *) w_inode;
  597. while (length) {
  598. clen = length;
  599. if ((offset + length) > fs->blocksize)
  600. clen = fs->blocksize - offset;
  601. if (fs->icache->buffer_blk != block_nr) {
  602. retval = io_channel_read_blk(fs->io, block_nr, 1,
  603. fs->icache->buffer);
  604. if (retval)
  605. goto errout;
  606. fs->icache->buffer_blk = block_nr;
  607. }
  608. memcpy((char *) fs->icache->buffer + (unsigned) offset,
  609. ptr, clen);
  610. retval = io_channel_write_blk(fs->io, block_nr, 1,
  611. fs->icache->buffer);
  612. if (retval)
  613. goto errout;
  614. offset = 0;
  615. ptr += clen;
  616. length -= clen;
  617. block_nr++;
  618. }
  619. fs->flags |= EXT2_FLAG_CHANGED;
  620. errout:
  621. if (w_inode && w_inode != &temp_inode)
  622. free(w_inode);
  623. return retval;
  624. }
  625. errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
  626. struct ext2_inode *inode)
  627. {
  628. return ext2fs_write_inode_full(fs, ino, inode,
  629. sizeof(struct ext2_inode));
  630. }
  631. /*
  632. * This function should be called when writing a new inode. It makes
  633. * sure that extra part of large inodes is initialized properly.
  634. */
  635. errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino,
  636. struct ext2_inode *inode)
  637. {
  638. struct ext2_inode *buf;
  639. int size = EXT2_INODE_SIZE(fs->super);
  640. struct ext2_inode_large *large_inode;
  641. if (size == sizeof(struct ext2_inode))
  642. return ext2fs_write_inode_full(fs, ino, inode,
  643. sizeof(struct ext2_inode));
  644. buf = xmalloc(size);
  645. memset(buf, 0, size);
  646. *buf = *inode;
  647. large_inode = (struct ext2_inode_large *) buf;
  648. large_inode->i_extra_isize = sizeof(struct ext2_inode_large) -
  649. EXT2_GOOD_OLD_INODE_SIZE;
  650. return ext2fs_write_inode_full(fs, ino, buf, size);
  651. }
  652. errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks)
  653. {
  654. struct ext2_inode inode;
  655. int i;
  656. errcode_t retval;
  657. EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  658. if (ino > fs->super->s_inodes_count)
  659. return EXT2_ET_BAD_INODE_NUM;
  660. if (fs->get_blocks) {
  661. if (!(*fs->get_blocks)(fs, ino, blocks))
  662. return 0;
  663. }
  664. retval = ext2fs_read_inode(fs, ino, &inode);
  665. if (retval)
  666. return retval;
  667. for (i=0; i < EXT2_N_BLOCKS; i++)
  668. blocks[i] = inode.i_block[i];
  669. return 0;
  670. }
  671. errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino)
  672. {
  673. struct ext2_inode inode;
  674. errcode_t retval;
  675. EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  676. if (ino > fs->super->s_inodes_count)
  677. return EXT2_ET_BAD_INODE_NUM;
  678. if (fs->check_directory) {
  679. retval = (fs->check_directory)(fs, ino);
  680. if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
  681. return retval;
  682. }
  683. retval = ext2fs_read_inode(fs, ino, &inode);
  684. if (retval)
  685. return retval;
  686. if (!LINUX_S_ISDIR(inode.i_mode))
  687. return EXT2_ET_NO_DIRECTORY;
  688. return 0;
  689. }