Ext2lib import by filip navara for use by usetup.

svn path=/branches/ext2/; revision=13010
This commit is contained in:
Art Yerkes 2005-01-13 01:54:28 +00:00
parent d31a52e423
commit 395064be78
16 changed files with 6008 additions and 0 deletions

View file

@ -0,0 +1,3 @@
*.d
*.o
*.sym

View file

@ -0,0 +1,43 @@
/*
* PROJECT: Mke2fs
* FILE: Badblock.c
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://ext2.yeah.net
*/
/* INCLUDES **************************************************************/
#include "Mke2fs.h"
/* DEFINITIONS ***********************************************************/
/* FUNCTIONS *************************************************************/
bool create_bad_block_inode( PEXT2_FILESYS Ext2Sys,
PEXT2_BADBLK_LIST bb_list)
{
bool retval;
EXT2_INODE inode;
LARGE_INTEGER SysTime;
NtQuerySystemTime(&SysTime);
ext2_mark_inode_bitmap(Ext2Sys->inode_map, EXT2_BAD_INO);
Ext2Sys->group_desc[0].bg_free_inodes_count--;
Ext2Sys->ext2_sb->s_free_inodes_count--;
memset(&inode, 0, sizeof(EXT2_INODE));
inode.i_mode = (USHORT)((0777 & ~Ext2Sys->umask));
inode.i_uid = inode.i_gid = 0;
inode.i_blocks = 0;
inode.i_block[0] = 0;
inode.i_links_count = 2;
RtlTimeToSecondsSince1970(&SysTime, &inode.i_mtime);
inode.i_ctime = inode.i_atime = inode.i_mtime;
inode.i_size = 0;
retval = ext2_save_inode(Ext2Sys, EXT2_BAD_INO, &inode);
return retval;
}

View file

