rw_bitmaps.c revision e48bf256e99e4923c6193ff78000af18c700d93d
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 > (int) fs->blocksize) || 167 (inode_nbytes > (int) fs->blocksize)) 168 return EXT2_ET_CORRUPT_SUPERBLOCK; 169 170 fs->write_bitmaps = ext2fs_write_bitmaps; 171 172 if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 173 EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) 174 csum_flag = 1; 175 176 retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf); 177 if (retval) 178 return retval; 179 if (do_block) { 180 if (fs->block_map) 181 ext2fs_free_block_bitmap(fs->block_map); 182 strcpy(buf, "block bitmap for "); 183 strcat(buf, fs->device_name); 184 retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map); 185 if (retval) 186 goto cleanup; 187 retval = io_channel_alloc_buf(fs->io, 0, &block_bitmap); 188 if (retval) 189 goto cleanup; 190 } else 191 block_nbytes = 0; 192 if (do_inode) { 193 if (fs->inode_map) 194 ext2fs_free_inode_bitmap(fs->inode_map); 195 strcpy(buf, "inode bitmap for "); 196 strcat(buf, fs->device_name); 197 retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map); 198 if (retval) 199 goto cleanup; 200 retval = io_channel_alloc_buf(fs->io, 0, &inode_bitmap); 201 if (retval) 202 goto cleanup; 203 } else 204 inode_nbytes = 0; 205 ext2fs_free_mem(&buf); 206 207 if (fs->flags & EXT2_FLAG_IMAGE_FILE) { 208 blk = (fs->image_header->offset_inodemap / fs->blocksize); 209 ino_cnt = fs->super->s_inodes_count; 210 while (inode_nbytes > 0) { 211 retval = io_channel_read_blk64(fs->image_io, blk++, 212 1, inode_bitmap); 213 if (retval) 214 goto cleanup; 215 cnt = fs->blocksize << 3; 216 if (cnt > ino_cnt) 217 cnt = ino_cnt; 218 retval = ext2fs_set_inode_bitmap_range2(fs->inode_map, 219 ino_itr, cnt, inode_bitmap); 220 if (retval) 221 goto cleanup; 222 ino_itr += fs->blocksize << 3; 223 ino_cnt -= fs->blocksize << 3; 224 inode_nbytes -= fs->blocksize; 225 } 226 blk = (fs->image_header->offset_blockmap / 227 fs->blocksize); 228 blk_cnt = (blk64_t)EXT2_CLUSTERS_PER_GROUP(fs->super) * 229 fs->group_desc_count; 230 while (block_nbytes > 0) { 231 retval = io_channel_read_blk64(fs->image_io, blk++, 232 1, block_bitmap); 233 if (retval) 234 goto cleanup; 235 cnt = fs->blocksize << 3; 236 if (cnt > blk_cnt) 237 cnt = blk_cnt; 238 retval = ext2fs_set_block_bitmap_range2(fs->block_map, 239 blk_itr, cnt, block_bitmap); 240 if (retval) 241 goto cleanup; 242 blk_itr += fs->blocksize << 3; 243 blk_cnt -= fs->blocksize << 3; 244 block_nbytes -= fs->blocksize; 245 } 246 goto success_cleanup; 247 } 248 249 for (i = 0; i < fs->group_desc_count; i++) { 250 if (block_bitmap) { 251 blk = ext2fs_block_bitmap_loc(fs, i); 252 if (csum_flag && 253 ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) && 254 ext2fs_group_desc_csum_verify(fs, i)) 255 blk = 0; 256 if (blk) { 257 retval = io_channel_read_blk64(fs->io, blk, 258 1, block_bitmap); 259 if (retval) { 260 retval = EXT2_ET_BLOCK_BITMAP_READ; 261 goto cleanup; 262 } 263 } else 264 memset(block_bitmap, 0, block_nbytes); 265 cnt = block_nbytes << 3; 266 retval = ext2fs_set_block_bitmap_range2(fs->block_map, 267 blk_itr, cnt, block_bitmap); 268 if (retval) 269 goto cleanup; 270 blk_itr += block_nbytes << 3; 271 } 272 if (inode_bitmap) { 273 blk = ext2fs_inode_bitmap_loc(fs, i); 274 if (csum_flag && 275 ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) && 276 ext2fs_group_desc_csum_verify(fs, i)) 277 blk = 0; 278 if (blk) { 279 retval = io_channel_read_blk64(fs->io, blk, 280 1, inode_bitmap); 281 if (retval) { 282 retval = EXT2_ET_INODE_BITMAP_READ; 283 goto cleanup; 284 } 285 } else 286 memset(inode_bitmap, 0, inode_nbytes); 287 cnt = inode_nbytes << 3; 288 retval = ext2fs_set_inode_bitmap_range2(fs->inode_map, 289 ino_itr, cnt, inode_bitmap); 290 if (retval) 291 goto cleanup; 292 ino_itr += inode_nbytes << 3; 293 } 294 } 295success_cleanup: 296 if (inode_bitmap) 297 ext2fs_free_mem(&inode_bitmap); 298 if (block_bitmap) 299 ext2fs_free_mem(&block_bitmap); 300 return 0; 301 302cleanup: 303 if (do_block) { 304 ext2fs_free_mem(&fs->block_map); 305 fs->block_map = 0; 306 } 307 if (do_inode) { 308 ext2fs_free_mem(&fs->inode_map); 309 fs->inode_map = 0; 310 } 311 if (inode_bitmap) 312 ext2fs_free_mem(&inode_bitmap); 313 if (block_bitmap) 314 ext2fs_free_mem(&block_bitmap); 315 if (buf) 316 ext2fs_free_mem(&buf); 317 return retval; 318} 319 320errcode_t ext2fs_read_inode_bitmap(ext2_filsys fs) 321{ 322 return read_bitmaps(fs, 1, 0); 323} 324 325errcode_t ext2fs_read_block_bitmap(ext2_filsys fs) 326{ 327 return read_bitmaps(fs, 0, 1); 328} 329 330errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs) 331{ 332 return write_bitmaps(fs, 1, 0); 333} 334 335errcode_t ext2fs_write_block_bitmap (ext2_filsys fs) 336{ 337 return write_bitmaps(fs, 0, 1); 338} 339 340errcode_t ext2fs_read_bitmaps(ext2_filsys fs) 341{ 342 if (fs->inode_map && fs->block_map) 343 return 0; 344 345 return read_bitmaps(fs, !fs->inode_map, !fs->block_map); 346} 347 348errcode_t ext2fs_write_bitmaps(ext2_filsys fs) 349{ 350 int do_inode = fs->inode_map && ext2fs_test_ib_dirty(fs); 351 int do_block = fs->block_map && ext2fs_test_bb_dirty(fs); 352 353 if (!do_inode && !do_block) 354 return 0; 355 356 return write_bitmaps(fs, do_inode, do_block); 357} 358