1 /* 2 * PROJECT: Mke2fs 3 * FILE: Bitmap.c 4 * PROGRAMMER: Matt Wu <mattwu@163.com> 5 * HOMEPAGE: http://ext2.yeah.net 6 */ 7 8 /* INCLUDES **************************************************************/ 9 10 #include "Mke2fs.h" 11 #include <debug.h> 12 13 /* DEFINITIONS ***********************************************************/ 14 15 /* FUNCTIONS *************************************************************/ 16 17 18 bool ext2_set_bit(int nr,void * addr) 19 { 20 int mask; 21 unsigned char *ADDR = (unsigned char *) addr; 22 23 ADDR += nr >> 3; 24 mask = 1 << (nr & 0x07); 25 *ADDR |= mask; 26 27 return true; 28 } 29 30 bool ext2_clear_bit(int nr, void * addr) 31 { 32 int mask; 33 unsigned char *ADDR = (unsigned char *) addr; 34 35 ADDR += nr >> 3; 36 mask = 1 << (nr & 0x07); 37 *ADDR &= ~mask; 38 return true; 39 } 40 41 bool ext2_test_bit(int nr, void * addr) 42 { 43 int mask; 44 const unsigned char *ADDR = (const unsigned char *) addr; 45 46 ADDR += nr >> 3; 47 mask = 1 << (nr & 0x07); 48 49 return ((mask & *ADDR) != 0); 50 } 51 52 bool ext2_mark_bitmap(PEXT2_BITMAP bitmap, ULONG bitno) 53 { 54 if ((bitno < bitmap->start) || (bitno > bitmap->end)) 55 { 56 return false; 57 } 58 59 return ext2_set_bit(bitno - bitmap->start, bitmap->bitmap); 60 } 61 62 bool ext2_unmark_bitmap(PEXT2_BITMAP bitmap, ULONG bitno) 63 { 64 if ((bitno < bitmap->start) || (bitno > bitmap->end)) 65 { 66 return false; 67 } 68 69 return ext2_clear_bit(bitno - bitmap->start, bitmap->bitmap); 70 } 71 72 73 bool ext2_test_block_bitmap(PEXT2_BLOCK_BITMAP bitmap, 74 ULONG block) 75 { 76 return ext2_test_bit(block - bitmap->start, bitmap->bitmap); 77 } 78 79 80 bool ext2_test_block_bitmap_range(PEXT2_BLOCK_BITMAP bitmap, 81 ULONG block, int num) 82 { 83 int i; 84 85 for (i=0; i < num; i++) 86 { 87 if (ext2_test_block_bitmap(bitmap, block+i)) 88 return false; 89 } 90 return true; 91 } 92 93 bool ext2_test_inode_bitmap(PEXT2_BLOCK_BITMAP bitmap, 94 ULONG inode) 95 { 96 return ext2_test_bit(inode - bitmap->start, bitmap->bitmap); 97 } 98 99 100 bool ext2_allocate_block_bitmap(PEXT2_FILESYS Ext2Sys) 101 { 102 ULONG size = 0; 103 104 PEXT2_SUPER_BLOCK pExt2Sb = Ext2Sys->ext2_sb; 105 Ext2Sys->block_map = (PEXT2_BLOCK_BITMAP) 106 RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(EXT2_BLOCK_BITMAP)); 107 108 if (!Ext2Sys->block_map) 109 { 110 DPRINT1("Mke2fs: error allocating block bitmap...\n"); 111 return false; 112 } 113 114 memset(Ext2Sys->block_map, 0, sizeof(EXT2_BLOCK_BITMAP)); 115 116 Ext2Sys->block_map->start = pExt2Sb->s_first_data_block; 117 Ext2Sys->block_map->end = pExt2Sb->s_blocks_count-1; 118 Ext2Sys->block_map->real_end = (EXT2_BLOCKS_PER_GROUP(pExt2Sb) 119 * Ext2Sys->group_desc_count) -1 + Ext2Sys->block_map->start; 120 121 size = (((Ext2Sys->block_map->real_end - Ext2Sys->block_map->start) / 8) + 1); 122 123 Ext2Sys->block_map->bitmap = 124 (char *)RtlAllocateHeap(RtlGetProcessHeap(), 0, size); 125 126 if (!Ext2Sys->block_map->bitmap) 127 { 128 RtlFreeHeap(RtlGetProcessHeap(), 0, Ext2Sys->block_map); 129 Ext2Sys->block_map = NULL; 130 DPRINT1("Mke2fs: error allocating block bitmap...\n"); 131 return false; 132 } 133 134 memset(Ext2Sys->block_map->bitmap, 0, size); 135 136 return true; 137 } 138 139 140 bool ext2_allocate_inode_bitmap(PEXT2_FILESYS Ext2Sys) 141 { 142 ULONG size = 0; 143 144 PEXT2_SUPER_BLOCK pExt2Sb = Ext2Sys->ext2_sb; 145 146 Ext2Sys->inode_map = (PEXT2_INODE_BITMAP) 147 RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(EXT2_INODE_BITMAP)); 148 149 if (!Ext2Sys->inode_map) 150 { 151 DPRINT1("Mke2fs: error allocating inode bitmap...\n"); 152 return false; 153 } 154 155 memset(Ext2Sys->inode_map, 0, sizeof(EXT2_INODE_BITMAP)); 156 157 Ext2Sys->inode_map->start = 1; 158 Ext2Sys->inode_map->end = pExt2Sb->s_inodes_count; 159 Ext2Sys->inode_map->real_end = (EXT2_INODES_PER_GROUP(pExt2Sb) 160 * Ext2Sys->group_desc_count); 161 162 size = (((Ext2Sys->inode_map->real_end - Ext2Sys->inode_map->start) / 8) + 1); 163 164 Ext2Sys->inode_map->bitmap = 165 (char *)RtlAllocateHeap(RtlGetProcessHeap(), 0, size); 166 167 if (!Ext2Sys->inode_map->bitmap) 168 { 169 RtlFreeHeap(RtlGetProcessHeap(), 0, Ext2Sys->inode_map); 170 Ext2Sys->inode_map = NULL; 171 DPRINT1("Mke2fs: error allocating block bitmap...\n"); 172 return false; 173 } 174 175 memset(Ext2Sys->inode_map->bitmap, 0, size); 176 177 return true; 178 } 179 180 void ext2_free_generic_bitmap(PEXT2_GENERIC_BITMAP bitmap) 181 { 182 if (!bitmap) 183 return; 184 185 if (bitmap->bitmap) 186 { 187 RtlFreeHeap(RtlGetProcessHeap(), 0, bitmap->bitmap); 188 bitmap->bitmap = 0; 189 } 190 191 RtlFreeHeap(RtlGetProcessHeap(), 0, bitmap); 192 } 193 194 void ext2_free_inode_bitmap(PEXT2_FILESYS Ext2Sys) 195 { 196 PEXT2_INODE_BITMAP bitmap = Ext2Sys->inode_map; 197 if (!bitmap) 198 return; 199 200 ext2_free_generic_bitmap(bitmap); 201 202 Ext2Sys->inode_map = NULL; 203 } 204 205 void ext2_free_block_bitmap(PEXT2_FILESYS Ext2Sys) 206 { 207 PEXT2_BLOCK_BITMAP bitmap = Ext2Sys->block_map; 208 if (!bitmap) 209 return; 210 211 ext2_free_generic_bitmap(bitmap); 212 213 Ext2Sys->block_map = NULL; 214 } 215 216 bool ext2_write_inode_bitmap(PEXT2_FILESYS fs) 217 { 218 ULONG i; 219 ULONG nbytes; 220 bool retval; 221 char *inode_bitmap = fs->inode_map->bitmap; 222 char *bitmap_block = NULL; 223 ULONG blk; 224 225 if (!inode_bitmap) 226 return false; 227 228 nbytes = (size_t) ((EXT2_INODES_PER_GROUP(fs->ext2_sb)+7) / 8); 229 230 bitmap_block = (char *)RtlAllocateHeap(RtlGetProcessHeap(), 0, fs->blocksize); 231 if (!bitmap_block) return false; 232 233 memset(bitmap_block, 0xff, fs->blocksize); 234 235 for (i = 0; i < fs->group_desc_count; i++) 236 { 237 memcpy(bitmap_block, inode_bitmap, nbytes); 238 blk = fs->group_desc[i].bg_inode_bitmap; 239 240 if (blk) 241 { 242 /* 243 #ifdef EXT2_BIG_ENDIAN_BITMAPS 244 if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || 245 (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))) 246 ext2_swap_bitmap(fs, bitmap_block, nbytes); 247 #endif 248 */ 249 retval = NT_SUCCESS(Ext2WriteDisk( 250 fs, 251 ((ULONGLONG)blk * fs->blocksize), 252 fs->blocksize, 253 (unsigned char *)bitmap_block)); 254 255 if (!retval) 256 { 257 RtlFreeHeap(RtlGetProcessHeap(), 0, bitmap_block); 258 return false; 259 } 260 } 261 262 inode_bitmap += nbytes; 263 } 264 265 RtlFreeHeap(RtlGetProcessHeap(), 0, bitmap_block); 266 267 return true; 268 } 269 270 bool ext2_write_block_bitmap (PEXT2_FILESYS fs) 271 { 272 ULONG i; 273 int j; 274 int nbytes; 275 int nbits; 276 bool retval; 277 char *block_bitmap = fs->block_map->bitmap; 278 char *bitmap_block = NULL; 279 ULONG blk; 280 281 if (!block_bitmap) 282 return false; 283 284 nbytes = EXT2_BLOCKS_PER_GROUP(fs->ext2_sb) / 8; 285 286 bitmap_block = (char *)RtlAllocateHeap(RtlGetProcessHeap(), 0, fs->blocksize); 287 if (!bitmap_block) 288 return false; 289 290 memset(bitmap_block, 0xff, fs->blocksize); 291 292 for (i = 0; i < fs->group_desc_count; i++) 293 { 294 memcpy(bitmap_block, block_bitmap, nbytes); 295 296 if (i == fs->group_desc_count - 1) 297 { 298 /* Force bitmap padding for the last group */ 299 nbits = (int) ((fs->ext2_sb->s_blocks_count 300 - fs->ext2_sb->s_first_data_block) 301 % EXT2_BLOCKS_PER_GROUP(fs->ext2_sb)); 302 303 if (nbits) 304 { 305 for (j = nbits; j < fs->blocksize * 8; j++) 306 { 307 ext2_set_bit(j, bitmap_block); 308 } 309 } 310 } 311 312 blk = fs->group_desc[i].bg_block_bitmap; 313 314 if (blk) 315 { 316 #ifdef EXT2_BIG_ENDIAN_BITMAPS 317 if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || 318 (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))) 319 ext2_swap_bitmap(fs, bitmap_block, nbytes); 320 #endif 321 retval = NT_SUCCESS(Ext2WriteDisk( 322 fs, 323 ((ULONGLONG)blk * fs->blocksize), 324 fs->blocksize, 325 (unsigned char *)bitmap_block)); 326 327 if (!retval) 328 { 329 RtlFreeHeap(RtlGetProcessHeap(), 0, bitmap_block); 330 return false; 331 } 332 } 333 334 block_bitmap += nbytes; 335 } 336 337 RtlFreeHeap(RtlGetProcessHeap(), 0, bitmap_block); 338 339 return true; 340 } 341 342 bool ext2_write_bitmaps(PEXT2_FILESYS fs) 343 { 344 bool retval; 345 346 if (fs->block_map) // && ext2fs_test_bb_dirty(fs)) 347 { 348 retval = ext2_write_block_bitmap(fs); 349 if (!retval) 350 return retval; 351 } 352 353 if (fs->inode_map) // && ext2fs_test_ib_dirty(fs)) 354 { 355 retval = ext2_write_inode_bitmap(fs); 356 if (!retval) 357 return retval; 358 } 359 360 return true; 361 } 362 363 364 bool read_bitmaps(PEXT2_FILESYS fs, int do_inode, int do_block) 365 { 366 ULONG i; 367 char *block_bitmap = 0, *inode_bitmap = 0; 368 bool retval = false; 369 ULONG block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->ext2_sb) / 8; 370 ULONG inode_nbytes = EXT2_INODES_PER_GROUP(fs->ext2_sb) / 8; 371 ULONG blk; 372 373 // fs->write_bitmaps = ext2_write_bitmaps; 374 375 if (do_block) 376 { 377 if (fs->block_map) 378 ext2_free_block_bitmap(fs); 379 380 retval = ext2_allocate_block_bitmap(fs); 381 382 if (!retval) 383 goto cleanup; 384 385 block_bitmap = fs->block_map->bitmap; 386 } 387 388 if (do_inode) 389 { 390 if (fs->inode_map) 391 ext2_free_inode_bitmap(fs); 392 393 retval = ext2_allocate_inode_bitmap(fs); 394 if (!retval) 395 goto cleanup; 396 397 inode_bitmap = fs->inode_map->bitmap; 398 } 399 400 for (i = 0; i < fs->group_desc_count; i++) 401 { 402 if (block_bitmap) 403 { 404 blk = fs->group_desc[i].bg_block_bitmap; 405 406 if (blk) 407 { 408 retval = NT_SUCCESS(Ext2ReadDisk( 409 fs, 410 ((ULONGLONG)blk * fs->blocksize), 411 block_nbytes, 412 (unsigned char *) block_bitmap)); 413 414 if (!retval) 415 { 416 goto cleanup; 417 } 418 419 #ifdef EXT2_BIG_ENDIAN_BITMAPS 420 if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || 421 (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))) 422 ext2_swap_bitmap(fs, block_bitmap, block_nbytes); 423 #endif 424 } 425 else 426 { 427 memset(block_bitmap, 0, block_nbytes); 428 } 429 430 block_bitmap += block_nbytes; 431 } 432 433 if (inode_bitmap) 434 { 435 blk = fs->group_desc[i].bg_inode_bitmap; 436 if (blk) 437 { 438 retval = NT_SUCCESS(Ext2ReadDisk( 439 fs, ((LONGLONG)blk * fs->blocksize), 440 inode_nbytes, 441 (unsigned char *)inode_bitmap)); 442 443 if (!retval) 444 { 445 goto cleanup; 446 } 447 448 #ifdef EXT2_BIG_ENDIAN_BITMAPS 449 if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || 450 (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))) 451 ext2_swap_bitmap(fs, inode_bitmap, inode_nbytes); 452 #endif 453 } 454 else 455 { 456 memset(inode_bitmap, 0, inode_nbytes); 457 } 458 459 inode_bitmap += inode_nbytes; 460 } 461 } 462 463 return true; 464 465 cleanup: 466 467 if (do_block) 468 { 469 RtlFreeHeap(RtlGetProcessHeap(), 0, fs->block_map); 470 fs->block_map = NULL; 471 } 472 473 if (do_inode) 474 { 475 RtlFreeHeap(RtlGetProcessHeap(), 0, fs->inode_map); 476 fs->inode_map = 0; 477 } 478 479 return false; 480 } 481 482 bool ext2_read_inode_bitmap (PEXT2_FILESYS fs) 483 { 484 return read_bitmaps(fs, 1, 0); 485 } 486 487 bool ext2_read_block_bitmap(PEXT2_FILESYS fs) 488 { 489 return read_bitmaps(fs, 0, 1); 490 } 491 492 bool ext2_read_bitmaps(PEXT2_FILESYS fs) 493 { 494 495 if (fs->inode_map && fs->block_map) 496 return 0; 497 498 return read_bitmaps(fs, !fs->inode_map, !fs->block_map); 499 } 500 501