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