rw_bitmaps.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * rw_bitmaps.c --- routines to read and write the inode and block bitmaps.
  4. *
  5. * Copyright (C) 1993, 1994, 1994, 1996 Theodore Ts'o.
  6. *
  7. * %Begin-Header%
  8. * This file may be redistributed under the terms of the GNU Public
  9. * License.
  10. * %End-Header%
  11. */
  12. #include <stdio.h>
  13. #include <string.h>
  14. #if HAVE_UNISTD_H
  15. #include <unistd.h>
  16. #endif
  17. #include <fcntl.h>
  18. #include <time.h>
  19. #ifdef HAVE_SYS_STAT_H
  20. #include <sys/stat.h>
  21. #endif
  22. #ifdef HAVE_SYS_TYPES_H
  23. #include <sys/types.h>
  24. #endif
  25. #include "ext2_fs.h"
  26. #include "ext2fs.h"
  27. #include "e2image.h"
  28. #if defined(__powerpc__) && BB_BIG_ENDIAN
  29. /*
  30. * On the PowerPC, the big-endian variant of the ext2 filesystem
  31. * has its bitmaps stored as 32-bit words with bit 0 as the LSB
  32. * of each word. Thus a bitmap with only bit 0 set would be, as
  33. * a string of bytes, 00 00 00 01 00 ...
  34. * To cope with this, we byte-reverse each word of a bitmap if
  35. * we have a big-endian filesystem, that is, if we are *not*
  36. * byte-swapping other word-sized numbers.
  37. */
  38. #define EXT2_BIG_ENDIAN_BITMAPS
  39. #endif
  40. #ifdef EXT2_BIG_ENDIAN_BITMAPS
  41. static void ext2fs_swap_bitmap(ext2_filsys fs, char *bitmap, int nbytes)
  42. {
  43. __u32 *p = (__u32 *) bitmap;
  44. int n;
  45. for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
  46. *p = ext2fs_swab32(*p);
  47. }
  48. #endif
  49. errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs)
  50. {
  51. dgrp_t i;
  52. size_t nbytes;
  53. errcode_t retval;
  54. char * inode_bitmap = fs->inode_map->bitmap;
  55. char * bitmap_block = NULL;
  56. blk_t blk;
  57. EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  58. if (!(fs->flags & EXT2_FLAG_RW))
  59. return EXT2_ET_RO_FILSYS;
  60. if (!inode_bitmap)
  61. return 0;
  62. nbytes = (size_t) ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8);
  63. retval = ext2fs_get_mem(fs->blocksize, &bitmap_block);
  64. if (retval)
  65. return retval;
  66. memset(bitmap_block, 0xff, fs->blocksize);
  67. for (i = 0; i < fs->group_desc_count; i++) {
  68. memcpy(bitmap_block, inode_bitmap, nbytes);
  69. blk = fs->group_desc[i].bg_inode_bitmap;
  70. if (blk) {
  71. #ifdef EXT2_BIG_ENDIAN_BITMAPS
  72. if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
  73. (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
  74. ext2fs_swap_bitmap(fs, bitmap_block, nbytes);
  75. #endif
  76. retval = io_channel_write_blk(fs->io, blk, 1,
  77. bitmap_block);
  78. if (retval)
  79. return EXT2_ET_INODE_BITMAP_WRITE;
  80. }
  81. inode_bitmap += nbytes;
  82. }
  83. fs->flags &= ~EXT2_FLAG_IB_DIRTY;
  84. ext2fs_free_mem(&bitmap_block);
  85. return 0;
  86. }
  87. errcode_t ext2fs_write_block_bitmap (ext2_filsys fs)
  88. {
  89. dgrp_t i;
  90. unsigned int j;
  91. int nbytes;
  92. unsigned int nbits;
  93. errcode_t retval;
  94. char * block_bitmap = fs->block_map->bitmap;
  95. char * bitmap_block = NULL;
  96. blk_t blk;
  97. EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  98. if (!(fs->flags & EXT2_FLAG_RW))
  99. return EXT2_ET_RO_FILSYS;
  100. if (!block_bitmap)
  101. return 0;
  102. nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
  103. retval = ext2fs_get_mem(fs->blocksize, &bitmap_block);
  104. if (retval)
  105. return retval;
  106. memset(bitmap_block, 0xff, fs->blocksize);
  107. for (i = 0; i < fs->group_desc_count; i++) {
  108. memcpy(bitmap_block, block_bitmap, nbytes);
  109. if (i == fs->group_desc_count - 1) {
  110. /* Force bitmap padding for the last group */
  111. nbits = ((fs->super->s_blocks_count
  112. - fs->super->s_first_data_block)
  113. % EXT2_BLOCKS_PER_GROUP(fs->super));
  114. if (nbits)
  115. for (j = nbits; j < fs->blocksize * 8; j++)
  116. ext2fs_set_bit(j, bitmap_block);
  117. }
  118. blk = fs->group_desc[i].bg_block_bitmap;
  119. if (blk) {
  120. #ifdef EXT2_BIG_ENDIAN_BITMAPS
  121. if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
  122. (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
  123. ext2fs_swap_bitmap(fs, bitmap_block, nbytes);
  124. #endif
  125. retval = io_channel_write_blk(fs->io, blk, 1,
  126. bitmap_block);
  127. if (retval)
  128. return EXT2_ET_BLOCK_BITMAP_WRITE;
  129. }
  130. block_bitmap += nbytes;
  131. }
  132. fs->flags &= ~EXT2_FLAG_BB_DIRTY;
  133. ext2fs_free_mem(&bitmap_block);
  134. return 0;
  135. }
  136. static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
  137. {
  138. dgrp_t i;
  139. char *block_bitmap = 0, *inode_bitmap = 0;
  140. char *buf;
  141. errcode_t retval;
  142. int block_nbytes = (int) EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
  143. int inode_nbytes = (int) EXT2_INODES_PER_GROUP(fs->super) / 8;
  144. blk_t blk;
  145. EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  146. fs->write_bitmaps = ext2fs_write_bitmaps;
  147. retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
  148. if (retval)
  149. return retval;
  150. if (do_block) {
  151. ext2fs_free_block_bitmap(fs->block_map);
  152. sprintf(buf, "block bitmap for %s", fs->device_name);
  153. retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
  154. if (retval)
  155. goto cleanup;
  156. block_bitmap = fs->block_map->bitmap;
  157. }
  158. if (do_inode) {
  159. ext2fs_free_inode_bitmap(fs->inode_map);
  160. sprintf(buf, "inode bitmap for %s", fs->device_name);
  161. retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
  162. if (retval)
  163. goto cleanup;
  164. inode_bitmap = fs->inode_map->bitmap;
  165. }
  166. ext2fs_free_mem(&buf);
  167. if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
  168. if (inode_bitmap) {
  169. blk = (fs->image_header->offset_inodemap /
  170. fs->blocksize);
  171. retval = io_channel_read_blk(fs->image_io, blk,
  172. -(inode_nbytes * fs->group_desc_count),
  173. inode_bitmap);
  174. if (retval)
  175. goto cleanup;
  176. }
  177. if (block_bitmap) {
  178. blk = (fs->image_header->offset_blockmap /
  179. fs->blocksize);
  180. retval = io_channel_read_blk(fs->image_io, blk,
  181. -(block_nbytes * fs->group_desc_count),
  182. block_bitmap);
  183. if (retval)
  184. goto cleanup;
  185. }
  186. return 0;
  187. }
  188. for (i = 0; i < fs->group_desc_count; i++) {
  189. if (block_bitmap) {
  190. blk = fs->group_desc[i].bg_block_bitmap;
  191. if (blk) {
  192. retval = io_channel_read_blk(fs->io, blk,
  193. -block_nbytes, block_bitmap);
  194. if (retval) {
  195. retval = EXT2_ET_BLOCK_BITMAP_READ;
  196. goto cleanup;
  197. }
  198. #ifdef EXT2_BIG_ENDIAN_BITMAPS
  199. if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
  200. (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
  201. ext2fs_swap_bitmap(fs, block_bitmap, block_nbytes);
  202. #endif
  203. } else
  204. memset(block_bitmap, 0, block_nbytes);
  205. block_bitmap += block_nbytes;
  206. }
  207. if (inode_bitmap) {
  208. blk = fs->group_desc[i].bg_inode_bitmap;
  209. if (blk) {
  210. retval = io_channel_read_blk(fs->io, blk,
  211. -inode_nbytes, inode_bitmap);
  212. if (retval) {
  213. retval = EXT2_ET_INODE_BITMAP_READ;
  214. goto cleanup;
  215. }
  216. #ifdef EXT2_BIG_ENDIAN_BITMAPS
  217. if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
  218. (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
  219. ext2fs_swap_bitmap(fs, inode_bitmap, inode_nbytes);
  220. #endif
  221. } else
  222. memset(inode_bitmap, 0, inode_nbytes);
  223. inode_bitmap += inode_nbytes;
  224. }
  225. }
  226. return 0;
  227. cleanup:
  228. if (do_block) {
  229. ext2fs_free_mem(&fs->block_map);
  230. }
  231. if (do_inode) {
  232. ext2fs_free_mem(&fs->inode_map);
  233. }
  234. ext2fs_free_mem(&buf);
  235. return retval;
  236. }
  237. errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs)
  238. {
  239. return read_bitmaps(fs, 1, 0);
  240. }
  241. errcode_t ext2fs_read_block_bitmap(ext2_filsys fs)
  242. {
  243. return read_bitmaps(fs, 0, 1);
  244. }
  245. errcode_t ext2fs_read_bitmaps(ext2_filsys fs)
  246. {
  247. EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  248. if (fs->inode_map && fs->block_map)
  249. return 0;
  250. return read_bitmaps(fs, !fs->inode_map, !fs->block_map);
  251. }
  252. errcode_t ext2fs_write_bitmaps(ext2_filsys fs)
  253. {
  254. errcode_t retval;
  255. EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  256. if (fs->block_map && ext2fs_test_bb_dirty(fs)) {
  257. retval = ext2fs_write_block_bitmap(fs);
  258. if (retval)
  259. return retval;
  260. }
  261. if (fs->inode_map && ext2fs_test_ib_dirty(fs)) {
  262. retval = ext2fs_write_inode_bitmap(fs);
  263. if (retval)
  264. return retval;
  265. }
  266. return 0;
  267. }