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