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