1 /* 2 * rw_bitmaps.c --- routines to read and write the inode and block bitmaps. 3 * 4 * Copyright (C) 1993, 1994, 1994, 1996 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 <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 26 #include "ext2_fs.h" 27 #include "ext2fs.h" 28 #include "e2image.h" 29 30 static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block) 31 { 32 dgrp_t i; 33 unsigned int j; 34 int block_nbytes, inode_nbytes; 35 unsigned int nbits; 36 errcode_t retval; 37 char *block_buf = NULL, *inode_buf = NULL; 38 int csum_flag = 0; 39 blk64_t blk; 40 blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block); 41 ext2_ino_t ino_itr = 1; 42 43 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 44 45 if (!(fs->flags & EXT2_FLAG_RW)) 46 return EXT2_ET_RO_FILSYS; 47 48 if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 49 EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) 50 csum_flag = 1; 51 52 inode_nbytes = block_nbytes = 0; 53 if (do_block) { 54 block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; 55 retval = io_channel_alloc_buf(fs->io, 0, &block_buf); 56 if (retval) 57 goto errout; 58 memset(block_buf, 0xff, fs->blocksize); 59 } 60 if (do_inode) { 61 inode_nbytes = (size_t) 62 ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8); 63 retval = io_channel_alloc_buf(fs->io, 0, &inode_buf); 64 if (retval) 65 goto errout; 66 memset(inode_buf, 0xff, fs->blocksize); 67 } 68 69 for (i = 0; i < fs->group_desc_count; i++) { 70 if (!do_block) 71 goto skip_block_bitmap; 72 73 if (csum_flag && ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) 74 ) 75 goto skip_this_block_bitmap; 76 77 retval = ext2fs_get_block_bitmap_range2(fs->block_map, 78 blk_itr, block_nbytes << 3, block_buf); 79 if (retval) 80 goto errout; 81 82 if (i == fs->group_desc_count - 1) { 83 /* Force bitmap padding for the last group */ 84 nbits = EXT2FS_NUM_B2C(fs, 85 ((ext2fs_blocks_count(fs->super) 86 - (__u64) fs->super->s_first_data_block) 87 % (__u64) EXT2_BLOCKS_PER_GROUP(fs->super))); 88 if (nbits) 89 for (j = nbits; j < fs->blocksize * 8; j++) 90 ext2fs_set_bit(j, block_buf); 91 } 92 blk = ext2fs_block_bitmap_loc(fs, i); 93 if (blk) { 94 retval = io_channel_write_blk64(fs->io, blk, 1, 95 block_buf); 96 if (retval) { 97 retval = EXT2_ET_BLOCK_BITMAP_WRITE; 98 goto errout; 99 } 100 } 101 skip_this_block_bitmap: 102 blk_itr += block_nbytes << 3; 103 skip_block_bitmap: 104 105 if (!do_inode) 106 continue; 107 108 if (csum_flag && ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) 109 ) 110 goto skip_this_inode_bitmap; 111 112 retval = ext2fs_get_inode_bitmap_range2(fs->inode_map, 113 ino_itr, inode_nbytes << 3, inode_buf); 114 if (retval) 115 goto errout; 116 117 blk = ext2fs_inode_bitmap_loc(fs, i); 118 if (blk) { 119 retval = io_channel_write_blk64(fs->io, blk, 1, 120 inode_buf); 121 if (retval) { 122 retval = EXT2_ET_INODE_BITMAP_WRITE; 123 goto errout; 124 } 125 } 126 skip_this_inode_bitmap: 127 ino_itr += inode_nbytes << 3; 128 129 } 130 if (do_block) { 131 fs->flags &= ~EXT2_FLAG_BB_DIRTY; 132 ext2fs_free_mem(&block_buf); 133 } 134 if (do_inode) { 135 fs->flags &= ~EXT2_FLAG_IB_DIRTY; 136 ext2fs_free_mem(&inode_buf); 137 } 138 return 0; 139 errout: 140 if (inode_buf) 141 ext2fs_free_mem(&inode_buf); 142 if (block_buf) 143 ext2fs_free_mem(&block_buf); 144 return retval; 145 } 146 147 static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) 148 { 149 dgrp_t i; 150 char *block_bitmap = 0, *inode_bitmap = 0; 151 char *buf; 152 errcode_t retval; 153 int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; 154 int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8; 155 int csum_flag = 0; 156 unsigned int cnt; 157 blk64_t blk; 158 blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block); 159 blk64_t blk_cnt; 160 ext2_ino_t ino_itr = 1; 161 ext2_ino_t ino_cnt; 162 163 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 164 165 if ((block_nbytes > (int) fs->blocksize) || 166 (inode_nbytes > (int) fs->blocksize)) 167 return EXT2_ET_CORRUPT_SUPERBLOCK; 168 169 fs->write_bitmaps = ext2fs_write_bitmaps; 170 171 if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 172 EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) 173 csum_flag = 1; 174 175 retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf); 176 if (retval) 177 return retval; 178 if (do_block) { 179 if (fs->block_map) 180 ext2fs_free_block_bitmap(fs->block_map); 181 strcpy(buf, "block bitmap for "); 182 strcat(buf, fs->device_name); 183 retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map); 184 if (retval) 185 goto cleanup; 186 retval = io_channel_alloc_buf(fs->io, 0, &block_bitmap); 187 if (retval) 188 goto cleanup; 189 } else 190 block_nbytes = 0; 191 if (do_inode) { 192 if (fs->inode_map) 193 ext2fs_free_inode_bitmap(fs->inode_map); 194 strcpy(buf, "inode bitmap for "); 195 strcat(buf, fs->device_name); 196 retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map); 197 if (retval) 198 goto cleanup; 199 retval = io_channel_alloc_buf(fs->io, 0, &inode_bitmap); 200 if (retval) 201 goto cleanup; 202 } else 203 inode_nbytes = 0; 204 ext2fs_free_mem(&buf); 205 206 if (fs->flags & EXT2_FLAG_IMAGE_FILE) { 207 blk = (fs->image_header->offset_inodemap / fs->blocksize); 208 ino_cnt = fs->super->s_inodes_count; 209 while (inode_nbytes > 0) { 210 retval = io_channel_read_blk64(fs->image_io, blk++, 211 1, inode_bitmap); 212 if (retval) 213 goto cleanup; 214 cnt = fs->blocksize << 3; 215 if (cnt > ino_cnt) 216 cnt = ino_cnt; 217 retval = ext2fs_set_inode_bitmap_range2(fs->inode_map, 218 ino_itr, cnt, inode_bitmap); 219 if (retval) 220 goto cleanup; 221 ino_itr += fs->blocksize << 3; 222 ino_cnt -= fs->blocksize << 3; 223 inode_nbytes -= fs->blocksize; 224 } 225 blk = (fs->image_header->offset_blockmap / 226 fs->blocksize); 227 blk_cnt = (blk64_t)EXT2_CLUSTERS_PER_GROUP(fs->super) * 228 fs->group_desc_count; 229 while (block_nbytes > 0) { 230 retval = io_channel_read_blk64(fs->image_io, blk++, 231 1, block_bitmap); 232 if (retval) 233 goto cleanup; 234 cnt = fs->blocksize << 3; 235 if (cnt > blk_cnt) 236 cnt = blk_cnt; 237 retval = ext2fs_set_block_bitmap_range2(fs->block_map, 238 blk_itr, cnt, block_bitmap); 239 if (retval) 240 goto cleanup; 241 blk_itr += fs->blocksize << 3; 242 blk_cnt -= fs->blocksize << 3; 243 block_nbytes -= fs->blocksize; 244 } 245 goto success_cleanup; 246 } 247 248 for (i = 0; i < fs->group_desc_count; i++) { 249 if (block_bitmap) { 250 blk = ext2fs_block_bitmap_loc(fs, i); 251 if (csum_flag && 252 ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) && 253 ext2fs_group_desc_csum_verify(fs, i)) 254 blk = 0; 255 if (blk) { 256 retval = io_channel_read_blk64(fs->io, blk, 257 1, block_bitmap); 258 if (retval) { 259 retval = EXT2_ET_BLOCK_BITMAP_READ; 260 goto cleanup; 261 } 262 } else 263 memset(block_bitmap, 0, block_nbytes); 264 cnt = block_nbytes << 3; 265 retval = ext2fs_set_block_bitmap_range2(fs->block_map, 266 blk_itr, cnt, block_bitmap); 267 if (retval) 268 goto cleanup; 269 blk_itr += block_nbytes << 3; 270 } 271 if (inode_bitmap) { 272 blk = ext2fs_inode_bitmap_loc(fs, i); 273 if (csum_flag && 274 ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) && 275 ext2fs_group_desc_csum_verify(fs, i)) 276 blk = 0; 277 if (blk) { 278 retval = io_channel_read_blk64(fs->io, blk, 279 1, inode_bitmap); 280 if (retval) { 281 retval = EXT2_ET_INODE_BITMAP_READ; 282 goto cleanup; 283 } 284 } else 285 memset(inode_bitmap, 0, inode_nbytes); 286 cnt = inode_nbytes << 3; 287 retval = ext2fs_set_inode_bitmap_range2(fs->inode_map, 288 ino_itr, cnt, inode_bitmap); 289 if (retval) 290 goto cleanup; 291 ino_itr += inode_nbytes << 3; 292 } 293 } 294 success_cleanup: 295 if (inode_bitmap) 296 ext2fs_free_mem(&inode_bitmap); 297 if (block_bitmap) 298 ext2fs_free_mem(&block_bitmap); 299 return 0; 300 301 cleanup: 302 if (do_block) { 303 ext2fs_free_mem(&fs->block_map); 304 fs->block_map = 0; 305 } 306 if (do_inode) { 307 ext2fs_free_mem(&fs->inode_map); 308 fs->inode_map = 0; 309 } 310 if (inode_bitmap) 311 ext2fs_free_mem(&inode_bitmap); 312 if (block_bitmap) 313 ext2fs_free_mem(&block_bitmap); 314 if (buf) 315 ext2fs_free_mem(&buf); 316 return retval; 317 } 318 319 errcode_t ext2fs_read_inode_bitmap(ext2_filsys fs) 320 { 321 return read_bitmaps(fs, 1, 0); 322 } 323 324 errcode_t ext2fs_read_block_bitmap(ext2_filsys fs) 325 { 326 return read_bitmaps(fs, 0, 1); 327 } 328 329 errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs) 330 { 331 return write_bitmaps(fs, 1, 0); 332 } 333 334 errcode_t ext2fs_write_block_bitmap (ext2_filsys fs) 335 { 336 return write_bitmaps(fs, 0, 1); 337 } 338 339 errcode_t ext2fs_read_bitmaps(ext2_filsys fs) 340 { 341 if (fs->inode_map && fs->block_map) 342 return 0; 343 344 return read_bitmaps(fs, !fs->inode_map, !fs->block_map); 345 } 346 347 errcode_t ext2fs_write_bitmaps(ext2_filsys fs) 348 { 349 int do_inode = fs->inode_map && ext2fs_test_ib_dirty(fs); 350 int do_block = fs->block_map && ext2fs_test_bb_dirty(fs); 351 352 if (!do_inode && !do_block) 353 return 0; 354 355 return write_bitmaps(fs, do_inode, do_block); 356 } 357