@ -0,0 +1,499 @@
/*
* PROJECT: Mke2fs
* FILE: Bitmap.c
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://ext2.yeah.net
*/
/* INCLUDES **************************************************************/
#include "Mke2fs.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(GetProcessHeap(), 0, sizeof(EXT2_BLOCK_BITMAP));
if (!Ext2Sys->block_map)
{
KdPrint(("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(GetProcessHeap(), 0, size);
if (!Ext2Sys->block_map->bitmap)
{
RtlFreeHeap(GetProcessHeap(), 0, Ext2Sys->block_map);
Ext2Sys->block_map = NULL;
KdPrint(("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(GetProcessHeap(), 0, sizeof(EXT2_INODE_BITMAP));
if (!Ext2Sys->inode_map)
{
KdPrint(("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(GetProcessHeap(), 0, size);
if (!Ext2Sys->inode_map->bitmap)
{
RtlFreeHeap(GetProcessHeap(), 0, Ext2Sys->inode_map);
Ext2Sys->inode_map = NULL;
KdPrint(("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(GetProcessHeap(), 0, bitmap->bitmap);
bitmap->bitmap = 0;
}
RtlFreeHeap(GetProcessHeap(), 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(GetProcessHeap(), 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(GetProcessHeap(), 0, bitmap_block);
return false;
}
}
inode_bitmap += nbytes;
}
RtlFreeHeap(GetProcessHeap(), 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(GetProcessHeap(), 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(GetProcessHeap(), 0, bitmap_block);
return false;
}
}
block_bitmap += nbytes;
}
RtlFreeHeap(GetProcessHeap(), 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(GetProcessHeap(), 0, fs->block_map);
fs->block_map = NULL;
}
if (do_inode)
{
RtlFreeHeap(GetProcessHeap(), 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);
}

View file

@ -0,0 +1,12 @@
#ifndef _BITMAP_H
#include "time.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "windows.h"
#endif // _BITMAP_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,19 @@
/*
* PROJECT: Mke2fs
* FILE: Disk.h
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://ext2.yeah.net
*/
#ifndef _DISK_H_
#define _DISK_H_
/* INCLUDES **************************************************************/
#include "Stdafx.h"
/* DEFINITIONS ***********************************************************/
#endif /* _DISK_H_ */

View file

@ -0,0 +1,68 @@
/*
* PROJECT: Mke2fs
* FILE: Group.c
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://ext2.yeah.net
*/
/* INCLUDES **************************************************************/
#include "Mke2fs.h"
/* DEFINITIONS ***********************************************************/
/* FUNCTIONS *************************************************************/
int test_root(int a, int b)
{
if (a == 0)
return 1;
while (1)
{
if (a == 1)
return 1;
if (a % b)
return 0;
a = a / b;
}
}
bool ext2_bg_has_super(PEXT2_SUPER_BLOCK pExt2Sb, int group_block)
{
if (!(pExt2Sb->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
return true;
if (test_root(group_block, 3) || (test_root(group_block, 5)) ||
test_root(group_block, 7))
return true;
return false;
}
bool ext2_allocate_group_desc(PEXT2_FILESYS Ext2Sys)
{
ULONG size;
size = Ext2Sys->desc_blocks * Ext2Sys->blocksize;
Ext2Sys->group_desc =
(PEXT2_GROUP_DESC)RtlAllocateHeap(GetProcessHeap(), 0, size);
if (Ext2Sys->group_desc)
{
memset(Ext2Sys->group_desc, 0, size);
return true;
}
return false;
}
void ext2_free_group_desc(PEXT2_FILESYS Ext2Sys)
{
if (Ext2Sys->group_desc)
{
RtlFreeHeap(GetProcessHeap(), 0, Ext2Sys->group_desc);
Ext2Sys->group_desc = NULL;
}
}

View file

@ -0,0 +1,697 @@
/*
* PROJECT: Mke2fs
* FILE: Inode.c
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://ext2.yeah.net
*/
/* INCLUDES **************************************************************/
#include "Mke2fs.h"
/* DEFINITIONS ***********************************************************/
extern char *device_name;
/* FUNCTIONS *************************************************************/
bool ext2_get_inode_lba(PEXT2_FILESYS Ext2Sys, ULONG no, LONGLONG *offset)
{
LONGLONG loc = 0;
PEXT2_SUPER_BLOCK pExt2Sb = Ext2Sys->ext2_sb;
if (no < 1 || no > pExt2Sb->s_inodes_count)
{
KdPrint(("Mke2fs: Inode value %lu was out of range in load_inode.(1-%ld)\n",
no, pExt2Sb->s_inodes_count));
*offset = 0;
return false;
}
loc = (LONGLONG)(Ext2Sys->blocksize) * Ext2Sys->group_desc[(no - 1) / pExt2Sb->s_inodes_per_group].bg_inode_table +
((no - 1) % pExt2Sb->s_inodes_per_group) * sizeof(EXT2_INODE);
*offset = loc;
return true;
}
bool ext2_load_inode(PEXT2_FILESYS Ext2Sys, ULONG no, PEXT2_INODE pInode)
{
LONGLONG Offset;
bool bRet = false;
if (ext2_get_inode_lba(Ext2Sys, no, &Offset))
{
bRet = NT_SUCCESS(Ext2ReadDisk(
Ext2Sys,
Offset,
sizeof(EXT2_INODE),
(unsigned char *)pInode));
}
return bRet;
}
bool ext2_save_inode(PEXT2_FILESYS Ext2Sys, ULONG no, PEXT2_INODE pInode)
{
LONGLONG offset;
bool bRet = false;
if (ext2_get_inode_lba(Ext2Sys, no, &offset))
{
bRet = NT_SUCCESS(Ext2WriteDisk(
Ext2Sys,
offset,
sizeof(EXT2_INODE),
(unsigned char *)pInode));
}
return bRet;
}
/*
* Right now, just search forward from the parent directory's block
* group to find the next free inode.
*
* Should have a special policy for directories.
*/
bool ext2_new_inode(PEXT2_FILESYS fs, ULONG dir, int mode,
PEXT2_INODE_BITMAP map, ULONG *ret)
{
ULONG dir_group = 0;
ULONG i;
ULONG start_inode;
if (!map)
map = fs->inode_map;
if (!map)
return false;
if (dir > 0)
dir_group = (dir - 1) / EXT2_INODES_PER_GROUP(fs->ext2_sb);
start_inode = (dir_group * EXT2_INODES_PER_GROUP(fs->ext2_sb)) + 1;
if (start_inode < EXT2_FIRST_INODE(fs->ext2_sb))
start_inode = EXT2_FIRST_INODE(fs->ext2_sb);
i = start_inode;
do
{
if (!ext2_test_inode_bitmap(map, i))
break;
i++;
if (i > fs->ext2_sb->s_inodes_count)
i = EXT2_FIRST_INODE(fs->ext2_sb);
} while (i != start_inode);
if (ext2_test_inode_bitmap(map, i))
return false;
*ret = i;
return true;
}
bool ext2_expand_block( PEXT2_FILESYS Ext2Sys, PEXT2_INODE Inode,
ULONG dwContent, ULONG Index, int layer,
ULONG newBlk, ULONG *dwRet, ULONG *off )
{
ULONG *pData = NULL;
ULONG i = 0, j = 0, temp = 1;
ULONG dwBlk;
ULONG dwNewBlk = newBlk;
bool bDirty = false;
bool bRet = true;
ULONG Offset = 0;
PEXT2_SUPER_BLOCK pExt2Sb = Ext2Sys->ext2_sb;
pData = (ULONG *)RtlAllocateHeap(GetProcessHeap(), 0, Ext2Sys->blocksize);
if (!pData)
{
bRet = false;
goto errorout;
}
if (!ext2_read_block(Ext2Sys, dwContent, (void *)pData))
{
bRet = false;
goto errorout;
}
if (layer == 1)
{
*dwRet = dwContent;
*off = Index;
pData[Index] = newBlk;
bDirty = TRUE;
}
else if (layer <= 3)
{
temp = 1 << ((10 + pExt2Sb->s_log_block_size - 2) * (layer - 1));
i = Index / temp;
j = Index % temp;
dwBlk = pData[i];
if (dwBlk == 0)
{
if (ext2_alloc_block(Ext2Sys, 0, &dwBlk) )
{
pData[i] = dwBlk;
bDirty = true;
Inode->i_blocks += (Ext2Sys->blocksize / SECTOR_SIZE);
}
if (!bDirty)
goto errorout;
}
if (!ext2_expand_block(Ext2Sys, Inode, dwBlk, j, layer - 1, bDirty, &dwNewBlk, &Offset))
{
bRet = false;
KdPrint(("Mke2fs: ext2_expand_block: ... error recuise...\n"));
goto errorout;
}
}
if (bDirty)
{
bRet = ext2_write_block(Ext2Sys, dwContent, (void *)pData);
}
errorout:
if (pData)
RtlFreeHeap(GetProcessHeap(), 0, pData);
if (bRet && dwRet)
*dwRet = dwNewBlk;
return bRet;
}
bool ext2_expand_inode( PEXT2_FILESYS Ext2Sys,
PEXT2_INODE Inode,
ULONG newBlk )
{
ULONG dwSizes[4] = {12, 1, 1, 1};
ULONG Index = 0;
ULONG dwTotal = 0;
ULONG dwBlk = 0, dwNewBlk = 0, Offset = 0;
PEXT2_SUPER_BLOCK pExt2Sb = Ext2Sys->ext2_sb;
int i = 0;
bool bRet = true;
bool bDirty = false;
ULONG TotalBlocks;
TotalBlocks = Inode->i_blocks / (Ext2Sys->blocksize / SECTOR_SIZE);
Index = Ext2DataBlocks(Ext2Sys, TotalBlocks);
for (i = 0; i < 4; i++)
{
dwSizes[i] = dwSizes[i] << ((10 + pExt2Sb->s_log_block_size - 2) * i);
dwTotal += dwSizes[i];
}
if (Index >= dwTotal)
{
KdPrint(("Mke2fs: ext2_expand_inode: beyond the maxinum size of an inode.\n"));
return false;
}
for (i = 0; i < 4; i++)
{
if (Index < dwSizes[i])
{
if (i == 0)
{
Inode->i_block[Index] = newBlk;
bDirty = true;
}
else
{
dwBlk = Inode->i_block[(i + 12 - 1)];
if (dwBlk == 0)
{
if (ext2_alloc_block(Ext2Sys, 0, &dwBlk))
{
Inode->i_block[(i + 12 - 1)] = dwBlk;
bDirty = true;
Inode->i_blocks += (Ext2Sys->blocksize / SECTOR_SIZE);
}
else
{
break;
}
}
dwNewBlk = 0;
bRet = ext2_expand_block(
Ext2Sys,
Inode,
dwBlk,
Index,
i,
newBlk,
&dwNewBlk,
&Offset );
}
break;
}
Index -= dwSizes[i];
}
return bRet;
}
bool ext2_get_block(PEXT2_FILESYS Ext2Sys, ULONG dwContent, ULONG Index, int layer, ULONG *dwRet)
{
ULONG *pData = NULL;
LONGLONG Offset = 0;
ULONG i = 0, j = 0, temp = 1;
ULONG dwBlk = 0;
bool bRet = true;
PEXT2_SUPER_BLOCK pExt2Sb = Ext2Sys->ext2_sb;
Offset = (LONGLONG) dwContent;
Offset = Offset * Ext2Sys->blocksize;
pData = (ULONG *)RtlAllocateHeap(GetProcessHeap(), 0, Ext2Sys->blocksize);
if (!pData)
{
return false;
}
memset(pData, 0, Ext2Sys->blocksize);
if (layer == 0)
{
dwBlk = dwContent;
}
else if (layer <= 3)
{
if (!ext2_read_block(Ext2Sys, dwContent, (void *)pData))
{
bRet = false;
goto errorout;
}
temp = 1 << ((10 + pExt2Sb->s_log_block_size - 2) * (layer - 1));
i = Index / temp;
j = Index % temp;
if (!ext2_get_block(Ext2Sys, pData[i], j, layer - 1, &dwBlk))
{
bRet = false;
KdPrint(("Mke2fs: ext2_get_block: ... error recuise...\n"));
goto errorout;
}
}
errorout:
if (pData)
RtlFreeHeap(GetProcessHeap(), 0, pData);
if (bRet && dwRet)
*dwRet = dwBlk;
return bRet;
}
bool ext2_block_map(PEXT2_FILESYS Ext2Sys, PEXT2_INODE inode, ULONG block, ULONG *dwRet)
{
ULONG dwSizes[4] = {12, 1, 1, 1};
ULONG Index = 0;
ULONG dwBlk = 0;
PEXT2_SUPER_BLOCK pExt2Sb = Ext2Sys->ext2_sb;
int i;
bool bRet = false;
Index = block;
for (i = 0; i < 4; i++)
{
dwSizes[i] = dwSizes[i] << ((10 + pExt2Sb->s_log_block_size - 2) * i);
}
if (Index >= inode->i_blocks / (Ext2Sys->blocksize / SECTOR_SIZE))
{
KdPrint(("Mke2fs: ext2_block_map: beyond the size of the inode.\n"));
return false;
}
for (i = 0; i < 4; i++)
{
if (Index < dwSizes[i])
{
dwBlk = inode->i_block[i==0 ? (Index):(i + 12 - 1)];
bRet = ext2_get_block(Ext2Sys, dwBlk, Index , i, &dwBlk);
break;
}
Index -= dwSizes[i];
}
if (bRet && dwBlk)
{
if (dwRet)
*dwRet = dwBlk;
return true;
}
else
return false;
}
ULONG ext2_build_bdl(PEXT2_FILESYS Ext2Sys,
PEXT2_INODE ext2_inode,
IN ULONG offset,
IN ULONG size,
OUT PEXT2_BDL *ext2_bdl )
{
ULONG nBeg, nEnd, nBlocks;
ULONG dwBlk;
ULONG i;
ULONG dwBytes = 0;
LONGLONG lba;
PEXT2_BDL ext2bdl = NULL;
*ext2_bdl = NULL;
if (offset >= ext2_inode->i_size)
{
KdPrint(("Mke2fs: ext2_build_bdl: beyond the file range.\n"));
return 0;
}
/*
if (offset + size > ext2_inode->i_size)
{
size = ext2_inode->i_size - offset;
}
*/
nBeg = offset / Ext2Sys->blocksize;
nEnd = (size + offset + Ext2Sys->blocksize - 1) / Ext2Sys->blocksize;
nBlocks = nEnd - nBeg;
if (nBlocks > 0)
{
ext2bdl = (PEXT2_BDL)
RtlAllocateHeap(GetProcessHeap(), 0, sizeof(EXT2_BDL) * nBlocks);
if (ext2bdl)
{
memset(ext2bdl, 0, sizeof(EXT2_BDL) * nBlocks);
for (i = nBeg; i < nEnd; i++)
{
if (!ext2_block_map(Ext2Sys, ext2_inode, i, &dwBlk))
{
goto fail;
}
lba = (LONGLONG) dwBlk;
lba = lba * Ext2Sys->blocksize;
if (nBlocks == 1) // ie. (nBeg == nEnd - 1)
{
dwBytes = size;
ext2bdl[i - nBeg].Lba = lba + (LONGLONG)(offset % (Ext2Sys->blocksize));
ext2bdl[i - nBeg].Length = dwBytes;
ext2bdl[i - nBeg].Offset = 0;
}
else
{
if (i == nBeg)
{
dwBytes = Ext2Sys->blocksize - (offset % (Ext2Sys->blocksize));
ext2bdl[i - nBeg].Lba = lba + (LONGLONG)(offset % (Ext2Sys->blocksize));
ext2bdl[i - nBeg].Length = dwBytes;
ext2bdl[i - nBeg].Offset = 0;
}
else if (i == nEnd - 1)
{
ext2bdl[i - nBeg].Lba = lba;
ext2bdl[i - nBeg].Length = size - dwBytes;
ext2bdl[i - nBeg].Offset = dwBytes;
dwBytes = size;
}
else
{
ext2bdl[i - nBeg].Lba = lba;
ext2bdl[i - nBeg].Length = Ext2Sys->blocksize;
ext2bdl[i - nBeg].Offset = dwBytes;
dwBytes += Ext2Sys->blocksize;
}
}
}
*ext2_bdl = ext2bdl;
return nBlocks;
}
}
fail:
if (ext2bdl)
RtlFreeHeap(GetProcessHeap(), 0, ext2bdl);
// Error
return 0;
}
bool ext2_read_inode(PEXT2_FILESYS Ext2Sys,
ULONG ino,
ULONG offset,
PVOID Buffer,
ULONG size,
PULONG dwReturn)
{
PEXT2_BDL ext2_bdl = NULL;
ULONG blocks, i;
bool bRet = true;
EXT2_INODE ext2_inode;
ULONG dwTotal = 0;
if (!ext2_load_inode(Ext2Sys, ino, &ext2_inode))
{
return false;
}
blocks = ext2_build_bdl(Ext2Sys, &ext2_inode, offset, size, &ext2_bdl);
if (blocks <= 0)
return false;
for(i = 0; i < blocks; i++)
{
bRet = NT_SUCCESS(Ext2ReadDisk(
Ext2Sys,
ext2_bdl[i].Lba,
ext2_bdl[i].Length,
(PUCHAR)Buffer + ext2_bdl[i].Offset
));
if (!bRet)
break;
dwTotal += ext2_bdl[i].Length;
}
*dwReturn = dwTotal;
if (ext2_bdl)
RtlFreeHeap(GetProcessHeap(), 0, ext2_bdl);
return bRet;
}
bool ext2_write_inode (PEXT2_FILESYS Ext2Sys,
ULONG ino,
ULONG offset,
PVOID Buffer,
ULONG size,
PULONG dwReturn )
{
PEXT2_BDL ext2_bdl = NULL;
ULONG blocks, i;
bool bRet = true;
EXT2_INODE inode;
ULONG dwTotal = 0;
ULONG dwBlk = 0;
ULONG TotalBlks;
blocks = (size + offset + Ext2Sys->blocksize - 1) / Ext2Sys->blocksize;
if (!ext2_load_inode(Ext2Sys, ino, &inode))
{
return false;
}
TotalBlks = inode.i_blocks / (Ext2Sys->blocksize / SECTOR_SIZE);
TotalBlks = Ext2DataBlocks(Ext2Sys, TotalBlks);
if (blocks > TotalBlks)
{
for (i=0; i < (blocks - TotalBlks); i++)
{
if (ext2_alloc_block(Ext2Sys, 0, &dwBlk) )
{
ext2_expand_inode(Ext2Sys, &inode, dwBlk);
inode.i_blocks += (Ext2Sys->blocksize/SECTOR_SIZE);
}
}
}
blocks = ext2_build_bdl(Ext2Sys, &inode, offset, size, &ext2_bdl);
if (blocks <= 0)
return false;
for(i = 0; i < blocks; i++)
{
bRet = NT_SUCCESS(Ext2WriteDisk(
Ext2Sys,
ext2_bdl[i].Lba,
ext2_bdl[i].Length,
(PUCHAR)Buffer + ext2_bdl[i].Offset
));
if (!bRet)
{
goto errorout;
}
dwTotal += ext2_bdl[i].Length;
}
*dwReturn = dwTotal;
if (size + offset > inode.i_size)
{
inode.i_size = size + offset;
}
ext2_save_inode(Ext2Sys, ino, &inode);
errorout:
if (ext2_bdl)
RtlFreeHeap(GetProcessHeap(), 0, ext2_bdl);
return bRet;
}
bool
ext2_add_entry( PEXT2_FILESYS Ext2Sys,
ULONG parent, ULONG inode,
int filetype, char *name )
{
PEXT2_DIR_ENTRY2 dir = NULL, newdir = NULL;
EXT2_INODE parent_inode;
ULONG dwRet;
char *buf;
int rec_len;
bool bRet = false;
rec_len = EXT2_DIR_REC_LEN(strlen(name));
if (!ext2_load_inode(Ext2Sys, parent, &parent_inode))
{
return false;
}
buf = (char *)RtlAllocateHeap(GetProcessHeap(), 0, parent_inode.i_size);
if (!ext2_read_inode(Ext2Sys, parent, 0, buf, parent_inode.i_size, &dwRet))
{
return false;
}
dir = (PEXT2_DIR_ENTRY2) buf;
while ((char *)dir < buf + parent_inode.i_size)
{
if ((dir->inode == 0 && dir->rec_len >= rec_len) ||
(dir->rec_len >= dir->name_len + rec_len) )
{
if (dir->inode)
{
newdir = (PEXT2_DIR_ENTRY2) ((PUCHAR)dir + EXT2_DIR_REC_LEN(dir->name_len));
newdir->rec_len = dir->rec_len - EXT2_DIR_REC_LEN(dir->name_len);
dir->rec_len = EXT2_DIR_REC_LEN(dir->name_len);
dir = newdir;
}
dir->file_type = filetype;
dir->inode = inode;
dir->name_len = strlen(name);
memcpy(dir->name, name, strlen(name));
bRet = true;
break;
}
dir = (PEXT2_DIR_ENTRY2) (dir->rec_len + (PUCHAR) dir);
}
if (bRet)
return ext2_write_inode(Ext2Sys, parent, 0, buf, parent_inode.i_size, &dwRet);
return bRet;
}
bool ext2_reserve_inodes(PEXT2_FILESYS fs)
{
ULONG i;
int group;
for (i = EXT2_ROOT_INO + 1; i < EXT2_FIRST_INODE(fs->ext2_sb); i++)
{
ext2_mark_inode_bitmap(fs->inode_map, i);
group = ext2_group_of_ino(fs, i);
fs->group_desc[group].bg_free_inodes_count--;
fs->ext2_sb->s_free_inodes_count--;
}
return true;
}

View file

@ -0,0 +1,19 @@
# $Id: $
PATH_TO_TOP = ../../..
TARGET_TYPE = library
TARGET_NAME = ext2lib
TARGET_CFLAGS = -I$(W32API_PATH)/include/ddk -D__USE_W32API -Wall -Werror -DDBG
TARGET_OBJECTS = \
Badblock.o \
Bitmap.o \
Disk.o \
Group.o \
Inode.o \
Memory.o \
Mke2fs.o \
Super.o \
Uuid.o
include $(PATH_TO_TOP)/rules.mak
include $(TOOLS_PATH)/helper.mk

View file

@ -0,0 +1,416 @@
/*
* PROJECT: Mke2fs
* FILE: Memory.c
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://ext2.yeah.net
*/
/* INCLUDES **************************************************************/
#include "Mke2fs.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;
int 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)
{
KdPrint(("\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(GetProcessHeap(), 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(GetProcessHeap(), 0, buf);
}
return true;
fail:
if (buf)
{
RtlFreeHeap(GetProcessHeap(), 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(GetProcessHeap(), 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;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,876 @@
/*
* PROJECT: Mke2fs
* FILE: Mke2fs.h
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://ext2.yeah.net
*/
#ifndef __MKE2FS__INCLUDE__
#define __MKE2FS__INCLUDE__
/* INCLUDES **************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <ntddk.h>
#include <ntdddisk.h>
#include <napi/teb.h>
#include "time.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "ctype.h"
#include "types.h"
#include "ext2_fs.h"
#include "getopt.h"
#define NTSYSAPI
/* DEFINITIONS ***********************************************************/
#define SECTOR_SIZE (Ext2Sys->DiskGeometry.BytesPerSector)
#ifndef GUID_DEFINED
#define GUID_DEFINED
typedef struct _GUID
{
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
unsigned char Data4[8];
} GUID;
#endif /* GUID_DEFINED */
#ifndef UUID_DEFINED
#define UUID_DEFINED
typedef GUID UUID;
#ifndef uuid_t
#define uuid_t UUID
#endif
#endif
#ifndef bool
#define bool BOOLEAN
#endif
#ifndef true
#define true TRUE
#endif
#ifndef false
#define false FALSE
#endif
#define EXT2_CHECK_MAGIC(struct, code) \
if ((struct)->magic != (code)) return (code)
/*
* ext2fs_scan flags
*/
#define EXT2_SF_CHK_BADBLOCKS 0x0001
#define EXT2_SF_BAD_INODE_BLK 0x0002
#define EXT2_SF_BAD_EXTRA_BYTES 0x0004
#define EXT2_SF_SKIP_MISSING_ITABLE 0x0008
/*
* ext2fs_check_if_mounted flags
*/
#define EXT2_MF_MOUNTED 1
#define EXT2_MF_ISROOT 2
#define EXT2_MF_READONLY 4
#define EXT2_MF_SWAP 8
/*
* Ext2/linux mode flags. We define them here so that we don't need
* to depend on the OS's sys/stat.h, since we may be compiling on a
* non-Linux system.
*/
#define LINUX_S_IFMT 00170000
#define LINUX_S_IFSOCK 0140000
#define LINUX_S_IFLNK 0120000
#define LINUX_S_IFREG 0100000
#define LINUX_S_IFBLK 0060000
#define LINUX_S_IFDIR 0040000
#define LINUX_S_IFCHR 0020000
#define LINUX_S_IFIFO 0010000
#define LINUX_S_ISUID 0004000
#define LINUX_S_ISGID 0002000
#define LINUX_S_ISVTX 0001000
#define LINUX_S_IRWXU 00700
#define LINUX_S_IRUSR 00400
#define LINUX_S_IWUSR 00200
#define LINUX_S_IXUSR 00100
#define LINUX_S_IRWXG 00070
#define LINUX_S_IRGRP 00040
#define LINUX_S_IWGRP 00020
#define LINUX_S_IXGRP 00010
#define LINUX_S_IRWXO 00007
#define LINUX_S_IROTH 00004
#define LINUX_S_IWOTH 00002
#define LINUX_S_IXOTH 00001
#define LINUX_S_ISLNK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFLNK)
#define LINUX_S_ISREG(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFREG)
#define LINUX_S_ISDIR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFDIR)
#define LINUX_S_ISCHR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFCHR)
#define LINUX_S_ISBLK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFBLK)
#define LINUX_S_ISFIFO(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFIFO)
#define LINUX_S_ISSOCK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFSOCK)
#define EXT2_FIRST_INODE(s) EXT2_FIRST_INO(s)
typedef struct _ext2fs_bitmap {
__u32 start, end;
__u32 real_end;
char* bitmap;
} EXT2_BITMAP, *PEXT2_BITMAP;
typedef EXT2_BITMAP EXT2_GENERIC_BITMAP, *PEXT2_GENERIC_BITMAP;
typedef EXT2_BITMAP EXT2_INODE_BITMAP, *PEXT2_INODE_BITMAP;
typedef EXT2_BITMAP EXT2_BLOCK_BITMAP, *PEXT2_BLOCK_BITMAP;
typedef struct ext2_acl_entry EXT2_ACL_ENTRY, *PEXT2_ACL_ENTRY;
typedef struct ext2_acl_header EXT2_ACL_HEADER, *PEXT2_ACL_HEADER;
typedef struct ext2_dir_entry EXT2_DIR_ENTRY, *PEXT2_DIR_ENTRY;
typedef struct ext2_dir_entry_2 EXT2_DIR_ENTRY2, *PEXT2_DIR_ENTRY2;
typedef struct ext2_dx_countlimit EXT2_DX_CL, *PEXT2_DX_CL;
typedef struct ext2_dx_entry EXT2_DX_ENTRY, *PEXT2_DX_ENTRY;
typedef struct ext2_dx_root_info EXT2_DX_RI, *PEXT2_DX_RI;
typedef struct ext2_inode EXT2_INODE, *PEXT2_INODE;
typedef struct ext2_group_desc EXT2_GROUP_DESC, *PEXT2_GROUP_DESC;
typedef struct ext2_super_block EXT2_SUPER_BLOCK, *PEXT2_SUPER_BLOCK;
/*
* Badblocks list
*/
struct ext2_struct_badblocks_list {
int num;
int size;
ULONG *list;
int badblocks_flags;
};
typedef struct ext2_struct_badblocks_list EXT2_BADBLK_LIST, *PEXT2_BADBLK_LIST;
typedef struct _ext2_filesys
{
int flags;
int blocksize;
int fragsize;
ULONG group_desc_count;
unsigned long desc_blocks;
PEXT2_GROUP_DESC group_desc;
PEXT2_SUPER_BLOCK ext2_sb;
unsigned long inode_blocks_per_group;
PEXT2_INODE_BITMAP inode_map;
PEXT2_BLOCK_BITMAP block_map;
EXT2_BADBLK_LIST badblocks;
/*
ext2_dblist dblist;
*/
__u32 stride; /* for mke2fs */
__u32 umask;
/*
* Reserved for future expansion
*/
__u32 reserved[8];
/*
* Reserved for the use of the calling application.
*/
void * priv_data;
HANDLE MediaHandle;
DISK_GEOMETRY DiskGeometry;
PARTITION_INFORMATION PartInfo;
} EXT2_FILESYS, *PEXT2_FILESYS;
// Block Description List
typedef struct _EXT2_BDL {
LONGLONG Lba;
ULONG Offset;
ULONG Length;
} EXT2_BDL, *PEXT2_BDL;
/*
* Where the master copy of the superblock is located, and how big
* superblocks are supposed to be. We define SUPERBLOCK_SIZE because
* the size of the superblock structure is not necessarily trustworthy
* (some versions have the padding set up so that the superblock is
* 1032 bytes long).
*/
#define SUPERBLOCK_OFFSET 1024
#define SUPERBLOCK_SIZE 1024
bool create_bad_block_inode(PEXT2_FILESYS fs, PEXT2_BADBLK_LIST bb_list);
//
// Definitions
//
#define FSCTL_REQUEST_OPLOCK_LEVEL_1 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSCTL_REQUEST_OPLOCK_LEVEL_2 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSCTL_REQUEST_BATCH_OPLOCK CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSCTL_OPLOCK_BREAK_ACKNOWLEDGE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 3, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSCTL_OPBATCH_ACK_CLOSE_PENDING CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 4, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSCTL_OPLOCK_BREAK_NOTIFY CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 5, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSCTL_LOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 6, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSCTL_UNLOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 7, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSCTL_DISMOUNT_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 8, METHOD_BUFFERED, FILE_ANY_ACCESS)
// decommissioned fsctl value 9
#define FSCTL_IS_VOLUME_MOUNTED CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 10, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSCTL_IS_PATHNAME_VALID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 11, METHOD_BUFFERED, FILE_ANY_ACCESS) // PATHNAME_BUFFER,
#define FSCTL_MARK_VOLUME_DIRTY CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 12, METHOD_BUFFERED, FILE_ANY_ACCESS)
// decommissioned fsctl value 13
#define FSCTL_QUERY_RETRIEVAL_POINTERS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 14, METHOD_NEITHER, FILE_ANY_ACCESS)
#define FSCTL_GET_COMPRESSION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 15, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSCTL_SET_COMPRESSION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 16, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
// decommissioned fsctl value 17
// decommissioned fsctl value 18
#define FSCTL_MARK_AS_SYSTEM_HIVE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 19, METHOD_NEITHER, FILE_ANY_ACCESS)
#define FSCTL_OPLOCK_BREAK_ACK_NO_2 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 20, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSCTL_INVALIDATE_VOLUMES CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 21, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSCTL_QUERY_FAT_BPB CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 22, METHOD_BUFFERED, FILE_ANY_ACCESS) // , FSCTL_QUERY_FAT_BPB_BUFFER
#define FSCTL_REQUEST_FILTER_OPLOCK CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 23, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSCTL_FILESYSTEM_GET_STATISTICS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 24, METHOD_BUFFERED, FILE_ANY_ACCESS) // , FILESYSTEM_STATISTICS
//
// Disk I/O Routines
//
NTSYSAPI
NTSTATUS
NTAPI
NtReadFile(HANDLE FileHandle,
HANDLE Event OPTIONAL,
PIO_APC_ROUTINE ApcRoutine OPTIONAL,
PVOID ApcContext OPTIONAL,
PIO_STATUS_BLOCK IoStatusBlock,
PVOID Buffer,
ULONG Length,
PLARGE_INTEGER ByteOffset OPTIONAL,
PULONG Key OPTIONAL);
NTSYSAPI
NTSTATUS
NTAPI
NtWriteFile(HANDLE FileHandle,
HANDLE Event OPTIONAL,
PIO_APC_ROUTINE ApcRoutine OPTIONAL,
PVOID ApcContext OPTIONAL,
PIO_STATUS_BLOCK IoStatusBlock,
PVOID Buffer,
ULONG Length,
PLARGE_INTEGER ByteOffset OPTIONAL,
PULONG Key OPTIONAL);
NTSYSAPI
NTSTATUS
NTAPI
NtClose(HANDLE Handle);
NTSYSAPI
NTSTATUS
NTAPI
NtCreateFile(PHANDLE FileHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PIO_STATUS_BLOCK IoStatusBlock,
PLARGE_INTEGER AllocationSize OPTIONAL,
ULONG FileAttributes,
ULONG ShareAccess,
ULONG CreateDisposition,
ULONG CreateOptions,
PVOID EaBuffer OPTIONAL,
ULONG EaLength);
NTSYSAPI
NTSTATUS
NTAPI
NtDeviceIoControlFile(
IN HANDLE FileHandle,
IN HANDLE Event,
IN PIO_APC_ROUTINE ApcRoutine,
IN PVOID ApcContext,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG IoControlCode,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
OUT ULONG OutputBufferLength
);
NTSYSAPI
NTSTATUS
NTAPI
NtFsControlFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG FsControlCode,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength
);
NTSYSAPI
NTSTATUS
NTAPI
NtQueryInformationFile(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
);
//
// Bitmap Routines
//
//
// BitMap routines. The following structure, routines, and macros are
// for manipulating bitmaps. The user is responsible for allocating a bitmap
// structure (which is really a header) and a buffer (which must be longword
// aligned and multiple longwords in size).
//
//
// The following routine initializes a new bitmap. It does not alter the
// data currently in the bitmap. This routine must be called before
// any other bitmap routine/macro.
//
NTSYSAPI
VOID
NTAPI
RtlInitializeBitMap (
PRTL_BITMAP BitMapHeader,
PULONG BitMapBuffer,
ULONG SizeOfBitMap
);
//
// The following two routines either clear or set all of the bits
// in a bitmap.
//
NTSYSAPI
VOID
NTAPI
RtlClearAllBits (
PRTL_BITMAP BitMapHeader
);
NTSYSAPI
VOID
NTAPI
RtlSetAllBits (
PRTL_BITMAP BitMapHeader
);
//
// The following two routines locate a contiguous region of either
// clear or set bits within the bitmap. The region will be at least
// as large as the number specified, and the search of the bitmap will
// begin at the specified hint index (which is a bit index within the
// bitmap, zero based). The return value is the bit index of the located
// region (zero based) or -1 (i.e., 0xffffffff) if such a region cannot
// be located
//
NTSYSAPI
ULONG
NTAPI
RtlFindClearBits (
PRTL_BITMAP BitMapHeader,
ULONG NumberToFind,
ULONG HintIndex
);
NTSYSAPI
ULONG
NTAPI
RtlFindSetBits (
PRTL_BITMAP BitMapHeader,
ULONG NumberToFind,
ULONG HintIndex
);
//
// The following two routines locate a contiguous region of either
// clear or set bits within the bitmap and either set or clear the bits
// within the located region. The region will be as large as the number
// specified, and the search for the region will begin at the specified
// hint index (which is a bit index within the bitmap, zero based). The
// return value is the bit index of the located region (zero based) or
// -1 (i.e., 0xffffffff) if such a region cannot be located. If a region
// cannot be located then the setting/clearing of the bitmap is not performed.
//
NTSYSAPI
ULONG
NTAPI
RtlFindClearBitsAndSet (
PRTL_BITMAP BitMapHeader,
ULONG NumberToFind,
ULONG HintIndex
);
NTSYSAPI
ULONG
NTAPI
RtlFindSetBitsAndClear (
PRTL_BITMAP BitMapHeader,
ULONG NumberToFind,
ULONG HintIndex
);
//
// The following two routines clear or set bits within a specified region
// of the bitmap. The starting index is zero based.
//
NTSYSAPI
VOID
NTAPI
RtlClearBits (
PRTL_BITMAP BitMapHeader,
ULONG StartingIndex,
ULONG NumberToClear
);
NTSYSAPI
VOID
NTAPI
RtlSetBits (
PRTL_BITMAP BitMapHeader,
ULONG StartingIndex,
ULONG NumberToSet
);
//
// The following routine locates a set of contiguous regions of clear
// bits within the bitmap. The caller specifies whether to return the
// longest runs or just the first found lcoated. The following structure is
// used to denote a contiguous run of bits. The two routines return an array
// of this structure, one for each run located.
//
NTSYSAPI
ULONG
NTAPI
RtlFindClearRuns (
PRTL_BITMAP BitMapHeader,
PRTL_BITMAP_RUN RunArray,
ULONG SizeOfRunArray,
BOOLEAN LocateLongestRuns
);
//
// The following routine locates the longest contiguous region of
// clear bits within the bitmap. The returned starting index value
// denotes the first contiguous region located satisfying our requirements
// The return value is the length (in bits) of the longest region found.
//
NTSYSAPI
ULONG
NTAPI
RtlFindLongestRunClear (
PRTL_BITMAP BitMapHeader,
PULONG StartingIndex
);
//
// The following routine locates the first contiguous region of
// clear bits within the bitmap. The returned starting index value
// denotes the first contiguous region located satisfying our requirements
// The return value is the length (in bits) of the region found.
//
NTSYSAPI
ULONG
NTAPI
RtlFindFirstRunClear (
PRTL_BITMAP BitMapHeader,
PULONG StartingIndex
);
//
// The following macro returns the value of the bit stored within the
// bitmap at the specified location. If the bit is set a value of 1 is
// returned otherwise a value of 0 is returned.
//
// ULONG
// RtlCheckBit (
// PRTL_BITMAP BitMapHeader,
// ULONG BitPosition
// );
//
//
// To implement CheckBit the macro retrieves the longword containing the
// bit in question, shifts the longword to get the bit in question into the
// low order bit position and masks out all other bits.
//
#define RtlCheckBit(BMH,BP) ((((BMH)->Buffer[(BP) / 32]) >> ((BP) % 32)) & 0x1)
//
// The following two procedures return to the caller the total number of
// clear or set bits within the specified bitmap.
//
NTSYSAPI
ULONG
NTAPI
RtlNumberOfClearBits (
PRTL_BITMAP BitMapHeader
);
NTSYSAPI
ULONG
NTAPI
RtlNumberOfSetBits (
PRTL_BITMAP BitMapHeader
);
//
// The following two procedures return to the caller a boolean value
// indicating if the specified range of bits are all clear or set.
//
NTSYSAPI
BOOLEAN
NTAPI
RtlAreBitsClear (
PRTL_BITMAP BitMapHeader,
ULONG StartingIndex,
ULONG Length
);
NTSYSAPI
BOOLEAN
NTAPI
RtlAreBitsSet (
PRTL_BITMAP BitMapHeader,
ULONG StartingIndex,
ULONG Length
);
NTSYSAPI
ULONG
NTAPI
RtlFindNextForwardRunClear (
IN PRTL_BITMAP BitMapHeader,
IN ULONG FromIndex,
IN PULONG StartingRunIndex
);
NTSYSAPI
ULONG
NTAPI
RtlFindLastBackwardRunClear (
IN PRTL_BITMAP BitMapHeader,
IN ULONG FromIndex,
IN PULONG StartingRunIndex
);
//
// The following two procedures return to the caller a value indicating
// the position within a ULONGLONG of the most or least significant non-zero
// bit. A value of zero results in a return value of -1.
//
NTSYSAPI
CCHAR
NTAPI
RtlFindLeastSignificantBit (
IN ULONGLONG Set
);
NTSYSAPI
CCHAR
NTAPI
RtlFindMostSignificantBit (
IN ULONGLONG Set
);
//
// Random routines ...
//
NTSYSAPI
ULONG
NTAPI
RtlRandom(
IN OUT PULONG Seed
);
//
// Time routines ...
//
NTSYSAPI
CCHAR
NTAPI
NtQuerySystemTime(
OUT PLARGE_INTEGER CurrentTime
);
NTSYSAPI
BOOLEAN
NTAPI
RtlTimeToSecondsSince1970(
IN PLARGE_INTEGER Time,
OUT PULONG ElapsedSeconds
);
NTSYSAPI
VOID
NTAPI
RtlSecondsSince1970ToTime(
IN ULONG ElapsedSeconds,
OUT PLARGE_INTEGER Time
);
//
// Heap routines...
//
#define GetProcessHeap() (NtCurrentTeb()->Peb->ProcessHeap)
PVOID STDCALL
RtlAllocateHeap (
HANDLE Heap,
ULONG Flags,
ULONG Size
);
BOOLEAN
STDCALL
RtlFreeHeap (
HANDLE Heap,
ULONG Flags,
PVOID Address
);
/*
* Bitmap.c
*/
#define ext2_mark_block_bitmap ext2_mark_bitmap
#define ext2_mark_inode_bitmap ext2_mark_bitmap
#define ext2_unmark_block_bitmap ext2_unmark_bitmap
#define ext2_unmark_inode_bitmap ext2_unmark_bitmap
bool ext2_set_bit(int nr, void * addr);
bool ext2_clear_bit(int nr, void * addr);
bool ext2_test_bit(int nr, void * addr);
bool ext2_mark_bitmap(PEXT2_BITMAP bitmap, ULONG bitno);
bool ext2_unmark_bitmap(PEXT2_BITMAP bitmap, ULONG bitno);
bool ext2_test_block_bitmap(PEXT2_BLOCK_BITMAP bitmap,
ULONG block);
bool ext2_test_block_bitmap_range(PEXT2_BLOCK_BITMAP bitmap,
ULONG block, int num);
bool ext2_test_inode_bitmap(PEXT2_BLOCK_BITMAP bitmap,
ULONG inode);
bool ext2_allocate_block_bitmap(PEXT2_FILESYS pExt2Sys);
bool ext2_allocate_inode_bitmap(PEXT2_FILESYS pExt2Sys);
void ext2_free_inode_bitmap(PEXT2_FILESYS pExt2Sys);
void ext2_free_block_bitmap(PEXT2_FILESYS pExt2Sys);
bool ext2_write_block_bitmap (PEXT2_FILESYS fs);
bool ext2_write_inode_bitmap (PEXT2_FILESYS fs);
bool ext2_write_bitmaps(PEXT2_FILESYS fs);
//bool read_bitmaps(PEXT2_FILESYS fs, int do_inode, int do_block);
bool ext2_read_inode_bitmap (PEXT2_FILESYS fs);
bool ext2_read_block_bitmap(PEXT2_FILESYS fs);
bool ext2_read_bitmaps(PEXT2_FILESYS fs);
/*
* Disk.c
*/
NTSTATUS
Ext2OpenDevice( PEXT2_FILESYS Ext2Sys,
PUNICODE_STRING DeviceName );
NTSTATUS
Ext2CloseDevice( PEXT2_FILESYS Ext2Sys);
NTSTATUS
Ext2ReadDisk( PEXT2_FILESYS Ext2Sys,
ULONGLONG Offset,
ULONG Length,
PVOID Buffer );
NTSTATUS
Ext2WriteDisk( PEXT2_FILESYS Ext2Sys,
ULONGLONG Offset,
ULONG Length,
PVOID Buffer );
NTSTATUS
Ext2GetMediaInfo( PEXT2_FILESYS Ext2Sys );
NTSTATUS
Ext2LockVolume( PEXT2_FILESYS Ext2Sys );
NTSTATUS
Ext2UnLockVolume( PEXT2_FILESYS Ext2Sys );
NTSTATUS
Ext2DisMountVolume( PEXT2_FILESYS Ext2Sys );
/*
* Group.c
*/
bool ext2_allocate_group_desc(PEXT2_FILESYS pExt2Sys);
void ext2_free_group_desc(PEXT2_FILESYS pExt2Sys);
bool ext2_bg_has_super(PEXT2_SUPER_BLOCK pExt2Sb, int group_block);
/*
* Inode.c
*/
bool ext2_get_inode_lba(PEXT2_FILESYS pExt2Sys, ULONG no, LONGLONG *offset);
bool ext2_load_inode(PEXT2_FILESYS pExt2Sys, ULONG no, PEXT2_INODE pInode);
bool ext2_save_inode(PEXT2_FILESYS pExt2Sys, ULONG no, PEXT2_INODE pInode);
bool ext2_new_inode(PEXT2_FILESYS fs, ULONG dir, int mode,
PEXT2_INODE_BITMAP map, ULONG *ret);
bool ext2_expand_inode(PEXT2_FILESYS pExt2Sys, PEXT2_INODE, ULONG newBlk);
bool ext2_read_inode (PEXT2_FILESYS pExt2Sys,
ULONG ino,
ULONG offset,
PVOID Buffer,
ULONG size,
PULONG dwReturn );
bool ext2_write_inode (PEXT2_FILESYS pExt2Sys,
ULONG ino,
ULONG offset,
PVOID Buffer,
ULONG size,
PULONG dwReturn );
bool ext2_add_entry(PEXT2_FILESYS pExt2Sys, ULONG parent, ULONG inode, int filetype, char *name);
bool ext2_reserve_inodes(PEXT2_FILESYS fs);
/*
* Memory.c
*/
//
// Return the group # of an inode number
//
int ext2_group_of_ino(PEXT2_FILESYS fs, ULONG ino);
//
// Return the group # of a block
//
int ext2_group_of_blk(PEXT2_FILESYS fs, ULONG blk);
/*
* Badblock.c
*/
void ext2_inode_alloc_stats2(PEXT2_FILESYS fs, ULONG ino, int inuse, int isdir);
void ext2_inode_alloc_stats(PEXT2_FILESYS fs, ULONG ino, int inuse);
void ext2_block_alloc_stats(PEXT2_FILESYS fs, ULONG blk, int inuse);
bool ext2_allocate_tables(PEXT2_FILESYS pExt2Sys);
bool ext2_allocate_group_table(PEXT2_FILESYS fs, ULONG group,
PEXT2_BLOCK_BITMAP bmap);
bool ext2_get_free_blocks(PEXT2_FILESYS fs, ULONG start, ULONG finish,
int num, PEXT2_BLOCK_BITMAP map, ULONG *ret);
bool write_inode_tables(PEXT2_FILESYS fs);
bool ext2_new_block(PEXT2_FILESYS fs, ULONG goal,
PEXT2_BLOCK_BITMAP map, ULONG *ret);
bool ext2_alloc_block(PEXT2_FILESYS fs, ULONG goal, ULONG *ret);
bool ext2_new_dir_block(PEXT2_FILESYS fs, ULONG dir_ino,
ULONG parent_ino, char **block);
bool ext2_write_block(PEXT2_FILESYS fs, ULONG block, void *inbuf);
bool ext2_read_block(PEXT2_FILESYS fs, ULONG block, void *inbuf);
/*
* Mke2fs.c
*/
bool parase_cmd(int argc, char *argv[], PEXT2_FILESYS pExt2Sys);
bool zero_blocks(PEXT2_FILESYS fs, ULONG blk, ULONG num,
ULONG *ret_blk, ULONG *ret_count);
ULONG
Ext2DataBlocks(PEXT2_FILESYS Ext2Sys, ULONG TotalBlocks);
ULONG
Ext2TotalBlocks(PEXT2_FILESYS Ext2Sys, ULONG DataBlocks);
/*
* Super.c
*/
void ext2_print_super(PEXT2_SUPER_BLOCK pExt2Sb);
bool ext2_initialize_sb(PEXT2_FILESYS pExt2Sys);
/*
* Super.c
*/
LONGLONG ext2_nt_time (ULONG i_time);
ULONG ext2_unix_time (LONGLONG n_time);
/*
* Uuid.c
*/
void uuid_generate(__u8 * uuid);
#endif //__MKE2FS__INCLUDE__

View file

@ -0,0 +1,302 @@
/*
* PROJECT: Mke2fs
* FILE: Super.c
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://ext2.yeah.net
*/
/* INCLUDES **************************************************************/
#include "Mke2fs.h"
/* DEFINITIONS ***********************************************************/
extern int inode_ratio;
/* FUNCTIONS *************************************************************/
void ext2_print_super(PEXT2_SUPER_BLOCK pExt2Sb)
{
int i;
KdPrint(("\nExt2 Super Block Details ...\n\n"));
KdPrint((" Inode Count: %lu\n", pExt2Sb->s_inodes_count));
KdPrint((" Block Count: %lu\n", pExt2Sb->s_blocks_count));
KdPrint((" Reserved Block Count: %lu\n", pExt2Sb->s_r_blocks_count));
KdPrint((" Free Blocks: %lu\n", pExt2Sb->s_free_blocks_count));
KdPrint((" Free Inodes: %lu\n", pExt2Sb->s_free_inodes_count));
KdPrint((" First Data Block: %lu\n", pExt2Sb->s_first_data_block));
KdPrint((" Log Block Size: %lu\n", pExt2Sb->s_log_block_size));
KdPrint((" Log Frag Size: %ld\n", pExt2Sb->s_log_frag_size));
KdPrint((" Blocks per Group: %lu\n", pExt2Sb->s_blocks_per_group));
KdPrint((" Fragments per Group: %lu\n", pExt2Sb->s_frags_per_group));
KdPrint((" Inodes per Group: %lu\n", pExt2Sb->s_inodes_per_group));
// KdPrint((" Mount Time: %s", ctime((time_t *) & (pExt2Sb->s_mtime))));
// KdPrint((" Write Time: %s", ctime((time_t *) & (pExt2Sb->s_wtime))));
KdPrint((" Mount Count: %u\n", pExt2Sb->s_mnt_count));
KdPrint((" Max Mount Count: %d\n", pExt2Sb->s_max_mnt_count));
KdPrint((" Magic Number: %X (%s)\n", pExt2Sb->s_magic,
pExt2Sb->s_magic == EXT2_SUPER_MAGIC ? "OK" : "BAD"));
KdPrint((" File System State: %X\n", pExt2Sb->s_state));
KdPrint((" Error Behaviour: %X\n", pExt2Sb->s_errors));
KdPrint((" Minor rev: %u\n", pExt2Sb->s_minor_rev_level));
// KdPrint((" Last Check: %s", ctime((time_t *) & (pExt2Sb->s_lastcheck))));
KdPrint((" Check Interval: %lu\n", pExt2Sb->s_checkinterval));
KdPrint((" Creator OS: %lu\n", pExt2Sb->s_creator_os));
KdPrint((" Revision Level: %lu\n", pExt2Sb->s_rev_level));
KdPrint((" Reserved Block Default UID: %u\n", pExt2Sb->s_def_resuid));
KdPrint((" Reserved Block Default GID: %u\n", pExt2Sb->s_def_resgid));
KdPrint((" uuid = "));
for (i=0; i < 16; i++)
KdPrint(("%x ", pExt2Sb->s_uuid[i]));
KdPrint(("\n"));
KdPrint((" volume label name: "));
for (i=0; i < 16; i++)
{
if (pExt2Sb->s_volume_name[i] == 0)
break;
KdPrint(("%c", pExt2Sb->s_volume_name[i]));
}
KdPrint(("\n"));
KdPrint(("\n\n"));
}
#define set_field(field, default) if (!pExt2Sb->field) pExt2Sb->field = (default);
/*
* Initialize super block ...
*/
bool ext2_initialize_sb(PEXT2_FILESYS Ext2Sys)
{
int frags_per_block = 0;
ULONG overhead = 0;
int rem = 0;
ULONG i = 0;
ULONG group_block = 0;
ULONG numblocks = 0;
PEXT2_SUPER_BLOCK pExt2Sb = Ext2Sys->ext2_sb;
LARGE_INTEGER SysTime;
NtQuerySystemTime(&SysTime);
Ext2Sys->blocksize = EXT2_BLOCK_SIZE(pExt2Sb);
Ext2Sys->fragsize = EXT2_FRAG_SIZE(pExt2Sb);
frags_per_block = Ext2Sys->blocksize / Ext2Sys->fragsize;
pExt2Sb->s_magic = EXT2_SUPER_MAGIC;
pExt2Sb->s_state = EXT2_VALID_FS;
pExt2Sb->s_first_data_block = (pExt2Sb->s_log_block_size) ? 0 : 1;
pExt2Sb->s_max_mnt_count = EXT2_DFL_MAX_MNT_COUNT;
pExt2Sb->s_errors = EXT2_ERRORS_DEFAULT;
pExt2Sb->s_checkinterval = EXT2_DFL_CHECKINTERVAL;
if (!pExt2Sb->s_rev_level)
pExt2Sb->s_rev_level = EXT2_GOOD_OLD_REV;
if (pExt2Sb->s_rev_level >= EXT2_DYNAMIC_REV)
{
set_field(s_first_ino, EXT2_GOOD_OLD_FIRST_INO);
set_field(s_inode_size, EXT2_GOOD_OLD_INODE_SIZE);
}
RtlTimeToSecondsSince1970(&SysTime, &pExt2Sb->s_wtime);
pExt2Sb->s_lastcheck = pExt2Sb->s_mtime = pExt2Sb->s_wtime;
if (!pExt2Sb->s_blocks_per_group)
pExt2Sb->s_blocks_per_group = Ext2Sys->blocksize * 8;
pExt2Sb->s_frags_per_group = pExt2Sb->s_blocks_per_group * frags_per_block;
pExt2Sb->s_creator_os = EXT2_OS_WINNT;
if (pExt2Sb->s_r_blocks_count >= pExt2Sb->s_blocks_count)
{
goto cleanup;
}
/*
* If we're creating an external journal device, we don't need
* to bother with the rest.
*/
if (pExt2Sb->s_feature_incompat &
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
{
Ext2Sys->group_desc_count = 0;
// ext2fs_mark_super_dirty(fs);
return true;
}
retry:
Ext2Sys->group_desc_count = (pExt2Sb->s_blocks_count - pExt2Sb->s_first_data_block
+ EXT2_BLOCKS_PER_GROUP(pExt2Sb) - 1) / EXT2_BLOCKS_PER_GROUP(pExt2Sb);
if (Ext2Sys->group_desc_count == 0)
return false;
Ext2Sys->desc_blocks = (Ext2Sys->group_desc_count + EXT2_DESC_PER_BLOCK(pExt2Sb)
- 1) / EXT2_DESC_PER_BLOCK(pExt2Sb);
if (!pExt2Sb->s_inodes_count)
pExt2Sb->s_inodes_count = pExt2Sb->s_blocks_count / ( inode_ratio /Ext2Sys->blocksize);
/*
* Make sure we have at least EXT2_FIRST_INO + 1 inodes, so
* that we have enough inodes for the filesystem(!)
*/
if (pExt2Sb->s_inodes_count < EXT2_FIRST_INODE(pExt2Sb)+1)
pExt2Sb->s_inodes_count = EXT2_FIRST_INODE(pExt2Sb)+1;
/*
* There should be at least as many inodes as the user
* requested. Figure out how many inodes per group that
* should be. But make sure that we don't allocate more than
* one bitmap's worth of inodes
*/
pExt2Sb->s_inodes_per_group = (pExt2Sb->s_inodes_count + Ext2Sys->group_desc_count - 1)
/Ext2Sys->group_desc_count;
if (pExt2Sb->s_inodes_per_group > (ULONG)(Ext2Sys->blocksize*8))
pExt2Sb->s_inodes_per_group = Ext2Sys->blocksize*8;
/*
* Make sure the number of inodes per group completely fills
* the inode table blocks in the descriptor. If not, add some
* additional inodes/group. Waste not, want not...
*/
Ext2Sys->inode_blocks_per_group = (((pExt2Sb->s_inodes_per_group * EXT2_INODE_SIZE(pExt2Sb))
+ EXT2_BLOCK_SIZE(pExt2Sb) - 1) / EXT2_BLOCK_SIZE(pExt2Sb));
pExt2Sb->s_inodes_per_group = ((Ext2Sys->inode_blocks_per_group * EXT2_BLOCK_SIZE(pExt2Sb))
/ EXT2_INODE_SIZE(pExt2Sb));
/*
* Finally, make sure the number of inodes per group is a
* multiple of 8. This is needed to simplify the bitmap
* splicing code.
*/
pExt2Sb->s_inodes_per_group &= ~7;
Ext2Sys->inode_blocks_per_group = (((pExt2Sb->s_inodes_per_group * EXT2_INODE_SIZE(pExt2Sb))
+ EXT2_BLOCK_SIZE(pExt2Sb) - 1) / EXT2_BLOCK_SIZE(pExt2Sb));
/*
* adjust inode count to reflect the adjusted inodes_per_group
*/
pExt2Sb->s_inodes_count = pExt2Sb->s_inodes_per_group * Ext2Sys->group_desc_count;
pExt2Sb->s_free_inodes_count = pExt2Sb->s_inodes_count;
/*
* Overhead is the number of bookkeeping blocks per group. It
* includes the superblock backup, the group descriptor
* backups, the inode bitmap, the block bitmap, and the inode
* table.
*
* XXX Not all block groups need the descriptor blocks, but
* being clever is tricky...
*/
overhead = (int) (3 + Ext2Sys->desc_blocks + Ext2Sys->inode_blocks_per_group);
/*
* See if the last group is big enough to support the
* necessary data structures. If not, we need to get rid of
* it.
*/
rem = (int) ((pExt2Sb->s_blocks_count - pExt2Sb->s_first_data_block) %
pExt2Sb->s_blocks_per_group);
if ((Ext2Sys->group_desc_count == 1) && rem && (rem < overhead))
return false;
if (rem && (rem < overhead+50))
{
pExt2Sb->s_blocks_count -= rem;
goto retry;
}
/*
* At this point we know how big the filesystem will be. So we can do
* any and all allocations that depend on the block count.
*/
// Allocate block bitmap
if(!ext2_allocate_block_bitmap(Ext2Sys))
{
goto cleanup;
}
// Allocate inode bitmap
if(!ext2_allocate_inode_bitmap(Ext2Sys))
{
goto cleanup;
}
// Allocate gourp desc
if(!ext2_allocate_group_desc(Ext2Sys))
{
goto cleanup;
}
/*
* Reserve the superblock and group descriptors for each
* group, and fill in the correct group statistics for group.
* Note that although the block bitmap, inode bitmap, and
* inode table have not been allocated (and in fact won't be
* by this routine), they are accounted for nevertheless.
*/
group_block = pExt2Sb->s_first_data_block;
numblocks = 0;
pExt2Sb->s_free_blocks_count = 0;
for (i = 0; i < Ext2Sys->group_desc_count; i++)
{
if (i == Ext2Sys->group_desc_count-1)
{
numblocks = (pExt2Sb->s_blocks_count - pExt2Sb->s_first_data_block)
% pExt2Sb->s_blocks_per_group;
if (!numblocks)
numblocks = pExt2Sb->s_blocks_per_group;
}
else
{
numblocks = pExt2Sb->s_blocks_per_group;
}
if (ext2_bg_has_super(pExt2Sb, i))
{
ULONG j;
for (j=0; j < Ext2Sys->desc_blocks+1; j++)
ext2_mark_bitmap(Ext2Sys->block_map, group_block + j);
numblocks -= 1 + Ext2Sys->desc_blocks;
}
numblocks -= 2 + Ext2Sys->inode_blocks_per_group;
pExt2Sb->s_free_blocks_count += numblocks;
Ext2Sys->group_desc[i].bg_free_blocks_count = (__u16)numblocks;
Ext2Sys->group_desc[i].bg_free_inodes_count = (__u16)pExt2Sb->s_inodes_per_group;
Ext2Sys->group_desc[i].bg_used_dirs_count = 0;
group_block += pExt2Sb->s_blocks_per_group;
}
return true;
cleanup:
ext2_free_group_desc(Ext2Sys);
ext2_free_block_bitmap(Ext2Sys);
ext2_free_inode_bitmap(Ext2Sys);
return false;
}

View file

@ -0,0 +1,25 @@
/*
* PROJECT: Mke2fs
* FILE: Timer.c
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://ext2.yeah.net
*/
/* INCLUDES **************************************************************/
#include "windows.h"
#include "types.h"
/* DEFINITIONS ***********************************************************/
/* FUNCTIONS *************************************************************/
void uuid_generate(__u8 * uuid)
{
#if 0
UuidCreate((UUID *) uuid);
#else
RtlZeroMemory(uuid, 16);
#endif
}

View file

@ -0,0 +1,657 @@
/*
* linux/include/linux/ext2_fs.h
*
* Copyright (C) 1992, 1993, 1994, 1995
* Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* from
*
* linux/include/linux/minix_fs.h
*
* Copyright f(C) 1991, 1992 Linus Torvalds
*/
#ifndef _LINUX_EXT2_FS_H
#define _LINUX_EXT2_FS_H
#include "types.h" /* Changed from linux/types.h */
/*
* The second extended filesystem constants/structures
*/
/*
* Define EXT2FS_DEBUG to produce debug messages
*/
#undef EXT2FS_DEBUG
/*
* Define EXT2_PREALLOCATE to preallocate data blocks for expanding files
*/
#define EXT2_PREALLOCATE
#define EXT2_DEFAULT_PREALLOC_BLOCKS 8
/*
* The second extended file system version
*/
#define EXT2FS_DATE "95/08/09"
#define EXT2FS_VERSION "0.5b"
/*
* Special inodes numbers
*/
#define EXT2_BAD_INO 1 /* Bad blocks inode */
#define EXT2_ROOT_INO 2 /* Root inode */
#define EXT2_ACL_IDX_INO 3 /* ACL inode */
#define EXT2_ACL_DATA_INO 4 /* ACL inode */
#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
#define EXT2_RESIZE_INO 7 /* Reserved group descriptors inode */
#define EXT2_JOURNAL_INO 8 /* Journal inode */
/* First non-reserved inode for old ext2 filesystems */
#define EXT2_GOOD_OLD_FIRST_INO 11
/*
* The second extended file system magic number
*/
#define EXT2_SUPER_MAGIC 0xEF53
/*
* Maximal count of links to a file
*/
#define EXT2_LINK_MAX 32000
/*
* Macro-instructions used to manage several block sizes
*/
#define EXT2_MIN_BLOCK_SIZE 1024
#define EXT2_MAX_BLOCK_SIZE 4096
#define EXT2_MIN_BLOCK_LOG_SIZE 10
#ifdef __KERNEL__
# define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize)
#else
# define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
#endif
#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
#ifdef __KERNEL__
# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
#else
# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
#endif
#ifdef __KERNEL__
#define EXT2_ADDR_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_addr_per_block_bits)
#define EXT2_INODE_SIZE(s) ((s)->u.ext2_sb.s_inode_size)
#define EXT2_FIRST_INO(s) ((s)->u.ext2_sb.s_first_ino)
#else
#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
EXT2_GOOD_OLD_INODE_SIZE : \
(s)->s_inode_size)
#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
EXT2_GOOD_OLD_FIRST_INO : \
(s)->s_first_ino)
#endif
/*
* Macro-instructions used to manage fragments
*/
#define EXT2_MIN_FRAG_SIZE 1024
#define EXT2_MAX_FRAG_SIZE 4096
#define EXT2_MIN_FRAG_LOG_SIZE 10
#ifdef __KERNEL__
# define EXT2_FRAG_SIZE(s) ((s)->u.ext2_sb.s_frag_size)
# define EXT2_FRAGS_PER_BLOCK(s) ((s)->u.ext2_sb.s_frags_per_block)
#else
# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
#endif
/*
* ACL structures
*/
struct ext2_acl_header /* Header of Access Control Lists */
{
__u32 aclh_size;
__u32 aclh_file_count;
__u32 aclh_acle_count;
__u32 aclh_first_acle;
};
struct ext2_acl_entry /* Access Control List Entry */
{
__u32 acle_size;
__u16 acle_perms; /* Access permissions */
__u16 acle_type; /* Type of entry */
__u16 acle_tag; /* User or group identity */
__u16 acle_pad1;
__u32 acle_next; /* Pointer on next entry for the */
/* same inode or on next free entry */
};
/*
* Structure of a blocks group descriptor
*/
struct ext2_group_desc
{
__u32 bg_block_bitmap; /* Blocks bitmap block */
__u32 bg_inode_bitmap; /* Inodes bitmap block */
__u32 bg_inode_table; /* Inodes table block */
__u16 bg_free_blocks_count; /* Free blocks count */
__u16 bg_free_inodes_count; /* Free inodes count */
__u16 bg_used_dirs_count; /* Directories count */
__u16 bg_pad;
__u32 bg_reserved[3];
};
/*
* Data structures used by the directory indexing feature
*
* Note: all of the multibyte integer fields are little endian.
*/
/*
* Note: dx_root_info is laid out so that if it should somehow get
* overlaid by a dirent the two low bits of the hash version will be
* zero. Therefore, the hash version mod 4 should never be 0.
* Sincerely, the paranoia department.
*/
struct ext2_dx_root_info {
__u32 reserved_zero;
__u8 hash_version; /* 0 now, 1 at release */
__u8 info_length; /* 8 */
__u8 indirect_levels;
__u8 unused_flags;
};
struct ext2_dx_entry {
__u32 hash;
__u32 block;
};
struct ext2_dx_countlimit {
__u16 limit;
__u16 count;
};
/*
* Macro-instructions used to manage group descriptors
*/
#ifdef __KERNEL__
# define EXT2_BLOCKS_PER_GROUP(s) ((s)->u.ext2_sb.s_blocks_per_group)
# define EXT2_DESC_PER_BLOCK(s) ((s)->u.ext2_sb.s_desc_per_block)
# define EXT2_INODES_PER_GROUP(s) ((s)->u.ext2_sb.s_inodes_per_group)
# define EXT2_DESC_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_desc_per_block_bits)
#else
# define EXT2_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group)
# define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
# define EXT2_INODES_PER_GROUP(s) ((s)->s_inodes_per_group)
#endif
/*
* Constants relative to the data blocks
*/
#define EXT2_NDIR_BLOCKS 12
#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
/*
* Inode flags
*/
#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */
#define EXT2_UNRM_FL 0x00000002 /* Undelete */
#define EXT2_COMPR_FL 0x00000004 /* Compress file */
#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */
#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */
/* Reserved for compression usage... */
#define EXT2_DIRTY_FL 0x00000100
#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
#define EXT2_NOCOMPR_FL 0x00000400 /* Access raw compressed data */
#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */
/* End compression flags --- maybe not all used */
#define EXT2_BTREE_FL 0x00001000 /* btree format dir */
#define EXT2_INDEX_FL 0x00001000 /* hash-indexed directory */
#define EXT2_IMAGIC_FL 0x00002000
#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
#define EXT2_NOTAIL_FL 0x00008000 /* file tail should not be merged */
#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
#define EXT2_FL_USER_VISIBLE 0x0000DFFF /* User visible flags */
#define EXT2_FL_USER_MODIFIABLE 0x000080FF /* User modifiable flags */
/*
* ioctl commands
*/
#define EXT2_IOC_GETFLAGS _IOR('f', 1, long)
#define EXT2_IOC_SETFLAGS _IOW('f', 2, long)
#define EXT2_IOC_GETVERSION _IOR('v', 1, long)
#define EXT2_IOC_SETVERSION _IOW('v', 2, long)
/*
* Structure of an inode on the disk
*/
struct ext2_inode {
__u16 i_mode; /* File mode */
__u16 i_uid; /* Low 16 bits of Owner Uid */
__u32 i_size; /* Size in bytes */
__u32 i_atime; /* Access time */
__u32 i_ctime; /* Creation time */
__u32 i_mtime; /* Modification time */
__u32 i_dtime; /* Deletion Time */
__u16 i_gid; /* Low 16 bits of Group Id */
__u16 i_links_count; /* Links count */
__u32 i_blocks; /* Blocks count */
__u32 i_flags; /* File flags */
union {
struct {
__u32 l_i_reserved1;
} linux1;
struct {
__u32 h_i_translator;
} hurd1;
struct {
__u32 m_i_reserved1;
} masix1;
} osd1; /* OS dependent 1 */
__u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
__u32 i_generation; /* File version (for NFS) */
__u32 i_file_acl; /* File ACL */
__u32 i_dir_acl; /* Directory ACL */
__u32 i_faddr; /* Fragment address */
union {
struct {
__u8 l_i_frag; /* Fragment number */
__u8 l_i_fsize; /* Fragment size */
__u16 i_pad1;
__u16 l_i_uid_high; /* these 2 fields */
__u16 l_i_gid_high; /* were reserved2[0] */
__u32 l_i_reserved2;
} linux2;
struct {
__u8 h_i_frag; /* Fragment number */
__u8 h_i_fsize; /* Fragment size */
__u16 h_i_mode_high;
__u16 h_i_uid_high;
__u16 h_i_gid_high;
__u32 h_i_author;
} hurd2;
struct {
__u8 m_i_frag; /* Fragment number */
__u8 m_i_fsize; /* Fragment size */
__u16 m_pad1;
__u32 m_i_reserved2[2];
} masix2;
} osd2; /* OS dependent 2 */
};
#define i_size_high i_dir_acl
#if defined(__KERNEL__) || defined(__linux__)
#define i_reserved1 osd1.linux1.l_i_reserved1
#define i_frag osd2.linux2.l_i_frag
#define i_fsize osd2.linux2.l_i_fsize
#define i_uid_low i_uid
#define i_gid_low i_gid
#define i_uid_high osd2.linux2.l_i_uid_high
#define i_gid_high osd2.linux2.l_i_gid_high
#define i_reserved2 osd2.linux2.l_i_reserved2
#elif defined(__GNU__)
#define i_translator osd1.hurd1.h_i_translator
#define i_frag osd2.hurd2.h_i_frag;
#define i_fsize osd2.hurd2.h_i_fsize;
#define i_uid_high osd2.hurd2.h_i_uid_high
#define i_gid_high osd2.hurd2.h_i_gid_high
#define i_author osd2.hurd2.h_i_author
#elif defined(__masix__)
#define i_reserved1 osd1.masix1.m_i_reserved1
#define i_frag osd2.masix2.m_i_frag
#define i_fsize osd2.masix2.m_i_fsize
#define i_reserved2 osd2.masix2.m_i_reserved2
#endif /* defined(__KERNEL) || defined(__linux__) */
/*
* File system states
*/
#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */
#define EXT2_ERROR_FS 0x0002 /* Errors detected */
/*
* Mount flags
*/
#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */
#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */
#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */
#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */
#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
#define test_opt(sb, opt) ((sb)->u.ext2_sb.s_mount_opt & \
EXT2_MOUNT_##opt)
/*
* Maximal mount counts between two filesystem checks
*/
#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */
/*
* Behaviour when detecting errors
*/
#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */
#define EXT2_ERRORS_RO 2 /* Remount fs read-only */
#define EXT2_ERRORS_PANIC 3 /* Panic */
#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE
/*
* Structure of the super block
*/
struct ext2_super_block {
__u32 s_inodes_count; /* Inodes count */
__u32 s_blocks_count; /* Blocks count */
__u32 s_r_blocks_count; /* Reserved blocks count */
__u32 s_free_blocks_count; /* Free blocks count */
__u32 s_free_inodes_count; /* Free inodes count */
__u32 s_first_data_block; /* First Data Block */
__u32 s_log_block_size; /* Block size */
__s32 s_log_frag_size; /* Fragment size */
__u32 s_blocks_per_group; /* # Blocks per group */
__u32 s_frags_per_group; /* # Fragments per group */
__u32 s_inodes_per_group; /* # Inodes per group */
__u32 s_mtime; /* Mount time */
__u32 s_wtime; /* Write time */
__u16 s_mnt_count; /* Mount count */
__s16 s_max_mnt_count; /* Maximal mount count */
__u16 s_magic; /* Magic signature */
__u16 s_state; /* File system state */
__u16 s_errors; /* Behaviour when detecting errors */
__u16 s_minor_rev_level; /* minor revision level */
__u32 s_lastcheck; /* time of last check */
__u32 s_checkinterval; /* max. time between checks */
__u32 s_creator_os; /* OS */
__u32 s_rev_level; /* Revision level */
__u16 s_def_resuid; /* Default uid for reserved blocks */
__u16 s_def_resgid; /* Default gid for reserved blocks */
/*
* These fields are for EXT2_DYNAMIC_REV superblocks only.
*
* Note: the difference between the compatible feature set and
* the incompatible feature set is that if there is a bit set
* in the incompatible feature set that the kernel doesn't
* know about, it should refuse to mount the filesystem.
*
* e2fsck's requirements are more strict; if it doesn't know
* about a feature in either the compatible or incompatible
* feature set, it must abort and not try to meddle with
* things it doesn't understand...
*/
__u32 s_first_ino; /* First non-reserved inode */
__u16 s_inode_size; /* size of inode structure */
__u16 s_block_group_nr; /* block group # of this superblock */
__u32 s_feature_compat; /* compatible feature set */
__u32 s_feature_incompat; /* incompatible feature set */
__u32 s_feature_ro_compat; /* readonly-compatible feature set */
__u8 s_uuid[16]; /* 128-bit uuid for volume */
char s_volume_name[16]; /* volume name */
char s_last_mounted[64]; /* directory where last mounted */
__u32 s_algorithm_usage_bitmap; /* For compression */
/*
* Performance hints. Directory preallocation should only
* happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
*/
__u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
__u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
__u16 s_padding1;
/*
* Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
*/
__u8 s_journal_uuid[16]; /* uuid of journal superblock */
__u32 s_journal_inum; /* inode number of journal file */
__u32 s_journal_dev; /* device number of journal file */
__u32 s_last_orphan; /* start of list of inodes to delete */
__u32 s_reserved[197]; /* Padding to the end of the block */
};
#ifdef __KERNEL__
#define EXT2_SB(sb) (&((sb)->u.ext2_sb))
#else
/* Assume that user mode programs are passing in an ext2fs superblock, not
* a kernel struct super_block. This will allow us to call the feature-test
* macros from user land. */
#define EXT2_SB(sb) (sb)
#endif
/*
* Codes for operating systems
*/
#define EXT2_OS_LINUX 0
#define EXT2_OS_HURD 1
#define EXT2_OS_MASIX 2
#define EXT2_OS_FREEBSD 3
#define EXT2_OS_LITES 4
#define EXT2_OS_WINNT 5
/*
* Revision levels
*/
#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV
#define EXT2_GOOD_OLD_INODE_SIZE 128
/*
* Feature set definitions
*/
#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \
( EXT2_SB(sb)->s_feature_compat & (mask) )
#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \
( EXT2_SB(sb)->s_feature_ro_compat & (mask) )
#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \
( EXT2_SB(sb)->s_feature_incompat & (mask) )
#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002
#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008
#define EXT2_FEATURE_COMPAT_RESIZE_INODE 0x0010
#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
#define EXT2_FEATURE_COMPAT_SUPP 0
#define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
/*
* Default values for user and/or group using reserved blocks
*/
#define EXT2_DEF_RESUID 0
#define EXT2_DEF_RESGID 0
/*
* Structure of a directory entry
*/
#define EXT2_NAME_LEN 255
struct ext2_dir_entry {
__u32 inode; /* Inode number */
__u16 rec_len; /* Directory entry length */
__u16 name_len; /* Name length */
char name[EXT2_NAME_LEN]; /* File name */
};
/*
* The new version of the directory entry. Since EXT2 structures are
* stored in intel byte order, and the name_len field could never be
* bigger than 255 chars, it's safe to reclaim the extra byte for the
* file_type field.
*/
struct ext2_dir_entry_2 {
__u32 inode; /* Inode number */
__u16 rec_len; /* Directory entry length */
__u8 name_len; /* Name length */
__u8 file_type;
char name[EXT2_NAME_LEN]; /* File name */
};
/*
* Ext2 directory file types. Only the low 3 bits are used. The
* other bits are reserved for now.
*/
#define EXT2_FT_UNKNOWN 0
#define EXT2_FT_REG_FILE 1
#define EXT2_FT_DIR 2
#define EXT2_FT_CHRDEV 3
#define EXT2_FT_BLKDEV 4
#define EXT2_FT_FIFO 5
#define EXT2_FT_SOCK 6
#define EXT2_FT_SYMLINK 7
#define EXT2_FT_MAX 8
/*
* EXT2_DIR_PAD defines the directory entries boundaries
*
* NOTE: It must be a multiple of 4
*/
#define EXT2_DIR_PAD 4
#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
~EXT2_DIR_ROUND)
#ifdef __KERNEL__
/*
* Function prototypes
*/
/*
* Ok, these declarations are also in <linux/kernel.h> but none of the
* ext2 source programs needs to include it so they are duplicated here.
*/
# define NORET_TYPE /**/
# define ATTRIB_NORET __attribute__((noreturn))
# define NORET_AND noreturn,
/* acl.c */
extern int ext2_permission (struct inode *, int);
/* balloc.c */
extern int ext2_bg_has_super(struct super_block *sb, int group);
extern unsigned long ext2_bg_num_gdb(struct super_block *sb, int group);
extern int ext2_new_block (const struct inode *, unsigned long,
__u32 *, __u32 *, int *);
extern void ext2_free_blocks (const struct inode *, unsigned long,
unsigned long);
extern unsigned long ext2_count_free_blocks (struct super_block *);
extern void ext2_check_blocks_bitmap (struct super_block *);
extern struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
unsigned int block_group,
struct buffer_head ** bh);
/* bitmap.c */
extern unsigned long ext2_count_free (struct buffer_head *, unsigned);
/* dir.c */
extern int ext2_check_dir_entry (const char *, struct inode *,
struct ext2_dir_entry_2 *, struct buffer_head *,
unsigned long);
/* file.c */
extern int ext2_read (struct inode *, struct file *, char *, int);
extern int ext2_write (struct inode *, struct file *, char *, int);
/* fsync.c */
extern int ext2_sync_file (struct file *, struct dentry *, int);
extern int ext2_fsync_inode (struct inode *, int);
/* ialloc.c */
extern struct inode * ext2_new_inode (const struct inode *, int);
extern void ext2_free_inode (struct inode *);
extern unsigned long ext2_count_free_inodes (struct super_block *);
extern void ext2_check_inodes_bitmap (struct super_block *);
/* inode.c */
extern struct buffer_head * ext2_getblk (struct inode *, long, int, int *);
extern struct buffer_head * ext2_bread (struct inode *, int, int, int *);
extern void ext2_read_inode (struct inode *);
extern void ext2_write_inode (struct inode *, int);
extern void ext2_put_inode (struct inode *);
extern void ext2_delete_inode (struct inode *);
extern int ext2_sync_inode (struct inode *);
extern void ext2_discard_prealloc (struct inode *);
/* ioctl.c */
extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
unsigned long);
/* namei.c */
extern struct inode_operations ext2_dir_inode_operations;
/* super.c */
extern void ext2_error (struct super_block *, const char *, const char *, ...)
__attribute__ ((format (printf, 3, 4)));
extern NORET_TYPE void ext2_panic (struct super_block *, const char *,
const char *, ...)
__attribute__ ((NORET_AND format (printf, 3, 4)));
extern void ext2_warning (struct super_block *, const char *, const char *, ...)
__attribute__ ((format (printf, 3, 4)));
extern void ext2_update_dynamic_rev (struct super_block *sb);
extern void ext2_put_super (struct super_block *);
extern void ext2_write_super (struct super_block *);
extern int ext2_remount (struct super_block *, int *, char *);
extern struct super_block * ext2_read_super (struct super_block *,void *,int);
extern int ext2_statfs (struct super_block *, struct statfs *);
/* truncate.c */
extern void ext2_truncate (struct inode *);
/*
* Inodes and files operations
*/
/* dir.c */
extern struct file_operations ext2_dir_operations;
/* file.c */
extern struct inode_operations ext2_file_inode_operations;
extern struct file_operations ext2_file_operations;
/* symlink.c */
extern struct inode_operations ext2_fast_symlink_inode_operations;
extern struct address_space_operations ext2_aops;
#endif /* __KERNEL__ */
#endif /* _LINUX_EXT2_FS_H */

View file

@ -0,0 +1,10 @@
#ifndef _LINUX_TYPES_H
#define _LINUX_TYPES_H
typedef unsigned long __u32;
typedef signed long __s32;
typedef unsigned short int __u16;
typedef signed short int __s16;
typedef unsigned char __u8;
#endif /* LINUX_TYPES_H */