mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 02:05:50 +00:00
Ext2lib import by filip navara for use by usetup.
svn path=/branches/ext2/; revision=13010
This commit is contained in:
parent
d31a52e423
commit
395064be78
16 changed files with 6008 additions and 0 deletions
3
reactos/lib/fslib/ext2lib/.cvsignore
Normal file
3
reactos/lib/fslib/ext2lib/.cvsignore
Normal file
|
@ -0,0 +1,3 @@
|
|||
*.d
|
||||
*.o
|
||||
*.sym
|
43
reactos/lib/fslib/ext2lib/Badblock.c
Normal file
43
reactos/lib/fslib/ext2lib/Badblock.c
Normal 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;
|
||||
}
|
499
reactos/lib/fslib/ext2lib/Bitmap.c
Normal file
499
reactos/lib/fslib/ext2lib/Bitmap.c
Normal 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);
|
||||
}
|
||||
|
12
reactos/lib/fslib/ext2lib/Bitmap.h
Normal file
12
reactos/lib/fslib/ext2lib/Bitmap.h
Normal 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
|
1352
reactos/lib/fslib/ext2lib/Disk.c
Normal file
1352
reactos/lib/fslib/ext2lib/Disk.c
Normal file
File diff suppressed because it is too large
Load diff
19
reactos/lib/fslib/ext2lib/Disk.h
Normal file
19
reactos/lib/fslib/ext2lib/Disk.h
Normal 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_ */
|
68
reactos/lib/fslib/ext2lib/Group.c
Normal file
68
reactos/lib/fslib/ext2lib/Group.c
Normal 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;
|
||||
}
|
||||
}
|
697
reactos/lib/fslib/ext2lib/Inode.c
Normal file
697
reactos/lib/fslib/ext2lib/Inode.c
Normal 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;
|
||||
}
|
19
reactos/lib/fslib/ext2lib/Makefile
Normal file
19
reactos/lib/fslib/ext2lib/Makefile
Normal 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
|
416
reactos/lib/fslib/ext2lib/Memory.c
Normal file
416
reactos/lib/fslib/ext2lib/Memory.c
Normal 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;
|
||||
}
|
1010
reactos/lib/fslib/ext2lib/Mke2fs.c
Normal file
1010
reactos/lib/fslib/ext2lib/Mke2fs.c
Normal file
File diff suppressed because it is too large
Load diff
876
reactos/lib/fslib/ext2lib/Mke2fs.h
Normal file
876
reactos/lib/fslib/ext2lib/Mke2fs.h
Normal 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__
|
302
reactos/lib/fslib/ext2lib/Super.c
Normal file
302
reactos/lib/fslib/ext2lib/Super.c
Normal 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;
|
||||
}
|
25
reactos/lib/fslib/ext2lib/Uuid.c
Normal file
25
reactos/lib/fslib/ext2lib/Uuid.c
Normal 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
|
||||
}
|
657
reactos/lib/fslib/ext2lib/ext2_fs.h
Normal file
657
reactos/lib/fslib/ext2lib/ext2_fs.h
Normal 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 */
|
10
reactos/lib/fslib/ext2lib/types.h
Normal file
10
reactos/lib/fslib/ext2lib/types.h
Normal 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 */
|
Loading…
Add table
Add a link
Reference in a new issue