mirror of
https://github.com/reactos/reactos.git
synced 2024-12-04 00:43:32 +08:00
501 lines
12 KiB
C
501 lines
12 KiB
C
/*
|
|
* PROJECT: Mke2fs
|
|
* FILE: Bitmap.c
|
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
|
* HOMEPAGE: http://ext2.yeah.net
|
|
*/
|
|
|
|
/* INCLUDES **************************************************************/
|
|
|
|
#include "Mke2fs.h"
|
|
#include <debug.h>
|
|
|
|
/* DEFINITIONS ***********************************************************/
|
|
|
|
/* FUNCTIONS *************************************************************/
|
|
|
|
|
|
bool ext2_set_bit(int nr,void * addr)
|
|
{
|
|
int mask;
|
|
unsigned char *ADDR = (unsigned char *) addr;
|
|
|
|
ADDR += nr >> 3;
|
|
mask = 1 << (nr & 0x07);
|
|
*ADDR |= mask;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ext2_clear_bit(int nr, void * addr)
|
|
{
|
|
int mask;
|
|
unsigned char *ADDR = (unsigned char *) addr;
|
|
|
|
ADDR += nr >> 3;
|
|
mask = 1 << (nr & 0x07);
|
|
*ADDR &= ~mask;
|
|
return true;
|
|
}
|
|
|
|
bool ext2_test_bit(int nr, void * addr)
|
|
{
|
|
int mask;
|
|
const unsigned char *ADDR = (const unsigned char *) addr;
|
|
|
|
ADDR += nr >> 3;
|
|
mask = 1 << (nr & 0x07);
|
|
|
|
return ((mask & *ADDR) != 0);
|
|
}
|
|
|
|
bool ext2_mark_bitmap(PEXT2_BITMAP bitmap, ULONG bitno)
|
|
{
|
|
if ((bitno < bitmap->start) || (bitno > bitmap->end))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return ext2_set_bit(bitno - bitmap->start, bitmap->bitmap);
|
|
}
|
|
|
|
bool ext2_unmark_bitmap(PEXT2_BITMAP bitmap, ULONG bitno)
|
|
{
|
|
if ((bitno < bitmap->start) || (bitno > bitmap->end))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return ext2_clear_bit(bitno - bitmap->start, bitmap->bitmap);
|
|
}
|
|
|
|
|
|
bool ext2_test_block_bitmap(PEXT2_BLOCK_BITMAP bitmap,
|
|
ULONG block)
|
|
{
|
|
return ext2_test_bit(block - bitmap->start, bitmap->bitmap);
|
|
}
|
|
|
|
|
|
bool ext2_test_block_bitmap_range(PEXT2_BLOCK_BITMAP bitmap,
|
|
ULONG block, int num)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i < num; i++)
|
|
{
|
|
if (ext2_test_block_bitmap(bitmap, block+i))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool ext2_test_inode_bitmap(PEXT2_BLOCK_BITMAP bitmap,
|
|
ULONG inode)
|
|
{
|
|
return ext2_test_bit(inode - bitmap->start, bitmap->bitmap);
|
|
}
|
|
|
|
|
|
bool ext2_allocate_block_bitmap(PEXT2_FILESYS Ext2Sys)
|
|
{
|
|
ULONG size = 0;
|
|
|
|
PEXT2_SUPER_BLOCK pExt2Sb = Ext2Sys->ext2_sb;
|
|
Ext2Sys->block_map = (PEXT2_BLOCK_BITMAP)
|
|
RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(EXT2_BLOCK_BITMAP));
|
|
|
|
if (!Ext2Sys->block_map)
|
|
{
|
|
DPRINT1("Mke2fs: error allocating block bitmap...\n");
|
|
return false;
|
|
}
|
|
|
|
memset(Ext2Sys->block_map, 0, sizeof(EXT2_BLOCK_BITMAP));
|
|
|
|
Ext2Sys->block_map->start = pExt2Sb->s_first_data_block;
|
|
Ext2Sys->block_map->end = pExt2Sb->s_blocks_count-1;
|
|
Ext2Sys->block_map->real_end = (EXT2_BLOCKS_PER_GROUP(pExt2Sb)
|
|
* Ext2Sys->group_desc_count) -1 + Ext2Sys->block_map->start;
|
|
|
|
size = (((Ext2Sys->block_map->real_end - Ext2Sys->block_map->start) / 8) + 1);
|
|
|
|
Ext2Sys->block_map->bitmap =
|
|
(char *)RtlAllocateHeap(RtlGetProcessHeap(), 0, size);
|
|
|
|
if (!Ext2Sys->block_map->bitmap)
|
|
{
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Ext2Sys->block_map);
|
|
Ext2Sys->block_map = NULL;
|
|
DPRINT1("Mke2fs: error allocating block bitmap...\n");
|
|
return false;
|
|
}
|
|
|
|
memset(Ext2Sys->block_map->bitmap, 0, size);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool ext2_allocate_inode_bitmap(PEXT2_FILESYS Ext2Sys)
|
|
{
|
|
ULONG size = 0;
|
|
|
|
PEXT2_SUPER_BLOCK pExt2Sb = Ext2Sys->ext2_sb;
|
|
|
|
Ext2Sys->inode_map = (PEXT2_INODE_BITMAP)
|
|
RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(EXT2_INODE_BITMAP));
|
|
|
|
if (!Ext2Sys->inode_map)
|
|
{
|
|
DPRINT1("Mke2fs: error allocating inode bitmap...\n");
|
|
return false;
|
|
}
|
|
|
|
memset(Ext2Sys->inode_map, 0, sizeof(EXT2_INODE_BITMAP));
|
|
|
|
Ext2Sys->inode_map->start = 1;
|
|
Ext2Sys->inode_map->end = pExt2Sb->s_inodes_count;
|
|
Ext2Sys->inode_map->real_end = (EXT2_INODES_PER_GROUP(pExt2Sb)
|
|
* Ext2Sys->group_desc_count);
|
|
|
|
size = (((Ext2Sys->inode_map->real_end - Ext2Sys->inode_map->start) / 8) + 1);
|
|
|
|
Ext2Sys->inode_map->bitmap =
|
|
(char *)RtlAllocateHeap(RtlGetProcessHeap(), 0, size);
|
|
|
|
if (!Ext2Sys->inode_map->bitmap)
|
|
{
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Ext2Sys->inode_map);
|
|
Ext2Sys->inode_map = NULL;
|
|
DPRINT1("Mke2fs: error allocating block bitmap...\n");
|
|
return false;
|
|
}
|
|
|
|
memset(Ext2Sys->inode_map->bitmap, 0, size);
|
|
|
|
return true;
|
|
}
|
|
|
|
void ext2_free_generic_bitmap(PEXT2_GENERIC_BITMAP bitmap)
|
|
{
|
|
if (!bitmap)
|
|
return;
|
|
|
|
if (bitmap->bitmap)
|
|
{
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, bitmap->bitmap);
|
|
bitmap->bitmap = 0;
|
|
}
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, bitmap);
|
|
}
|
|
|
|
void ext2_free_inode_bitmap(PEXT2_FILESYS Ext2Sys)
|
|
{
|
|
PEXT2_INODE_BITMAP bitmap = Ext2Sys->inode_map;
|
|
if (!bitmap)
|
|
return;
|
|
|
|
ext2_free_generic_bitmap(bitmap);
|
|
|
|
Ext2Sys->inode_map = NULL;
|
|
}
|
|
|
|
void ext2_free_block_bitmap(PEXT2_FILESYS Ext2Sys)
|
|
{
|
|
PEXT2_BLOCK_BITMAP bitmap = Ext2Sys->block_map;
|
|
if (!bitmap)
|
|
return;
|
|
|
|
ext2_free_generic_bitmap(bitmap);
|
|
|
|
Ext2Sys->block_map = NULL;
|
|
}
|
|
|
|
bool ext2_write_inode_bitmap(PEXT2_FILESYS fs)
|
|
{
|
|
ULONG i;
|
|
ULONG nbytes;
|
|
bool retval;
|
|
char *inode_bitmap = fs->inode_map->bitmap;
|
|
char *bitmap_block = NULL;
|
|
ULONG blk;
|
|
|
|
if (!inode_bitmap)
|
|
return false;
|
|
|
|
nbytes = (size_t) ((EXT2_INODES_PER_GROUP(fs->ext2_sb)+7) / 8);
|
|
|
|
bitmap_block = (char *)RtlAllocateHeap(RtlGetProcessHeap(), 0, fs->blocksize);
|
|
if (!bitmap_block) return false;
|
|
|
|
memset(bitmap_block, 0xff, fs->blocksize);
|
|
|
|
for (i = 0; i < fs->group_desc_count; i++)
|
|
{
|
|
memcpy(bitmap_block, inode_bitmap, nbytes);
|
|
blk = fs->group_desc[i].bg_inode_bitmap;
|
|
|
|
if (blk)
|
|
{
|
|
/*
|
|
#ifdef EXT2_BIG_ENDIAN_BITMAPS
|
|
if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
|
|
(fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
|
|
ext2_swap_bitmap(fs, bitmap_block, nbytes);
|
|
#endif
|
|
*/
|
|
retval = NT_SUCCESS(Ext2WriteDisk(
|
|
fs,
|
|
((ULONGLONG)blk * fs->blocksize),
|
|
fs->blocksize,
|
|
(unsigned char *)bitmap_block));
|
|
|
|
if (!retval)
|
|
{
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, bitmap_block);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
inode_bitmap += nbytes;
|
|
}
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, bitmap_block);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ext2_write_block_bitmap (PEXT2_FILESYS fs)
|
|
{
|
|
ULONG i;
|
|
int j;
|
|
int nbytes;
|
|
int nbits;
|
|
bool retval;
|
|
char *block_bitmap = fs->block_map->bitmap;
|
|
char *bitmap_block = NULL;
|
|
ULONG blk;
|
|
|
|
if (!block_bitmap)
|
|
return false;
|
|
|
|
nbytes = EXT2_BLOCKS_PER_GROUP(fs->ext2_sb) / 8;
|
|
|
|
bitmap_block = (char *)RtlAllocateHeap(RtlGetProcessHeap(), 0, fs->blocksize);
|
|
if (!bitmap_block)
|
|
return false;
|
|
|
|
memset(bitmap_block, 0xff, fs->blocksize);
|
|
|
|
for (i = 0; i < fs->group_desc_count; i++)
|
|
{
|
|
memcpy(bitmap_block, block_bitmap, nbytes);
|
|
|
|
if (i == fs->group_desc_count - 1)
|
|
{
|
|
/* Force bitmap padding for the last group */
|
|
nbits = (int) ((fs->ext2_sb->s_blocks_count
|
|
- fs->ext2_sb->s_first_data_block)
|
|
% EXT2_BLOCKS_PER_GROUP(fs->ext2_sb));
|
|
|
|
if (nbits)
|
|
{
|
|
for (j = nbits; j < fs->blocksize * 8; j++)
|
|
{
|
|
ext2_set_bit(j, bitmap_block);
|
|
}
|
|
}
|
|
}
|
|
|
|
blk = fs->group_desc[i].bg_block_bitmap;
|
|
|
|
if (blk)
|
|
{
|
|
#ifdef EXT2_BIG_ENDIAN_BITMAPS
|
|
if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
|
|
(fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
|
|
ext2_swap_bitmap(fs, bitmap_block, nbytes);
|
|
#endif
|
|
retval = NT_SUCCESS(Ext2WriteDisk(
|
|
fs,
|
|
((ULONGLONG)blk * fs->blocksize),
|
|
fs->blocksize,
|
|
(unsigned char *)bitmap_block));
|
|
|
|
if (!retval)
|
|
{
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, bitmap_block);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
block_bitmap += nbytes;
|
|
}
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, bitmap_block);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ext2_write_bitmaps(PEXT2_FILESYS fs)
|
|
{
|
|
bool retval;
|
|
|
|
if (fs->block_map) // && ext2fs_test_bb_dirty(fs))
|
|
{
|
|
retval = ext2_write_block_bitmap(fs);
|
|
if (!retval)
|
|
return retval;
|
|
}
|
|
|
|
if (fs->inode_map) // && ext2fs_test_ib_dirty(fs))
|
|
{
|
|
retval = ext2_write_inode_bitmap(fs);
|
|
if (!retval)
|
|
return retval;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool read_bitmaps(PEXT2_FILESYS fs, int do_inode, int do_block)
|
|
{
|
|
ULONG i;
|
|
char *block_bitmap = 0, *inode_bitmap = 0;
|
|
bool retval = false;
|
|
ULONG block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->ext2_sb) / 8;
|
|
ULONG inode_nbytes = EXT2_INODES_PER_GROUP(fs->ext2_sb) / 8;
|
|
ULONG blk;
|
|
|
|
// fs->write_bitmaps = ext2_write_bitmaps;
|
|
|
|
if (do_block)
|
|
{
|
|
if (fs->block_map)
|
|
ext2_free_block_bitmap(fs);
|
|
|
|
retval = ext2_allocate_block_bitmap(fs);
|
|
|
|
if (!retval)
|
|
goto cleanup;
|
|
|
|
block_bitmap = fs->block_map->bitmap;
|
|
}
|
|
|
|
if (do_inode)
|
|
{
|
|
if (fs->inode_map)
|
|
ext2_free_inode_bitmap(fs);
|
|
|
|
retval = ext2_allocate_inode_bitmap(fs);
|
|
if (!retval)
|
|
goto cleanup;
|
|
|
|
inode_bitmap = fs->inode_map->bitmap;
|
|
}
|
|
|
|
for (i = 0; i < fs->group_desc_count; i++)
|
|
{
|
|
if (block_bitmap)
|
|
{
|
|
blk = fs->group_desc[i].bg_block_bitmap;
|
|
|
|
if (blk)
|
|
{
|
|
retval = NT_SUCCESS(Ext2ReadDisk(
|
|
fs,
|
|
((ULONGLONG)blk * fs->blocksize),
|
|
block_nbytes,
|
|
(unsigned char *) block_bitmap));
|
|
|
|
if (!retval)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
#ifdef EXT2_BIG_ENDIAN_BITMAPS
|
|
if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
|
|
(fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
|
|
ext2_swap_bitmap(fs, block_bitmap, block_nbytes);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
memset(block_bitmap, 0, block_nbytes);
|
|
}
|
|
|
|
block_bitmap += block_nbytes;
|
|
}
|
|
|
|
if (inode_bitmap)
|
|
{
|
|
blk = fs->group_desc[i].bg_inode_bitmap;
|
|
if (blk)
|
|
{
|
|
retval = NT_SUCCESS(Ext2ReadDisk(
|
|
fs, ((LONGLONG)blk * fs->blocksize),
|
|
inode_nbytes,
|
|
(unsigned char *)inode_bitmap));
|
|
|
|
if (!retval)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
#ifdef EXT2_BIG_ENDIAN_BITMAPS
|
|
if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
|
|
(fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
|
|
ext2_swap_bitmap(fs, inode_bitmap, inode_nbytes);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
memset(inode_bitmap, 0, inode_nbytes);
|
|
}
|
|
|
|
inode_bitmap += inode_nbytes;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
|
|
cleanup:
|
|
|
|
if (do_block)
|
|
{
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, fs->block_map);
|
|
fs->block_map = NULL;
|
|
}
|
|
|
|
if (do_inode)
|
|
{
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, fs->inode_map);
|
|
fs->inode_map = 0;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ext2_read_inode_bitmap (PEXT2_FILESYS fs)
|
|
{
|
|
return read_bitmaps(fs, 1, 0);
|
|
}
|
|
|
|
bool ext2_read_block_bitmap(PEXT2_FILESYS fs)
|
|
{
|
|
return read_bitmaps(fs, 0, 1);
|
|
}
|
|
|
|
bool ext2_read_bitmaps(PEXT2_FILESYS fs)
|
|
{
|
|
|
|
if (fs->inode_map && fs->block_map)
|
|
return 0;
|
|
|
|
return read_bitmaps(fs, !fs->inode_map, !fs->block_map);
|
|
}
|
|
|