Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417/* * PROJECT: Mke2fs * FILE: Memory.c * PROGRAMMER: Matt Wu <mattwu@163.com> * HOMEPAGE: http://ext2.yeah.net */
/* INCLUDES **************************************************************/
#include "Mke2fs.h"#include <debug.h>
/* DEFINITIONS ***********************************************************/
extern char *device_name;
/* FUNCTIONS *************************************************************/
/* * Return the group # of an inode number */int ext2_group_of_ino(PEXT2_FILESYS fs, ULONG ino){ return (ino - 1) / fs->ext2_sb->s_inodes_per_group;}
/* * Return the group # of a block */int ext2_group_of_blk(PEXT2_FILESYS fs, ULONG blk){ return (blk - fs->ext2_sb->s_first_data_block) / fs->ext2_sb->s_blocks_per_group;}
void ext2_inode_alloc_stats2(PEXT2_FILESYS fs, ULONG ino, int inuse, int isdir){ int group = ext2_group_of_ino(fs, ino);
if (inuse > 0) ext2_mark_inode_bitmap(fs->inode_map, ino); else ext2_unmark_inode_bitmap(fs->inode_map, ino);
fs->group_desc[group].bg_free_inodes_count -= inuse;
if (isdir) fs->group_desc[group].bg_used_dirs_count += inuse;
fs->ext2_sb->s_free_inodes_count -= inuse;}
void ext2_inode_alloc_stats(PEXT2_FILESYS fs, ULONG ino, int inuse){ ext2_inode_alloc_stats2(fs, ino, inuse, 0);}
void ext2_block_alloc_stats(PEXT2_FILESYS fs, ULONG blk, int inuse){ int group = ext2_group_of_blk(fs, blk);
if (inuse > 0) ext2_mark_block_bitmap(fs->block_map, blk); else ext2_unmark_block_bitmap(fs->block_map, blk);
fs->group_desc[group].bg_free_blocks_count -= inuse; fs->ext2_sb->s_free_blocks_count -= inuse;}
bool ext2_allocate_tables(PEXT2_FILESYS Ext2Sys){ bool retval; ULONG i;
for (i = 0; i < Ext2Sys->group_desc_count; i++) { retval = ext2_allocate_group_table(Ext2Sys, i, Ext2Sys->block_map);
if (!retval) return retval; }
return true;}
bool ext2_allocate_group_table(PEXT2_FILESYS fs, ULONG group, PEXT2_BLOCK_BITMAP bmap){ bool retval; ULONG group_blk, start_blk, last_blk, new_blk, blk, j;
group_blk = fs->ext2_sb->s_first_data_block + (group * fs->ext2_sb->s_blocks_per_group);
last_blk = group_blk + fs->ext2_sb->s_blocks_per_group; if (last_blk >= fs->ext2_sb->s_blocks_count) last_blk = fs->ext2_sb->s_blocks_count - 1;
start_blk = group_blk + 3 + fs->desc_blocks; if (start_blk > last_blk) start_blk = group_blk;
if (!bmap) bmap = fs->block_map;
/* * Allocate the inode table */ if (!fs->group_desc[group].bg_inode_table) { retval = ext2_get_free_blocks(fs, start_blk, last_blk, fs->inode_blocks_per_group, bmap, &new_blk); if (!retval) return retval;
for (j=0, blk = new_blk; j < fs->inode_blocks_per_group; j++, blk++) ext2_mark_block_bitmap(bmap, blk);
fs->group_desc[group].bg_inode_table = new_blk; }
/* * Allocate the block and inode bitmaps, if necessary */ if (fs->stride) { start_blk += fs->inode_blocks_per_group; start_blk += ((fs->stride * group) % (last_blk - start_blk)); if (start_blk > last_blk) /* should never happen */ start_blk = group_blk; } else { start_blk = group_blk; }
if (!fs->group_desc[group].bg_block_bitmap) { retval = ext2_get_free_blocks(fs, start_blk, last_blk, 1, bmap, &new_blk);
if (!retval) retval = ext2_get_free_blocks(fs, group_blk, last_blk, 1, bmap, &new_blk);
if (!retval) return retval;
ext2_mark_block_bitmap(bmap, new_blk); fs->group_desc[group].bg_block_bitmap = new_blk; }
if (!fs->group_desc[group].bg_inode_bitmap) { retval = ext2_get_free_blocks(fs, start_blk, last_blk, 1, bmap, &new_blk); if (!retval) retval = ext2_get_free_blocks(fs, group_blk, last_blk, 1, bmap, &new_blk); if (!retval) return retval;
ext2_mark_block_bitmap(bmap, new_blk); fs->group_desc[group].bg_inode_bitmap = new_blk; }
return true;}
bool ext2_get_free_blocks(PEXT2_FILESYS fs, ULONG start, ULONG finish, int num, PEXT2_BLOCK_BITMAP map, ULONG *ret){ ULONG b = start;
if (!map) map = fs->block_map;
if (!map) return false;
if (!b) b = fs->ext2_sb->s_first_data_block;
if (!finish) finish = start;
if (!num) num = 1;
do { if (b+num-1 > fs->ext2_sb->s_blocks_count) b = fs->ext2_sb->s_first_data_block;
if (ext2_test_block_bitmap_range(map, b, num)) { *ret = b; return true; }
b++;
} while (b != finish);
return false;}
bool write_inode_tables(PEXT2_FILESYS fs){ bool retval; ULONG blk, num; int i;
for (i = 0; (ULONG)i < fs->group_desc_count; i++) { blk = fs->group_desc[i].bg_inode_table; num = fs->inode_blocks_per_group;
retval = zero_blocks(fs, blk, num, &blk, &num); if (!retval) { DPRINT1("\nMke2fs: Could not write %lu blocks " "in inode table starting at %lu.\n", num, blk);
zero_blocks(0, 0, 0, 0, 0); return false; } }
zero_blocks(0, 0, 0, 0, 0);
return true;}
/* * Stupid algorithm --- we now just search forward starting from the * goal. Should put in a smarter one someday.... */bool ext2_new_block(PEXT2_FILESYS fs, ULONG goal, PEXT2_BLOCK_BITMAP map, ULONG *ret){ ULONG i;
if (!map) map = fs->block_map;
if (!map) return false;
if (!goal || (goal >= fs->ext2_sb->s_blocks_count)) goal = fs->ext2_sb->s_first_data_block;
i = goal;
do { if (!ext2_test_block_bitmap(map, i)) { *ret = i; return true; }
i++;
if (i >= fs->ext2_sb->s_blocks_count) i = fs->ext2_sb->s_first_data_block;
} while (i != goal);
return false;}
/* * This function zeros out the allocated block, and updates all of the * appropriate filesystem records. */bool ext2_alloc_block(PEXT2_FILESYS fs, ULONG goal, ULONG *ret){ bool retval; ULONG block; char *buf = NULL;
buf = (char *)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, fs->blocksize); if (!buf) return false;
if (!fs->block_map) { retval = ext2_read_block_bitmap(fs); if (!retval) goto fail; }
retval = ext2_new_block(fs, goal, 0, &block);
if (!retval) goto fail;
retval = NT_SUCCESS(Ext2WriteDisk( fs, ((LONGLONG)block * fs->blocksize), fs->blocksize, (unsigned char *)buf));
if (!retval) { goto fail; }
ext2_block_alloc_stats(fs, block, +1); *ret = block;
if (buf) { RtlFreeHeap(RtlGetProcessHeap(), 0, buf); }
return true;
fail:
if (buf) { RtlFreeHeap(RtlGetProcessHeap(), 0, buf); }
return false;}
/* * Create new directory block */bool ext2_new_dir_block(PEXT2_FILESYS fs, ULONG dir_ino, ULONG parent_ino, char **block){ PEXT2_DIR_ENTRY dir = NULL; char *buf; int rec_len; int filetype = 0;
buf = (char *)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, fs->blocksize); if (!buf) return false;
dir = (PEXT2_DIR_ENTRY) buf; dir->rec_len = fs->blocksize;
if (dir_ino) { if (fs->ext2_sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE) filetype = EXT2_FT_DIR << 8; /* * Set up entry for '.' */ dir->inode = dir_ino; dir->name_len = 1 | filetype; dir->name[0] = '.'; rec_len = dir->rec_len - EXT2_DIR_REC_LEN(1); dir->rec_len = EXT2_DIR_REC_LEN(1);
/* * Set up entry for '..' */ dir = (struct ext2_dir_entry *) (buf + dir->rec_len); dir->rec_len = rec_len; dir->inode = parent_ino; dir->name_len = 2 | filetype; dir->name[0] = '.'; dir->name[1] = '.'; }
*block = buf;
return true;}
bool ext2_write_block(PEXT2_FILESYS fs, ULONG block, void *inbuf){ bool retval = false;
retval = NT_SUCCESS(Ext2WriteDisk( fs, ((ULONGLONG)block * fs->blocksize), fs->blocksize, (unsigned char *)inbuf));
return retval;}
bool ext2_read_block(PEXT2_FILESYS fs, ULONG block, void *inbuf){ bool retval = false;
retval = NT_SUCCESS(Ext2ReadDisk( fs, ((ULONGLONG)block * fs->blocksize), fs->blocksize, (unsigned char *)inbuf));
return retval;}