rw_bitmaps.c revision 1d6fd6d0c3766a8165e69284c75812574a29c804
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 "config.h" 13#include <stdio.h> 14#include <string.h> 15#if HAVE_UNISTD_H 16#include <unistd.h> 17#endif 18#include <fcntl.h> 19#include <time.h> 20#ifdef HAVE_SYS_STAT_H 21#include <sys/stat.h> 22#endif 23#ifdef HAVE_SYS_TYPES_H 24#include <sys/types.h> 25#endif 26 27#include "ext2_fs.h" 28#include "ext2fs.h" 29#include "e2image.h" 30 31static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block) 32{ 33 dgrp_t i; 34 unsigned int j; 35 int block_nbytes, inode_nbytes; 36 unsigned int nbits; 37 errcode_t retval; 38 char *block_buf = NULL, *inode_buf = NULL; 39 int csum_flag = 0; 40 blk64_t blk; 41 blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block); 42 ext2_ino_t ino_itr = 1; 43 44 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 45 46 if (!(fs->flags & EXT2_FLAG_RW)) 47 return EXT2_ET_RO_FILSYS; 48 49 if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 50 EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) 51 csum_flag = 1; 52 53 inode_nbytes = block_nbytes = 0; 54 if (do_block) { 55 block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; 56 retval = io_channel_alloc_buf(fs->io, 0, &block_buf); 57 if (retval) 58 goto errout; 59 memset(block_buf, 0xff, fs->blocksize); 60 } 61 if (do_inode) { 62 inode_nbytes = (size_t) 63 ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8); 64 retval = io_channel_alloc_buf(fs->io, 0, &inode_buf); 65 if (retval) 66 goto errout; 67 memset(inode_buf, 0xff, fs->blocksize); 68 } 69 70 for (i = 0; i < fs->group_desc_count; i++) { 71 if (!do_block) 72 goto skip_block_bitmap; 73 74 if (csum_flag && ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) 75 ) 76 goto skip_this_block_bitmap; 77 78 retval = ext2fs_get_block_bitmap_range2(fs->block_map, 79 blk_itr, block_nbytes << 3, block_buf); 80 if (retval) 81 goto errout; 82 83 if (i == fs->group_desc_count - 1) { 84 /* Force bitmap padding for the last group */ 85 nbits = EXT2FS_NUM_B2C(fs, 86 ((ext2fs_blocks_count(fs->super) 87 - (__u64) fs->super->s_first_data_block) 88 % (__u64) EXT2_BLOCKS_PER_GROUP(fs->super))); 89 if (nbits) 90 for (j = nbits; j < fs->blocksize * 8; j++) 91 ext2fs_set_bit(j, block_buf); 92 } 93 blk = ext2fs_block_bitmap_loc(fs, i); 94 if (blk) { 95 retval = io_channel_write_blk64(fs->io, blk, 1, 96 block_buf); 97 if (retval) { 98 retval = EXT2_ET_BLOCK_BITMAP_WRITE; 99 goto errout; 100 } 101 } 102 skip_this_block_bitmap: 103 blk_itr += block_nbytes << 3; 104 skip_block_bitmap: 105 106 if (!do_inode) 107 continue; 108 109 if (csum_flag && ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) 110 ) 111 goto skip_this_inode_bitmap; 112 113 retval = ext2fs_get_inode_bitmap_range2(fs->inode_map, 114 ino_itr, inode_nbytes << 3, inode_buf); 115 if (retval) 116 goto errout; 117 118 blk = ext2fs_inode_bitmap_loc(fs, i); 119 if (blk) { 120 retval = io_channel_write_blk64(fs->io, blk, 1, 121 inode_buf); 122 if (retval) { 123 retval = EXT2_ET_INODE_BITMAP_WRITE; 124 goto errout; 125 } 126 } 127 skip_this_inode_bitmap: 128 ino_itr += inode_nbytes << 3; 129 130 } 131 if (do_block) { 132 fs->flags &= ~EXT2_FLAG_BB_DIRTY; 133 ext2fs_free_mem(&block_buf); 134 } 135 if (do_inode) { 136 fs->flags &= ~EXT2_FLAG_IB_DIRTY; 137 ext2fs_free_mem(&inode_buf); 138 } 139 return 0; 140errout: 141 if (inode_buf) 142 ext2fs_free_mem(&inode_buf); 143 if (block_buf) 144 ext2fs_free_mem(&block_buf); 145 return retval; 146} 147 148static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) 149{ 150 dgrp_t i; 151 char *block_bitmap = 0, *inode_bitmap = 0; 152 char *buf; 153 errcode_t retval; 154 int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; 155 int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8; 156 int csum_flag = 0; 157 unsigned int cnt; 158 blk64_t blk; 159 blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block); 160 blk64_t blk_cnt; 161 ext2_ino_t ino_itr = 1; 162 ext2_ino_t ino_cnt; 163 164 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 165 166 if ((block_nbytes > fs->blocksize) || (inode_nbytes > 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 } 294success_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 301cleanup: 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 319errcode_t ext2fs_read_inode_bitmap(ext2_filsys fs) 320{ 321 return read_bitmaps(fs, 1, 0); 322} 323 324errcode_t ext2fs_read_block_bitmap(ext2_filsys fs) 325{ 326 return read_bitmaps(fs, 0, 1); 327} 328 329errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs) 330{ 331 return write_bitmaps(fs, 1, 0); 332} 333 334errcode_t ext2fs_write_block_bitmap (ext2_filsys fs) 335{ 336 return write_bitmaps(fs, 0, 1); 337} 338 339errcode_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 347errcode_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