mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 21:16:09 +00:00
[FREELDR] Rewrite the header and reformat/adapt current code
This commit is contained in:
parent
1f3083be75
commit
a980ad08b4
2 changed files with 355 additions and 342 deletions
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* FreeLoader
|
* FreeLoader
|
||||||
* Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
|
* Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
|
||||||
|
* Copyright (C) 2024-2025 Daniel Victor <ilauncherdeveloper@gmail.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -39,161 +40,173 @@
|
||||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Magic value used to identify an ext filesystem. */
|
#include <pshpack1.h>
|
||||||
#define EXT_MAGIC 0xEF53
|
|
||||||
/* Amount of indirect blocks in an inode. */
|
|
||||||
#define INDIRECT_BLOCKS 12
|
|
||||||
/* Maximum length of a pathname. */
|
|
||||||
#define EXT_PATH_MAX 4096
|
|
||||||
/* Maximum nesting of symlinks, used to prevent a loop. */
|
|
||||||
#define EXT_MAX_SYMLINKCNT 8
|
|
||||||
|
|
||||||
/* The good old revision and the default inode size. */
|
#define EXT_SUPERBLOCK_MAGIC 0xEF53
|
||||||
#define EXT_GOOD_OLD_REVISION 0
|
|
||||||
#define EXT_DYNAMIC_REVISION 1
|
#define EXT_DYNAMIC_REVISION 1
|
||||||
#define EXT_GOOD_OLD_INODE_SIZE 128
|
#define EXT_DEFAULT_INODE_SIZE 128
|
||||||
|
#define EXT_DEFAULT_GROUP_DESC_SIZE 32
|
||||||
|
|
||||||
/* Filetype used in directory entry. */
|
#define EXT_DIR_ENTRY_MAX_NAME_LENGTH 255
|
||||||
#define FILETYPE_UNKNOWN 0
|
|
||||||
#define FILETYPE_REG 1
|
|
||||||
#define FILETYPE_DIRECTORY 2
|
|
||||||
#define FILETYPE_SYMLINK 7
|
|
||||||
|
|
||||||
/* Filetype information as used in inodes. */
|
typedef struct _ExtSuperBlock
|
||||||
#define FILETYPE_INO_MASK 0170000
|
|
||||||
#define FILETYPE_INO_REG 0100000
|
|
||||||
#define FILETYPE_INO_DIRECTORY 0040000
|
|
||||||
#define FILETYPE_INO_SYMLINK 0120000
|
|
||||||
|
|
||||||
/* The ext superblock. */
|
|
||||||
struct ext_sblock
|
|
||||||
{
|
{
|
||||||
ULONG total_inodes;
|
/* SuperBlock Information Ext2 */
|
||||||
ULONG total_blocks;
|
ULONG InodesCount;
|
||||||
ULONG reserved_blocks;
|
ULONG BlocksCountLo;
|
||||||
ULONG free_blocks;
|
ULONG RBlocksCountLo;
|
||||||
ULONG free_inodes;
|
ULONG FreeBlocksCountLo;
|
||||||
ULONG first_data_block;
|
ULONG FreeInodesCount;
|
||||||
ULONG log2_block_size;
|
ULONG FirstDataBlock;
|
||||||
LONG log2_fragment_size;
|
ULONG LogBlockSize;
|
||||||
ULONG blocks_per_group;
|
LONG LogFragSize;
|
||||||
ULONG fragments_per_group;
|
ULONG BlocksPerGroup;
|
||||||
ULONG inodes_per_group;
|
ULONG FragsPerGroup;
|
||||||
ULONG mtime;
|
ULONG InodesPerGroup;
|
||||||
ULONG utime;
|
ULONG MTime;
|
||||||
USHORT mnt_count;
|
ULONG WTime;
|
||||||
USHORT max_mnt_count;
|
USHORT MntCount;
|
||||||
USHORT magic;
|
USHORT MaxMntCount;
|
||||||
USHORT fs_state;
|
USHORT Magic;
|
||||||
USHORT error_handling;
|
USHORT State;
|
||||||
USHORT minor_revision_level;
|
USHORT Errors;
|
||||||
ULONG lastcheck;
|
USHORT MinorRevisionLevel;
|
||||||
ULONG checkinterval;
|
ULONG LastCheck;
|
||||||
ULONG creator_os;
|
ULONG CheckInterval;
|
||||||
ULONG revision_level;
|
ULONG CreatorOS;
|
||||||
USHORT uid_reserved;
|
ULONG RevisionLevel;
|
||||||
USHORT gid_reserved;
|
USHORT DefResUID;
|
||||||
ULONG first_inode;
|
USHORT DefResGID;
|
||||||
USHORT inode_size;
|
|
||||||
USHORT block_group_number;
|
|
||||||
ULONG feature_compatibility;
|
|
||||||
ULONG feature_incompat;
|
|
||||||
ULONG feature_ro_compat;
|
|
||||||
ULONG unique_id[4];
|
|
||||||
char volume_name[16];
|
|
||||||
char last_mounted_on[64];
|
|
||||||
ULONG compression_info;
|
|
||||||
ULONG padding[77];
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The ext blockgroup. */
|
/* SuperBlock Information Ext3 */
|
||||||
struct ext_block_group
|
ULONG FirstInode;
|
||||||
{
|
USHORT InodeSize;
|
||||||
ULONG block_id;
|
USHORT BlockGroupNr;
|
||||||
ULONG inode_id;
|
ULONG FeatureCompat;
|
||||||
ULONG inode_table_id;
|
ULONG FeatureIncompat;
|
||||||
USHORT free_blocks;
|
ULONG FeatureROCompat;
|
||||||
USHORT free_inodes;
|
UCHAR UUID[16];
|
||||||
USHORT used_dirs;
|
CHAR VolumeName[16];
|
||||||
USHORT pad;
|
CHAR LastMounted[64];
|
||||||
ULONG reserved[3];
|
ULONG AlgorithmUsageBitmap;
|
||||||
};
|
UCHAR PreallocBlocks;
|
||||||
|
UCHAR PreallocDirBlocks;
|
||||||
|
USHORT ReservedGdtBlocks;
|
||||||
|
UCHAR JournalUUID[16];
|
||||||
|
ULONG JournalInum;
|
||||||
|
ULONG JournalDev;
|
||||||
|
ULONG LastOrphan;
|
||||||
|
ULONG HashSeed[4];
|
||||||
|
UCHAR DefHashVersion;
|
||||||
|
UCHAR JournalBackupType;
|
||||||
|
USHORT GroupDescSize;
|
||||||
|
UCHAR Reserved[768];
|
||||||
|
} EXT_SUPER_BLOCK, *PEXT_SUPER_BLOCK;
|
||||||
|
|
||||||
/* The ext inode. */
|
typedef struct _ExtGroupDescriptor
|
||||||
struct ext_inode
|
|
||||||
{
|
{
|
||||||
USHORT mode;
|
ULONG BlockBitmap;
|
||||||
USHORT uid;
|
ULONG InodeBitmap;
|
||||||
ULONG size;
|
ULONG InodeTable;
|
||||||
ULONG atime;
|
USHORT FreeBlocksCount;
|
||||||
ULONG ctime;
|
USHORT FreeInodesCount;
|
||||||
ULONG mtime;
|
USHORT UsedDirsCount;
|
||||||
ULONG dtime;
|
} EXT_GROUP_DESC, *PEXT_GROUP_DESC;
|
||||||
USHORT gid;
|
|
||||||
USHORT nlinks;
|
typedef struct _Ext4ExtentHeader
|
||||||
ULONG blockcnt; /* Blocks of 512 bytes!! */
|
{
|
||||||
ULONG flags;
|
USHORT Magic;
|
||||||
ULONG osd1;
|
USHORT Entries;
|
||||||
|
USHORT Max;
|
||||||
|
USHORT Depth;
|
||||||
|
ULONG Generation;
|
||||||
|
} EXT4_EXTENT_HEADER, *PEXT4_EXTENT_HEADER;
|
||||||
|
|
||||||
|
typedef struct _Ext4ExtentIdx
|
||||||
|
{
|
||||||
|
ULONG Block;
|
||||||
|
ULONG Leaf;
|
||||||
|
USHORT LeafHigh;
|
||||||
|
USHORT Unused;
|
||||||
|
} EXT4_EXTENT_IDX, *PEXT4_EXTENT_IDX;
|
||||||
|
|
||||||
|
typedef struct _Ext4Extent
|
||||||
|
{
|
||||||
|
ULONG Block;
|
||||||
|
USHORT Length;
|
||||||
|
USHORT StartHigh;
|
||||||
|
ULONG Start;
|
||||||
|
} EXT4_EXTENT, *PEXT4_EXTENT;
|
||||||
|
|
||||||
|
typedef struct _ExtInode
|
||||||
|
{
|
||||||
|
USHORT Mode;
|
||||||
|
USHORT UID;
|
||||||
|
ULONG Size;
|
||||||
|
ULONG Atime;
|
||||||
|
ULONG Ctime;
|
||||||
|
ULONG Mtime;
|
||||||
|
ULONG Dtime;
|
||||||
|
USHORT GID;
|
||||||
|
USHORT LinksCount;
|
||||||
|
ULONG BlocksCount;
|
||||||
|
ULONG Flags;
|
||||||
|
ULONG OSD1;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct datablocks
|
CHAR SymLink[60];
|
||||||
|
struct
|
||||||
{
|
{
|
||||||
ULONG dir_blocks[INDIRECT_BLOCKS];
|
ULONG DirectBlocks[12];
|
||||||
ULONG indir_block;
|
ULONG IndirectBlock;
|
||||||
ULONG double_indir_block;
|
ULONG DoubleIndirectBlock;
|
||||||
ULONG tripple_indir_block;
|
ULONG TripleIndirectBlock;
|
||||||
} blocks;
|
} Blocks;
|
||||||
char symlink[60];
|
EXT4_EXTENT_HEADER ExtentHeader;
|
||||||
};
|
|
||||||
ULONG version;
|
|
||||||
ULONG acl;
|
|
||||||
ULONG dir_acl;
|
|
||||||
ULONG fragment_addr;
|
|
||||||
ULONG osd2[3];
|
|
||||||
};
|
};
|
||||||
|
ULONG Generation;
|
||||||
|
ULONG FileACL;
|
||||||
|
ULONG DirACL;
|
||||||
|
ULONG FragAddress;
|
||||||
|
ULONG OSD2[3];
|
||||||
|
} EXT_INODE, *PEXT_INODE;
|
||||||
|
|
||||||
/* The header of an ext directory entry. */
|
typedef struct _ExtDirEntry
|
||||||
#define EXT_NAME_LEN 255
|
|
||||||
|
|
||||||
struct ext_dirent
|
|
||||||
{
|
{
|
||||||
ULONG inode;
|
ULONG Inode;
|
||||||
USHORT direntlen;
|
USHORT EntryLen;
|
||||||
UCHAR namelen;
|
UCHAR NameLen;
|
||||||
UCHAR filetype;
|
UCHAR FileType;
|
||||||
CHAR name[EXT_NAME_LEN];
|
CHAR Name[EXT_DIR_ENTRY_MAX_NAME_LENGTH];
|
||||||
};
|
} EXT_DIR_ENTRY, *PEXT_DIR_ENTRY;
|
||||||
|
|
||||||
/*
|
#include <poppack.h>
|
||||||
* End of code from grub/fs/ext2.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct ext_sblock EXT_SUPER_BLOCK, *PEXT_SUPER_BLOCK;
|
|
||||||
typedef struct ext_inode EXT_INODE, *PEXT_INODE;
|
|
||||||
typedef struct ext_block_group EXT_GROUP_DESC, *PEXT_GROUP_DESC;
|
|
||||||
typedef struct ext_dirent EXT_DIR_ENTRY, *PEXT_DIR_ENTRY;
|
|
||||||
|
|
||||||
/* Special inode numbers. */
|
/* Special inode numbers. */
|
||||||
#define EXT_ROOT_INO 2
|
#define EXT_ROOT_INODE 2
|
||||||
|
|
||||||
/* Feature set definitions. */
|
|
||||||
#define EXT3_FEATURE_INCOMPAT_SUPP 0x0002
|
|
||||||
|
|
||||||
/* Log2 size of ext block in bytes. */
|
|
||||||
#define LOG2_BLOCK_SIZE(sb) (sb->log2_block_size + 10)
|
|
||||||
|
|
||||||
/* The size of an ext block in bytes. */
|
|
||||||
#define EXT_BLOCK_SIZE(sb) (((SIZE_T)1) << LOG2_BLOCK_SIZE(sb))
|
|
||||||
|
|
||||||
/* The revision level. */
|
/* The revision level. */
|
||||||
#define EXT_REVISION(sb) (sb->revision_level)
|
#define EXT_REVISION(sb) (sb->RevisionLevel)
|
||||||
|
|
||||||
/* The inode size. */
|
/* The inode size. */
|
||||||
#define EXT_INODE_SIZE(sb) (EXT_REVISION(sb) == EXT_GOOD_OLD_REVISION \
|
#define EXT_INODE_SIZE(sb) \
|
||||||
? EXT_GOOD_OLD_INODE_SIZE \
|
(EXT_REVISION(sb) < EXT_DYNAMIC_REVISION ? EXT_DEFAULT_INODE_SIZE : sb->InodeSize)
|
||||||
: sb->inode_size)
|
|
||||||
|
|
||||||
#define EXT_DESC_PER_BLOCK(s) (EXT_BLOCK_SIZE(s) / sizeof(struct ext_block_group))
|
/* The group descriptor size. */
|
||||||
|
#define EXT_GROUP_DESC_SIZE(sb) \
|
||||||
|
((EXT_REVISION(sb) >= EXT_DYNAMIC_REVISION && sb->GroupDescSize) ? sb->GroupDescSize : EXT_DEFAULT_GROUP_DESC_SIZE)
|
||||||
|
|
||||||
|
/* The inode extents flag. */
|
||||||
|
#define EXT4_INODE_FLAG_EXTENTS 0x80000
|
||||||
|
|
||||||
|
/* The extent header magic value. */
|
||||||
|
#define EXT4_EXTENT_HEADER_MAGIC 0xF30A
|
||||||
|
|
||||||
|
/* The maximum extent level. */
|
||||||
|
#define EXT4_EXTENT_MAX_LEVEL 5
|
||||||
|
|
||||||
|
/* The maximum extent length used to check for sparse extents. */
|
||||||
|
#define EXT4_EXTENT_MAX_LENGTH 32768
|
||||||
|
|
||||||
// EXT_INODE::mode values
|
// EXT_INODE::mode values
|
||||||
#define EXT_S_IRWXO 0x0007 // Other mask
|
#define EXT_S_IRWXO 0x0007 // Other mask
|
||||||
|
@ -228,11 +241,11 @@ typedef struct ext_dirent EXT_DIR_ENTRY, *PEXT_DIR_ENTRY;
|
||||||
|
|
||||||
typedef struct _EXT_VOLUME_INFO *PEXT_VOLUME_INFO;
|
typedef struct _EXT_VOLUME_INFO *PEXT_VOLUME_INFO;
|
||||||
|
|
||||||
typedef struct
|
typedef struct _EXT_FILE_INFO
|
||||||
{
|
{
|
||||||
ULONGLONG FileSize; // File size
|
ULONGLONG FileSize; // File size
|
||||||
ULONGLONG FilePointer; // File pointer
|
ULONGLONG FilePointer; // File pointer
|
||||||
ULONG* FileBlockList; // File block list
|
PULONG FileBlockList; // File block list
|
||||||
EXT_INODE Inode; // File's inode
|
EXT_INODE Inode; // File's inode
|
||||||
PEXT_VOLUME_INFO Volume;
|
PEXT_VOLUME_INFO Volume;
|
||||||
} EXT_FILE_INFO, *PEXT_FILE_INFO;
|
} EXT_FILE_INFO, *PEXT_FILE_INFO;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* FreeLoader
|
* FreeLoader
|
||||||
* Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
|
* Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
|
||||||
|
* Copyright (C) 2024-2025 Daniel Victor <ilauncherdeveloper@gmail.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -54,6 +55,8 @@ typedef struct _EXT_VOLUME_INFO
|
||||||
ULONG BlockSizeInSectors; // Block size in sectors
|
ULONG BlockSizeInSectors; // Block size in sectors
|
||||||
ULONG FragmentSizeInBytes; // Fragment size in bytes
|
ULONG FragmentSizeInBytes; // Fragment size in bytes
|
||||||
ULONG FragmentSizeInSectors; // Fragment size in sectors
|
ULONG FragmentSizeInSectors; // Fragment size in sectors
|
||||||
|
ULONG InodeSizeInBytes; // Inode size in bytes
|
||||||
|
ULONG GroupDescSizeInBytes; // Group descriptor size in bytes
|
||||||
ULONG GroupCount; // Number of groups in this file system
|
ULONG GroupCount; // Number of groups in this file system
|
||||||
ULONG InodesPerBlock; // Number of inodes in one block
|
ULONG InodesPerBlock; // Number of inodes in one block
|
||||||
ULONG GroupDescPerBlock; // Number of group descriptors in one block
|
ULONG GroupDescPerBlock; // Number of group descriptors in one block
|
||||||
|
@ -104,11 +107,11 @@ PEXT_FILE_INFO ExtOpenFile(PEXT_VOLUME_INFO Volume, PCSTR FileName)
|
||||||
{
|
{
|
||||||
EXT_FILE_INFO TempExtFileInfo;
|
EXT_FILE_INFO TempExtFileInfo;
|
||||||
PEXT_FILE_INFO FileHandle;
|
PEXT_FILE_INFO FileHandle;
|
||||||
CHAR SymLinkPath[EXT_NAME_LEN];
|
CHAR SymLinkPath[EXT_DIR_ENTRY_MAX_NAME_LENGTH];
|
||||||
CHAR FullPath[EXT_NAME_LEN * 2];
|
CHAR FullPath[EXT_DIR_ENTRY_MAX_NAME_LENGTH * 2];
|
||||||
ULONG_PTR Index;
|
ULONG_PTR Index;
|
||||||
|
|
||||||
TRACE("ExtOpenFile() FileName = %s\n", FileName);
|
TRACE("ExtOpenFile() FileName = \"%s\"\n", FileName);
|
||||||
|
|
||||||
RtlZeroMemory(SymLinkPath, sizeof(SymLinkPath));
|
RtlZeroMemory(SymLinkPath, sizeof(SymLinkPath));
|
||||||
|
|
||||||
|
@ -120,7 +123,7 @@ PEXT_FILE_INFO ExtOpenFile(PEXT_VOLUME_INFO Volume, PCSTR FileName)
|
||||||
|
|
||||||
// If we got a symbolic link then fix up the path
|
// If we got a symbolic link then fix up the path
|
||||||
// and re-call this function
|
// and re-call this function
|
||||||
if ((TempExtFileInfo.Inode.mode & EXT_S_IFMT) == EXT_S_IFLNK)
|
if ((TempExtFileInfo.Inode.Mode & EXT_S_IFMT) == EXT_S_IFLNK)
|
||||||
{
|
{
|
||||||
TRACE("File is a symbolic link\n");
|
TRACE("File is a symbolic link\n");
|
||||||
|
|
||||||
|
@ -135,14 +138,14 @@ PEXT_FILE_INFO ExtOpenFile(PEXT_VOLUME_INFO Volume, PCSTR FileName)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("Symbolic link path = %s\n", SymLinkPath);
|
TRACE("Symbolic link path = \"%s\"\n", SymLinkPath);
|
||||||
|
|
||||||
// Get the full path
|
// Get the full path
|
||||||
if (SymLinkPath[0] == '/' || SymLinkPath[0] == '\\')
|
if (SymLinkPath[0] == '/' || SymLinkPath[0] == '\\')
|
||||||
{
|
{
|
||||||
// Symbolic link is an absolute path
|
// Symbolic link is an absolute path
|
||||||
// So copy it to FullPath, but skip over
|
// So copy it to FullPath, but skip over
|
||||||
// the '/' char at the beginning
|
// the '/' character at the beginning
|
||||||
strcpy(FullPath, &SymLinkPath[1]);
|
strcpy(FullPath, &SymLinkPath[1]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -167,7 +170,7 @@ PEXT_FILE_INFO ExtOpenFile(PEXT_VOLUME_INFO Volume, PCSTR FileName)
|
||||||
strcat(FullPath, SymLinkPath);
|
strcat(FullPath, SymLinkPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("Full file path = %s\n", FullPath);
|
TRACE("Full file path = \"%s\"\n", FullPath);
|
||||||
|
|
||||||
if (TempExtFileInfo.FileBlockList != NULL)
|
if (TempExtFileInfo.FileBlockList != NULL)
|
||||||
{
|
{
|
||||||
|
@ -208,11 +211,11 @@ BOOLEAN ExtLookupFile(PEXT_VOLUME_INFO Volume, PCSTR FileName, PEXT_FILE_INFO Ex
|
||||||
ULONG NumberOfPathParts;
|
ULONG NumberOfPathParts;
|
||||||
CHAR PathPart[261];
|
CHAR PathPart[261];
|
||||||
PVOID DirectoryBuffer;
|
PVOID DirectoryBuffer;
|
||||||
ULONG DirectoryInode = EXT_ROOT_INO;
|
ULONG DirectoryInode = EXT_ROOT_INODE;
|
||||||
EXT_INODE InodeData;
|
EXT_INODE InodeData;
|
||||||
EXT_DIR_ENTRY DirectoryEntry;
|
EXT_DIR_ENTRY DirectoryEntry;
|
||||||
|
|
||||||
TRACE("ExtLookupFile() FileName = %s\n", FileName);
|
TRACE("ExtLookupFile() FileName = \"%s\"\n", FileName);
|
||||||
|
|
||||||
RtlZeroMemory(ExtFileInfo, sizeof(EXT_FILE_INFO));
|
RtlZeroMemory(ExtFileInfo, sizeof(EXT_FILE_INFO));
|
||||||
|
|
||||||
|
@ -261,7 +264,7 @@ BOOLEAN ExtLookupFile(PEXT_VOLUME_INFO Volume, PCSTR FileName, PEXT_FILE_INFO Ex
|
||||||
|
|
||||||
FrLdrTempFree(DirectoryBuffer, TAG_EXT_BUFFER);
|
FrLdrTempFree(DirectoryBuffer, TAG_EXT_BUFFER);
|
||||||
|
|
||||||
DirectoryInode = DirectoryEntry.inode;
|
DirectoryInode = DirectoryEntry.Inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ExtReadInode(Volume, DirectoryInode, &InodeData))
|
if (!ExtReadInode(Volume, DirectoryInode, &InodeData))
|
||||||
|
@ -269,8 +272,8 @@ BOOLEAN ExtLookupFile(PEXT_VOLUME_INFO Volume, PCSTR FileName, PEXT_FILE_INFO Ex
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((InodeData.mode & EXT_S_IFMT) != EXT_S_IFREG) &&
|
if (((InodeData.Mode & EXT_S_IFMT) != EXT_S_IFREG) &&
|
||||||
((InodeData.mode & EXT_S_IFMT) != EXT_S_IFLNK))
|
((InodeData.Mode & EXT_S_IFMT) != EXT_S_IFLNK))
|
||||||
{
|
{
|
||||||
FileSystemError("Inode is not a regular file or symbolic link.");
|
FileSystemError("Inode is not a regular file or symbolic link.");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -282,8 +285,8 @@ BOOLEAN ExtLookupFile(PEXT_VOLUME_INFO Volume, PCSTR FileName, PEXT_FILE_INFO Ex
|
||||||
// If it's a regular file or a regular symbolic link
|
// If it's a regular file or a regular symbolic link
|
||||||
// then get the block pointer list otherwise it must
|
// then get the block pointer list otherwise it must
|
||||||
// be a fast symbolic link which doesn't have a block list
|
// be a fast symbolic link which doesn't have a block list
|
||||||
if (((InodeData.mode & EXT_S_IFMT) == EXT_S_IFREG) ||
|
if (((InodeData.Mode & EXT_S_IFMT) == EXT_S_IFREG) ||
|
||||||
((InodeData.mode & EXT_S_IFMT) == EXT_S_IFLNK && InodeData.size > FAST_SYMLINK_MAX_NAME_SIZE))
|
((InodeData.Mode & EXT_S_IFMT) == EXT_S_IFLNK && InodeData.Size > FAST_SYMLINK_MAX_NAME_SIZE))
|
||||||
{
|
{
|
||||||
ExtFileInfo->FileBlockList = ExtReadBlockPointerList(Volume, &InodeData);
|
ExtFileInfo->FileBlockList = ExtReadBlockPointerList(Volume, &InodeData);
|
||||||
if (ExtFileInfo->FileBlockList == NULL)
|
if (ExtFileInfo->FileBlockList == NULL)
|
||||||
|
@ -305,50 +308,49 @@ BOOLEAN ExtLookupFile(PEXT_VOLUME_INFO Volume, PCSTR FileName, PEXT_FILE_INFO Ex
|
||||||
|
|
||||||
BOOLEAN ExtSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySize, PCHAR FileName, PEXT_DIR_ENTRY DirectoryEntry)
|
BOOLEAN ExtSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySize, PCHAR FileName, PEXT_DIR_ENTRY DirectoryEntry)
|
||||||
{
|
{
|
||||||
ULONG CurrentOffset;
|
ULONG CurrentOffset = 0;
|
||||||
PEXT_DIR_ENTRY CurrentDirectoryEntry;
|
PEXT_DIR_ENTRY CurrentDirectoryEntry;
|
||||||
|
|
||||||
TRACE("ExtSearchDirectoryBufferForFile() DirectoryBuffer = 0x%x DirectorySize = %d FileName = %s\n", DirectoryBuffer, DirectorySize, FileName);
|
TRACE("ExtSearchDirectoryBufferForFile() DirectoryBuffer = 0x%x DirectorySize = %d FileName = \"%s\"\n", DirectoryBuffer, DirectorySize, FileName);
|
||||||
|
|
||||||
for (CurrentOffset=0; CurrentOffset<DirectorySize; )
|
while (CurrentOffset < DirectorySize)
|
||||||
{
|
{
|
||||||
CurrentDirectoryEntry = (PEXT_DIR_ENTRY)((ULONG_PTR)DirectoryBuffer + CurrentOffset);
|
CurrentDirectoryEntry = (PEXT_DIR_ENTRY)((ULONG_PTR)DirectoryBuffer + CurrentOffset);
|
||||||
|
|
||||||
if (CurrentDirectoryEntry->direntlen == 0)
|
if (!CurrentDirectoryEntry->EntryLen)
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
if ((CurrentDirectoryEntry->direntlen + CurrentOffset) > DirectorySize)
|
if ((CurrentDirectoryEntry->EntryLen + CurrentOffset) > DirectorySize)
|
||||||
{
|
{
|
||||||
FileSystemError("Directory entry extends past end of directory file.");
|
FileSystemError("Directory entry extends past end of directory file.");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("Dumping directory entry at offset %d:\n", CurrentOffset);
|
if (!CurrentDirectoryEntry->Inode)
|
||||||
DbgDumpBuffer(DPRINT_FILESYSTEM, CurrentDirectoryEntry, CurrentDirectoryEntry->direntlen);
|
goto NextDirectoryEntry;
|
||||||
|
|
||||||
if ((_strnicmp(FileName, CurrentDirectoryEntry->name, CurrentDirectoryEntry->namelen) == 0) &&
|
|
||||||
(strlen(FileName) == CurrentDirectoryEntry->namelen))
|
|
||||||
{
|
|
||||||
RtlCopyMemory(DirectoryEntry, CurrentDirectoryEntry, sizeof(EXT_DIR_ENTRY));
|
|
||||||
|
|
||||||
TRACE("EXT Directory Entry:\n");
|
TRACE("EXT Directory Entry:\n");
|
||||||
TRACE("inode = %d\n", DirectoryEntry->inode);
|
TRACE("Inode = %d\n", CurrentDirectoryEntry->Inode);
|
||||||
TRACE("direntlen = %d\n", DirectoryEntry->direntlen);
|
TRACE("EntryLen = %d\n", CurrentDirectoryEntry->EntryLen);
|
||||||
TRACE("namelen = %d\n", DirectoryEntry->namelen);
|
TRACE("NameLen = %d\n", CurrentDirectoryEntry->NameLen);
|
||||||
TRACE("filetype = %d\n", DirectoryEntry->filetype);
|
TRACE("FileType = %d\n", CurrentDirectoryEntry->FileType);
|
||||||
TRACE("name = ");
|
TRACE("Name = \"");
|
||||||
for (CurrentOffset=0; CurrentOffset<DirectoryEntry->namelen; CurrentOffset++)
|
for (ULONG NameOffset = 0; NameOffset < CurrentDirectoryEntry->NameLen; NameOffset++)
|
||||||
{
|
{
|
||||||
TRACE("%c", DirectoryEntry->name[CurrentOffset]);
|
TRACE("%c", CurrentDirectoryEntry->Name[NameOffset]);
|
||||||
}
|
}
|
||||||
TRACE("\n");
|
TRACE("\"\n\n");
|
||||||
|
|
||||||
|
if (strlen(FileName) == CurrentDirectoryEntry->NameLen &&
|
||||||
|
!_strnicmp(FileName, CurrentDirectoryEntry->Name, CurrentDirectoryEntry->NameLen))
|
||||||
|
{
|
||||||
|
RtlCopyMemory(DirectoryEntry, CurrentDirectoryEntry, sizeof(EXT_DIR_ENTRY));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrentOffset += CurrentDirectoryEntry->direntlen;
|
NextDirectoryEntry:
|
||||||
|
CurrentOffset += CurrentDirectoryEntry->EntryLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -380,7 +382,7 @@ BOOLEAN ExtReadFileBig(PEXT_FILE_INFO ExtFileInfo, ULONGLONG BytesToRead, ULONGL
|
||||||
{
|
{
|
||||||
// Block pointer list is NULL
|
// Block pointer list is NULL
|
||||||
// so this better be a fast symbolic link or else
|
// so this better be a fast symbolic link or else
|
||||||
if (((ExtFileInfo->Inode.mode & EXT_S_IFMT) != EXT_S_IFLNK) ||
|
if (((ExtFileInfo->Inode.Mode & EXT_S_IFMT) != EXT_S_IFLNK) ||
|
||||||
(ExtFileInfo->FileSize > FAST_SYMLINK_MAX_NAME_SIZE))
|
(ExtFileInfo->FileSize > FAST_SYMLINK_MAX_NAME_SIZE))
|
||||||
{
|
{
|
||||||
FileSystemError("Block pointer list is NULL and file is not a fast symbolic link.");
|
FileSystemError("Block pointer list is NULL and file is not a fast symbolic link.");
|
||||||
|
@ -408,13 +410,13 @@ BOOLEAN ExtReadFileBig(PEXT_FILE_INFO ExtFileInfo, ULONGLONG BytesToRead, ULONGL
|
||||||
|
|
||||||
// Check if this is a fast symbolic link
|
// Check if this is a fast symbolic link
|
||||||
// if so then the read is easy
|
// if so then the read is easy
|
||||||
if (((ExtFileInfo->Inode.mode & EXT_S_IFMT) == EXT_S_IFLNK) &&
|
if (((ExtFileInfo->Inode.Mode & EXT_S_IFMT) == EXT_S_IFLNK) &&
|
||||||
(ExtFileInfo->FileSize <= FAST_SYMLINK_MAX_NAME_SIZE))
|
(ExtFileInfo->FileSize <= FAST_SYMLINK_MAX_NAME_SIZE))
|
||||||
{
|
{
|
||||||
TRACE("Reading fast symbolic link data\n");
|
TRACE("Reading fast symbolic link data\n");
|
||||||
|
|
||||||
// Copy the data from the link
|
// Copy the data from the link
|
||||||
RtlCopyMemory(Buffer, (PVOID)((ULONG_PTR)ExtFileInfo->FilePointer + ExtFileInfo->Inode.symlink), (ULONG)BytesToRead);
|
RtlCopyMemory(Buffer, (PVOID)((ULONG_PTR)ExtFileInfo->FilePointer + ExtFileInfo->Inode.SymLink), (ULONG)BytesToRead);
|
||||||
|
|
||||||
if (BytesRead != NULL)
|
if (BytesRead != NULL)
|
||||||
{
|
{
|
||||||
|
@ -615,94 +617,96 @@ BOOLEAN ExtReadSuperBlock(PEXT_VOLUME_INFO Volume)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
TRACE("Dumping super block:\n");
|
TRACE("Dumping super block:\n");
|
||||||
TRACE("total_inodes: %d\n", SuperBlock->total_inodes);
|
TRACE("InodesCount: %d\n", SuperBlock->InodesCount);
|
||||||
TRACE("total_blocks: %d\n", SuperBlock->total_blocks);
|
TRACE("BlocksCountLo: %d\n", SuperBlock->BlocksCountLo);
|
||||||
TRACE("reserved_blocks: %d\n", SuperBlock->reserved_blocks);
|
TRACE("RBlocksCountLo: %d\n", SuperBlock->RBlocksCountLo);
|
||||||
TRACE("free_blocks: %d\n", SuperBlock->free_blocks);
|
TRACE("FreeBlocksCountLo: %d\n", SuperBlock->FreeBlocksCountLo);
|
||||||
TRACE("free_inodes: %d\n", SuperBlock->free_inodes);
|
TRACE("FreeInodesCount: %d\n", SuperBlock->FreeInodesCount);
|
||||||
TRACE("first_data_block: %d\n", SuperBlock->first_data_block);
|
TRACE("FirstDataBlock: %d\n", SuperBlock->FirstDataBlock);
|
||||||
TRACE("log2_block_size: %d\n", SuperBlock->log2_block_size);
|
TRACE("LogBlockSize: %d\n", SuperBlock->LogBlockSize);
|
||||||
TRACE("log2_fragment_size: %d\n", SuperBlock->log2_fragment_size);
|
TRACE("LogFragSize: %d\n", SuperBlock->LogFragSize);
|
||||||
TRACE("blocks_per_group: %d\n", SuperBlock->blocks_per_group);
|
TRACE("BlocksPerGroup: %d\n", SuperBlock->BlocksPerGroup);
|
||||||
TRACE("fragments_per_group: %d\n", SuperBlock->fragments_per_group);
|
TRACE("FragsPerGroup: %d\n", SuperBlock->FragsPerGroup);
|
||||||
TRACE("inodes_per_group: %d\n", SuperBlock->inodes_per_group);
|
TRACE("InodesPerGroup: %d\n", SuperBlock->InodesPerGroup);
|
||||||
TRACE("mtime: %d\n", SuperBlock->mtime);
|
TRACE("MTime: %d\n", SuperBlock->MTime);
|
||||||
TRACE("utime: %d\n", SuperBlock->utime);
|
TRACE("WTime: %d\n", SuperBlock->WTime);
|
||||||
TRACE("mnt_count: %d\n", SuperBlock->mnt_count);
|
TRACE("MntCount: %d\n", SuperBlock->MntCount);
|
||||||
TRACE("max_mnt_count: %d\n", SuperBlock->max_mnt_count);
|
TRACE("MaxMntCount: %d\n", SuperBlock->MaxMntCount);
|
||||||
TRACE("magic: 0x%x\n", SuperBlock->magic);
|
TRACE("Magic: 0x%x\n", SuperBlock->Magic);
|
||||||
TRACE("fs_state: %d\n", SuperBlock->fs_state);
|
TRACE("State: 0x%x\n", SuperBlock->State);
|
||||||
TRACE("error_handling: %d\n", SuperBlock->error_handling);
|
TRACE("Errors: 0x%x\n", SuperBlock->Errors);
|
||||||
TRACE("minor_revision_level: %d\n", SuperBlock->minor_revision_level);
|
TRACE("MinorRevisionLevel: %d\n", SuperBlock->MinorRevisionLevel);
|
||||||
TRACE("lastcheck: %d\n", SuperBlock->lastcheck);
|
TRACE("LastCheck: %d\n", SuperBlock->LastCheck);
|
||||||
TRACE("checkinterval: %d\n", SuperBlock->checkinterval);
|
TRACE("CheckInterval: %d\n", SuperBlock->CheckInterval);
|
||||||
TRACE("creator_os: %d\n", SuperBlock->creator_os);
|
TRACE("CreatorOS: %d\n", SuperBlock->CreatorOS);
|
||||||
TRACE("revision_level: %d\n", SuperBlock->revision_level);
|
TRACE("RevisionLevel: %d\n", SuperBlock->RevisionLevel);
|
||||||
TRACE("uid_reserved: %d\n", SuperBlock->uid_reserved);
|
TRACE("DefResUID: %d\n", SuperBlock->DefResUID);
|
||||||
TRACE("gid_reserved: %d\n", SuperBlock->gid_reserved);
|
TRACE("DefResGID: %d\n", SuperBlock->DefResGID);
|
||||||
TRACE("first_inode: %d\n", SuperBlock->first_inode);
|
TRACE("FirstInode: %d\n", SuperBlock->FirstInode);
|
||||||
TRACE("inode_size: %d\n", SuperBlock->inode_size);
|
TRACE("InodeSize: %d\n", SuperBlock->InodeSize);
|
||||||
TRACE("block_group_number: %d\n", SuperBlock->block_group_number);
|
TRACE("BlockGroupNr: %d\n", SuperBlock->BlockGroupNr);
|
||||||
TRACE("feature_compatibility: 0x%x\n", SuperBlock->feature_compatibility);
|
TRACE("FeatureCompat: 0x%x\n", SuperBlock->FeatureCompat);
|
||||||
TRACE("feature_incompat: 0x%x\n", SuperBlock->feature_incompat);
|
TRACE("FeatureIncompat: 0x%x\n", SuperBlock->FeatureIncompat);
|
||||||
TRACE("feature_ro_compat: 0x%x\n", SuperBlock->feature_ro_compat);
|
TRACE("FeatureROCompat: 0x%x\n", SuperBlock->FeatureROCompat);
|
||||||
TRACE("unique_id = { 0x%x, 0x%x, 0x%x, 0x%x }\n",
|
TRACE("UUID: { ");
|
||||||
SuperBlock->unique_id[0], SuperBlock->unique_id[1],
|
for (ULONG i = 0; i < sizeof(SuperBlock->UUID); i++)
|
||||||
SuperBlock->unique_id[2], SuperBlock->unique_id[3]);
|
{
|
||||||
TRACE("volume_name = '%.16s'\n", SuperBlock->volume_name);
|
TRACE("0x%02x", SuperBlock->UUID[i]);
|
||||||
TRACE("last_mounted_on = '%.64s'\n", SuperBlock->last_mounted_on);
|
if (i < sizeof(SuperBlock->UUID) - 1)
|
||||||
TRACE("compression_info = 0x%x\n", SuperBlock->compression_info);
|
TRACE(", ");
|
||||||
|
}
|
||||||
|
TRACE(" }\n");
|
||||||
|
TRACE("VolumeName: \"%s\"\n", SuperBlock->VolumeName);
|
||||||
|
TRACE("LastMounted: \"%s\"\n", SuperBlock->LastMounted);
|
||||||
|
TRACE("AlgorithmUsageBitmap: 0x%x\n", SuperBlock->AlgorithmUsageBitmap);
|
||||||
|
TRACE("PreallocBlocks: %d\n", SuperBlock->PreallocBlocks);
|
||||||
|
TRACE("PreallocDirBlocks: %d\n", SuperBlock->PreallocDirBlocks);
|
||||||
|
TRACE("ReservedGdtBlocks: %d\n", SuperBlock->ReservedGdtBlocks);
|
||||||
|
TRACE("JournalUUID: { ");
|
||||||
|
for (ULONG i = 0; i < sizeof(SuperBlock->JournalUUID); i++)
|
||||||
|
{
|
||||||
|
TRACE("0x%02x", SuperBlock->JournalUUID[i]);
|
||||||
|
if (i < sizeof(SuperBlock->JournalUUID) - 1)
|
||||||
|
TRACE(", ");
|
||||||
|
}
|
||||||
|
TRACE(" }\n");
|
||||||
|
TRACE("JournalInum: %d\n", SuperBlock->JournalInum);
|
||||||
|
TRACE("JournalDev: %d\n", SuperBlock->JournalDev);
|
||||||
|
TRACE("LastOrphan: %d\n", SuperBlock->LastOrphan);
|
||||||
|
TRACE("HashSeed: { 0x%02x, 0x%02x, 0x%02x, 0x%02x }\n",
|
||||||
|
SuperBlock->HashSeed[0], SuperBlock->HashSeed[1],
|
||||||
|
SuperBlock->HashSeed[2], SuperBlock->HashSeed[3]);
|
||||||
|
TRACE("DefHashVersion: %d\n", SuperBlock->DefHashVersion);
|
||||||
|
TRACE("JournalBackupType: %d\n", SuperBlock->JournalBackupType);
|
||||||
|
TRACE("GroupDescSize: %d\n", SuperBlock->GroupDescSize);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check the super block magic
|
// Check the super block magic
|
||||||
//
|
//
|
||||||
if (SuperBlock->magic != EXT_MAGIC)
|
if (SuperBlock->Magic != EXT_SUPERBLOCK_MAGIC)
|
||||||
{
|
{
|
||||||
FileSystemError("Invalid super block magic (0xef53)");
|
FileSystemError("Invalid super block magic (0xef53)");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Check the revision level
|
|
||||||
//
|
|
||||||
if (SuperBlock->revision_level > EXT_DYNAMIC_REVISION)
|
|
||||||
{
|
|
||||||
FileSystemError("FreeLoader does not understand the revision of this EXT/EXT3 filesystem.\nPlease update FreeLoader.");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Check the feature set
|
|
||||||
// Don't need to check the compatible or read-only compatible features
|
|
||||||
// because we only mount the filesystem as read-only
|
|
||||||
//
|
|
||||||
if ((SuperBlock->revision_level >= EXT_DYNAMIC_REVISION) &&
|
|
||||||
(/*((SuperBlock->s_feature_compat & ~EXT3_FEATURE_COMPAT_SUPP) != 0) ||*/
|
|
||||||
/*((SuperBlock->s_feature_ro_compat & ~EXT3_FEATURE_RO_COMPAT_SUPP) != 0) ||*/
|
|
||||||
((SuperBlock->feature_incompat & ~EXT3_FEATURE_INCOMPAT_SUPP) != 0)))
|
|
||||||
{
|
|
||||||
FileSystemError("FreeLoader does not understand features of this EXT/EXT3 filesystem.\nPlease update FreeLoader.");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the group count
|
// Calculate the group count
|
||||||
Volume->GroupCount = (SuperBlock->total_blocks - SuperBlock->first_data_block + SuperBlock->blocks_per_group - 1) / SuperBlock->blocks_per_group;
|
Volume->GroupCount = (SuperBlock->BlocksCountLo - SuperBlock->FirstDataBlock + SuperBlock->BlocksPerGroup - 1) / SuperBlock->BlocksPerGroup;
|
||||||
TRACE("ExtGroupCount: %d\n", Volume->GroupCount);
|
TRACE("ExtGroupCount: %d\n", Volume->GroupCount);
|
||||||
|
|
||||||
// Calculate the block size
|
// Calculate the block size
|
||||||
Volume->BlockSizeInBytes = 1024 << SuperBlock->log2_block_size;
|
Volume->BlockSizeInBytes = 1024 << SuperBlock->LogBlockSize;
|
||||||
Volume->BlockSizeInSectors = Volume->BlockSizeInBytes / Volume->BytesPerSector;
|
Volume->BlockSizeInSectors = Volume->BlockSizeInBytes / Volume->BytesPerSector;
|
||||||
TRACE("ExtBlockSizeInBytes: %d\n", Volume->BlockSizeInBytes);
|
TRACE("ExtBlockSizeInBytes: %d\n", Volume->BlockSizeInBytes);
|
||||||
TRACE("ExtBlockSizeInSectors: %d\n", Volume->BlockSizeInSectors);
|
TRACE("ExtBlockSizeInSectors: %d\n", Volume->BlockSizeInSectors);
|
||||||
|
|
||||||
// Calculate the fragment size
|
// Calculate the fragment size
|
||||||
if (SuperBlock->log2_fragment_size >= 0)
|
if (SuperBlock->LogFragSize >= 0)
|
||||||
{
|
{
|
||||||
Volume->FragmentSizeInBytes = 1024 << SuperBlock->log2_fragment_size;
|
Volume->FragmentSizeInBytes = 1024 << SuperBlock->LogFragSize;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Volume->FragmentSizeInBytes = 1024 >> -(SuperBlock->log2_fragment_size);
|
Volume->FragmentSizeInBytes = 1024 >> -(SuperBlock->LogFragSize);
|
||||||
}
|
}
|
||||||
Volume->FragmentSizeInSectors = Volume->FragmentSizeInBytes / Volume->BytesPerSector;
|
Volume->FragmentSizeInSectors = Volume->FragmentSizeInBytes / Volume->BytesPerSector;
|
||||||
TRACE("ExtFragmentSizeInBytes: %d\n", Volume->FragmentSizeInBytes);
|
TRACE("ExtFragmentSizeInBytes: %d\n", Volume->FragmentSizeInBytes);
|
||||||
|
@ -715,12 +719,20 @@ BOOLEAN ExtReadSuperBlock(PEXT_VOLUME_INFO Volume)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the volume inode size in bytes
|
||||||
|
Volume->InodeSizeInBytes = EXT_INODE_SIZE(SuperBlock);
|
||||||
|
TRACE("InodeSizeInBytes: %d\n", Volume->InodeSizeInBytes);
|
||||||
|
|
||||||
|
// Set the volume group descriptor size in bytes
|
||||||
|
Volume->GroupDescSizeInBytes = EXT_GROUP_DESC_SIZE(SuperBlock);
|
||||||
|
TRACE("GroupDescSizeInBytes: %d\n", Volume->GroupDescSizeInBytes);
|
||||||
|
|
||||||
// Calculate the number of inodes in one block
|
// Calculate the number of inodes in one block
|
||||||
Volume->InodesPerBlock = Volume->BlockSizeInBytes / EXT_INODE_SIZE(SuperBlock);
|
Volume->InodesPerBlock = Volume->BlockSizeInBytes / Volume->InodeSizeInBytes;
|
||||||
TRACE("ExtInodesPerBlock: %d\n", Volume->InodesPerBlock);
|
TRACE("ExtInodesPerBlock: %d\n", Volume->InodesPerBlock);
|
||||||
|
|
||||||
// Calculate the number of group descriptors in one block
|
// Calculate the number of group descriptors in one block
|
||||||
Volume->GroupDescPerBlock = EXT_DESC_PER_BLOCK(SuperBlock);
|
Volume->GroupDescPerBlock = Volume->BlockSizeInBytes / Volume->GroupDescSizeInBytes;
|
||||||
TRACE("ExtGroupDescPerBlock: %d\n", Volume->GroupDescPerBlock);
|
TRACE("ExtGroupDescPerBlock: %d\n", Volume->GroupDescPerBlock);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -752,7 +764,7 @@ BOOLEAN ExtReadGroupDescriptors(PEXT_VOLUME_INFO Volume)
|
||||||
|
|
||||||
// Now read the group descriptors
|
// Now read the group descriptors
|
||||||
CurrentGroupDescBlock = (PUCHAR)Volume->GroupDescriptors;
|
CurrentGroupDescBlock = (PUCHAR)Volume->GroupDescriptors;
|
||||||
BlockNumber = Volume->SuperBlock->first_data_block + 1;
|
BlockNumber = Volume->SuperBlock->FirstDataBlock + 1;
|
||||||
|
|
||||||
while (GroupDescBlockCount--)
|
while (GroupDescBlockCount--)
|
||||||
{
|
{
|
||||||
|
@ -781,7 +793,7 @@ BOOLEAN ExtReadDirectory(PEXT_VOLUME_INFO Volume, ULONG Inode, PVOID* DirectoryB
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure it is a directory inode
|
// Make sure it is a directory inode
|
||||||
if ((InodePointer->mode & EXT_S_IFMT) != EXT_S_IFDIR)
|
if ((InodePointer->Mode & EXT_S_IFMT) != EXT_S_IFDIR)
|
||||||
{
|
{
|
||||||
FileSystemError("Inode is not a directory.");
|
FileSystemError("Inode is not a directory.");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -835,7 +847,7 @@ BOOLEAN ExtReadBlock(PEXT_VOLUME_INFO Volume, ULONG BlockNumber, PVOID Buffer)
|
||||||
TRACE("ExtReadBlock() BlockNumber = %d Buffer = 0x%x\n", BlockNumber, Buffer);
|
TRACE("ExtReadBlock() BlockNumber = %d Buffer = 0x%x\n", BlockNumber, Buffer);
|
||||||
|
|
||||||
// Make sure its a valid block
|
// Make sure its a valid block
|
||||||
if (BlockNumber > Volume->SuperBlock->total_blocks)
|
if (BlockNumber > Volume->SuperBlock->BlocksCountLo)
|
||||||
{
|
{
|
||||||
sprintf(ErrorString, "Error reading block %d - block out of range.", (int) BlockNumber);
|
sprintf(ErrorString, "Error reading block %d - block out of range.", (int) BlockNumber);
|
||||||
FileSystemError(ErrorString);
|
FileSystemError(ErrorString);
|
||||||
|
@ -880,31 +892,19 @@ BOOLEAN ExtReadPartialBlock(PEXT_VOLUME_INFO Volume, ULONG BlockNumber, ULONG St
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
ULONG ExtGetGroupDescBlockNumber(PEXT_VOLUME_INFO Volume, ULONG Group)
|
|
||||||
{
|
|
||||||
return (((Group * sizeof(EXT_GROUP_DESC)) / Volume->GroupDescPerBlock) + Volume->SuperBlock->first_data_block + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG ExtGetGroupDescOffsetInBlock(PEXT_VOLUME_INFO Volume, ULONG Group)
|
|
||||||
{
|
|
||||||
return ((Group * sizeof(EXT_GROUP_DESC)) % Volume->GroupDescPerBlock);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ULONG ExtGetInodeGroupNumber(PEXT_VOLUME_INFO Volume, ULONG Inode)
|
ULONG ExtGetInodeGroupNumber(PEXT_VOLUME_INFO Volume, ULONG Inode)
|
||||||
{
|
{
|
||||||
return ((Inode - 1) / Volume->SuperBlock->inodes_per_group);
|
return ((Inode - 1) / Volume->SuperBlock->InodesPerGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG ExtGetInodeBlockNumber(PEXT_VOLUME_INFO Volume, ULONG Inode)
|
ULONG ExtGetInodeBlockNumber(PEXT_VOLUME_INFO Volume, ULONG Inode)
|
||||||
{
|
{
|
||||||
return (((Inode - 1) % Volume->SuperBlock->inodes_per_group) / Volume->InodesPerBlock);
|
return (((Inode - 1) % Volume->SuperBlock->InodesPerGroup) / Volume->InodesPerBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG ExtGetInodeOffsetInBlock(PEXT_VOLUME_INFO Volume, ULONG Inode)
|
ULONG ExtGetInodeOffsetInBlock(PEXT_VOLUME_INFO Volume, ULONG Inode)
|
||||||
{
|
{
|
||||||
return (((Inode - 1) % Volume->SuperBlock->inodes_per_group) % Volume->InodesPerBlock);
|
return (((Inode - 1) % Volume->SuperBlock->InodesPerGroup) % Volume->InodesPerBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN ExtReadInode(PEXT_VOLUME_INFO Volume, ULONG Inode, PEXT_INODE InodeBuffer)
|
BOOLEAN ExtReadInode(PEXT_VOLUME_INFO Volume, ULONG Inode, PEXT_INODE InodeBuffer)
|
||||||
|
@ -918,7 +918,7 @@ BOOLEAN ExtReadInode(PEXT_VOLUME_INFO Volume, ULONG Inode, PEXT_INODE InodeBuffe
|
||||||
TRACE("ExtReadInode() Inode = %d\n", Inode);
|
TRACE("ExtReadInode() Inode = %d\n", Inode);
|
||||||
|
|
||||||
// Make sure its a valid inode
|
// Make sure its a valid inode
|
||||||
if ((Inode < 1) || (Inode > Volume->SuperBlock->total_inodes))
|
if ((Inode < 1) || (Inode > Volume->SuperBlock->InodesCount))
|
||||||
{
|
{
|
||||||
sprintf(ErrorString, "Error reading inode %ld - inode out of range.", Inode);
|
sprintf(ErrorString, "Error reading inode %ld - inode out of range.", Inode);
|
||||||
FileSystemError(ErrorString);
|
FileSystemError(ErrorString);
|
||||||
|
@ -940,13 +940,13 @@ BOOLEAN ExtReadInode(PEXT_VOLUME_INFO Volume, ULONG Inode, PEXT_INODE InodeBuffe
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the start block of the inode table to the inode block number
|
// Add the start block of the inode table to the inode block number
|
||||||
InodeBlockNumber += GroupDescriptor.inode_table_id;
|
InodeBlockNumber += GroupDescriptor.InodeTable;
|
||||||
TRACE("InodeBlockNumber (after group desc correction) = %d\n", InodeBlockNumber);
|
TRACE("InodeBlockNumber (after group desc correction) = %d\n", InodeBlockNumber);
|
||||||
|
|
||||||
// Read the block
|
// Read the block
|
||||||
if (!ExtReadPartialBlock(Volume,
|
if (!ExtReadPartialBlock(Volume,
|
||||||
InodeBlockNumber,
|
InodeBlockNumber,
|
||||||
(InodeOffsetInBlock * EXT_INODE_SIZE(Volume->SuperBlock)),
|
(InodeOffsetInBlock * Volume->InodeSizeInBytes),
|
||||||
sizeof(EXT_INODE),
|
sizeof(EXT_INODE),
|
||||||
InodeBuffer))
|
InodeBuffer))
|
||||||
{
|
{
|
||||||
|
@ -954,31 +954,31 @@ BOOLEAN ExtReadInode(PEXT_VOLUME_INFO Volume, ULONG Inode, PEXT_INODE InodeBuffe
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("Dumping inode information:\n");
|
TRACE("Dumping inode information:\n");
|
||||||
TRACE("mode = 0x%x\n", InodeBuffer->mode);
|
TRACE("Mode = 0x%x\n", InodeBuffer->Mode);
|
||||||
TRACE("uid = %d\n", InodeBuffer->uid);
|
TRACE("UID = %d\n", InodeBuffer->UID);
|
||||||
TRACE("size = %d\n", InodeBuffer->size);
|
TRACE("Size = %d\n", InodeBuffer->Size);
|
||||||
TRACE("atime = %d\n", InodeBuffer->atime);
|
TRACE("Atime = %d\n", InodeBuffer->Atime);
|
||||||
TRACE("ctime = %d\n", InodeBuffer->ctime);
|
TRACE("Ctime = %d\n", InodeBuffer->Ctime);
|
||||||
TRACE("mtime = %d\n", InodeBuffer->mtime);
|
TRACE("Mtime = %d\n", InodeBuffer->Mtime);
|
||||||
TRACE("dtime = %d\n", InodeBuffer->dtime);
|
TRACE("Dtime = %d\n", InodeBuffer->Dtime);
|
||||||
TRACE("gid = %d\n", InodeBuffer->gid);
|
TRACE("GID = %d\n", InodeBuffer->GID);
|
||||||
TRACE("nlinks = %d\n", InodeBuffer->nlinks);
|
TRACE("LinksCount = %d\n", InodeBuffer->LinksCount);
|
||||||
TRACE("blockcnt = %d\n", InodeBuffer->blockcnt);
|
TRACE("Blocks = %d\n", InodeBuffer->Blocks);
|
||||||
TRACE("flags = 0x%x\n", InodeBuffer->flags);
|
TRACE("Flags = 0x%x\n", InodeBuffer->Flags);
|
||||||
TRACE("osd1 = 0x%x\n", InodeBuffer->osd1);
|
TRACE("OSD1 = 0x%x\n", InodeBuffer->OSD1);
|
||||||
TRACE("dir_blocks = { %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u }\n",
|
TRACE("DirectBlocks = { %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u }\n",
|
||||||
InodeBuffer->blocks.dir_blocks[0], InodeBuffer->blocks.dir_blocks[1], InodeBuffer->blocks.dir_blocks[ 2], InodeBuffer->blocks.dir_blocks[ 3],
|
InodeBuffer->Blocks.DirectBlocks[0], InodeBuffer->Blocks.DirectBlocks[1], InodeBuffer->Blocks.DirectBlocks[2], InodeBuffer->Blocks.DirectBlocks[3],
|
||||||
InodeBuffer->blocks.dir_blocks[4], InodeBuffer->blocks.dir_blocks[5], InodeBuffer->blocks.dir_blocks[ 6], InodeBuffer->blocks.dir_blocks[ 7],
|
InodeBuffer->Blocks.DirectBlocks[4], InodeBuffer->Blocks.DirectBlocks[5], InodeBuffer->Blocks.DirectBlocks[6], InodeBuffer->Blocks.DirectBlocks[7],
|
||||||
InodeBuffer->blocks.dir_blocks[8], InodeBuffer->blocks.dir_blocks[9], InodeBuffer->blocks.dir_blocks[10], InodeBuffer->blocks.dir_blocks[11]);
|
InodeBuffer->Blocks.DirectBlocks[8], InodeBuffer->Blocks.DirectBlocks[9], InodeBuffer->Blocks.DirectBlocks[10], InodeBuffer->Blocks.DirectBlocks[11]);
|
||||||
TRACE("indir_block = %u\n", InodeBuffer->blocks.indir_block);
|
TRACE("IndirectBlock = %u\n", InodeBuffer->Blocks.IndirectBlock);
|
||||||
TRACE("double_indir_block = %u\n", InodeBuffer->blocks.double_indir_block);
|
TRACE("DoubleIndirectBlock = %u\n", InodeBuffer->Blocks.DoubleIndirectBlock);
|
||||||
TRACE("tripple_indir_block = %u\n", InodeBuffer->blocks.tripple_indir_block);
|
TRACE("TripleIndirectBlock = %u\n", InodeBuffer->Blocks.TripleIndirectBlock);
|
||||||
TRACE("version = %d\n", InodeBuffer->version);
|
TRACE("Generation = %d\n", InodeBuffer->Generation);
|
||||||
TRACE("acl = %d\n", InodeBuffer->acl);
|
TRACE("FileACL = %d\n", InodeBuffer->FileACL);
|
||||||
TRACE("dir_acl = %d\n", InodeBuffer->dir_acl);
|
TRACE("DirACL = %d\n", InodeBuffer->DirACL);
|
||||||
TRACE("fragment_addr = %d\n", InodeBuffer->fragment_addr);
|
TRACE("FragAddress = %d\n", InodeBuffer->FragAddress);
|
||||||
TRACE("osd2 = { %d, %d, %d }\n",
|
TRACE("OSD2 = { %d, %d, %d }\n",
|
||||||
InodeBuffer->osd2[0], InodeBuffer->osd2[1], InodeBuffer->osd2[2]);
|
InodeBuffer->OSD2[0], InodeBuffer->OSD2[1], InodeBuffer->OSD2[2]);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -995,15 +995,15 @@ BOOLEAN ExtReadGroupDescriptor(PEXT_VOLUME_INFO Volume, ULONG Group, PEXT_GROUP_
|
||||||
RtlCopyMemory(GroupBuffer, (PVOID)(FILESYSBUFFER + ExtGetGroupDescOffsetInBlock(Volume, Group)), sizeof(EXT_GROUP_DESC));
|
RtlCopyMemory(GroupBuffer, (PVOID)(FILESYSBUFFER + ExtGetGroupDescOffsetInBlock(Volume, Group)), sizeof(EXT_GROUP_DESC));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RtlCopyMemory(GroupBuffer, &Volume->GroupDescriptors[Group], sizeof(EXT_GROUP_DESC));
|
RtlCopyMemory(GroupBuffer, &((PUCHAR)Volume->GroupDescriptors)[Volume->GroupDescSizeInBytes * Group], sizeof(EXT_GROUP_DESC));
|
||||||
|
|
||||||
TRACE("Dumping group descriptor:\n");
|
TRACE("Dumping group descriptor:\n");
|
||||||
TRACE("block_id = %d\n", GroupBuffer->block_id);
|
TRACE("BlockBitmap = %d\n", GroupBuffer->BlockBitmap);
|
||||||
TRACE("inode_id = %d\n", GroupBuffer->inode_id);
|
TRACE("InodeBitmap = %d\n", GroupBuffer->InodeBitmap);
|
||||||
TRACE("inode_table_id = %d\n", GroupBuffer->inode_table_id);
|
TRACE("InodeTable = %d\n", GroupBuffer->InodeTable);
|
||||||
TRACE("free_blocks = %d\n", GroupBuffer->free_blocks);
|
TRACE("FreeBlocksCount = %d\n", GroupBuffer->FreeBlocksCount);
|
||||||
TRACE("free_inodes = %d\n", GroupBuffer->free_inodes);
|
TRACE("FreeInodesCount = %d\n", GroupBuffer->FreeInodesCount);
|
||||||
TRACE("used_dirs = %d\n", GroupBuffer->used_dirs);
|
TRACE("UsedDirsCount = %d\n", GroupBuffer->UsedDirsCount);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -1039,16 +1039,16 @@ ULONG* ExtReadBlockPointerList(PEXT_VOLUME_INFO Volume, PEXT_INODE Inode)
|
||||||
|
|
||||||
// Copy the direct block pointers
|
// Copy the direct block pointers
|
||||||
for (CurrentBlockInList = CurrentBlock = 0;
|
for (CurrentBlockInList = CurrentBlock = 0;
|
||||||
CurrentBlockInList < BlockCount && CurrentBlock < INDIRECT_BLOCKS;
|
CurrentBlockInList < BlockCount && CurrentBlock < sizeof(Inode->Blocks.DirectBlocks) / sizeof(*Inode->Blocks.DirectBlocks);
|
||||||
CurrentBlock++, CurrentBlockInList++)
|
CurrentBlock++, CurrentBlockInList++)
|
||||||
{
|
{
|
||||||
BlockList[CurrentBlockInList] = Inode->blocks.dir_blocks[CurrentBlock];
|
BlockList[CurrentBlockInList] = Inode->Blocks.DirectBlocks[CurrentBlock];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the indirect block pointers
|
// Copy the indirect block pointers
|
||||||
if (CurrentBlockInList < BlockCount)
|
if (CurrentBlockInList < BlockCount)
|
||||||
{
|
{
|
||||||
if (!ExtCopyIndirectBlockPointers(Volume, BlockList, &CurrentBlockInList, BlockCount, Inode->blocks.indir_block))
|
if (!ExtCopyIndirectBlockPointers(Volume, BlockList, &CurrentBlockInList, BlockCount, Inode->Blocks.IndirectBlock))
|
||||||
{
|
{
|
||||||
FrLdrTempFree(BlockList, TAG_EXT_BLOCK_LIST);
|
FrLdrTempFree(BlockList, TAG_EXT_BLOCK_LIST);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1058,7 +1058,7 @@ ULONG* ExtReadBlockPointerList(PEXT_VOLUME_INFO Volume, PEXT_INODE Inode)
|
||||||
// Copy the double indirect block pointers
|
// Copy the double indirect block pointers
|
||||||
if (CurrentBlockInList < BlockCount)
|
if (CurrentBlockInList < BlockCount)
|
||||||
{
|
{
|
||||||
if (!ExtCopyDoubleIndirectBlockPointers(Volume, BlockList, &CurrentBlockInList, BlockCount, Inode->blocks.double_indir_block))
|
if (!ExtCopyDoubleIndirectBlockPointers(Volume, BlockList, &CurrentBlockInList, BlockCount, Inode->Blocks.DoubleIndirectBlock))
|
||||||
{
|
{
|
||||||
FrLdrTempFree(BlockList, TAG_EXT_BLOCK_LIST);
|
FrLdrTempFree(BlockList, TAG_EXT_BLOCK_LIST);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1068,7 +1068,7 @@ ULONG* ExtReadBlockPointerList(PEXT_VOLUME_INFO Volume, PEXT_INODE Inode)
|
||||||
// Copy the triple indirect block pointers
|
// Copy the triple indirect block pointers
|
||||||
if (CurrentBlockInList < BlockCount)
|
if (CurrentBlockInList < BlockCount)
|
||||||
{
|
{
|
||||||
if (!ExtCopyTripleIndirectBlockPointers(Volume, BlockList, &CurrentBlockInList, BlockCount, Inode->blocks.tripple_indir_block))
|
if (!ExtCopyTripleIndirectBlockPointers(Volume, BlockList, &CurrentBlockInList, BlockCount, Inode->Blocks.TripleIndirectBlock))
|
||||||
{
|
{
|
||||||
FrLdrTempFree(BlockList, TAG_EXT_BLOCK_LIST);
|
FrLdrTempFree(BlockList, TAG_EXT_BLOCK_LIST);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1080,13 +1080,13 @@ ULONG* ExtReadBlockPointerList(PEXT_VOLUME_INFO Volume, PEXT_INODE Inode)
|
||||||
|
|
||||||
ULONGLONG ExtGetInodeFileSize(PEXT_INODE Inode)
|
ULONGLONG ExtGetInodeFileSize(PEXT_INODE Inode)
|
||||||
{
|
{
|
||||||
if ((Inode->mode & EXT_S_IFMT) == EXT_S_IFDIR)
|
if ((Inode->Mode & EXT_S_IFMT) == EXT_S_IFDIR)
|
||||||
{
|
{
|
||||||
return (ULONGLONG)(Inode->size);
|
return (ULONGLONG)(Inode->Size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return ((ULONGLONG)(Inode->size) | ((ULONGLONG)(Inode->dir_acl) << 32));
|
return ((ULONGLONG)(Inode->Size) | ((ULONGLONG)(Inode->DirACL) << 32));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1227,7 +1227,7 @@ ARC_STATUS ExtOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
|
||||||
DeviceId = FsGetDeviceId(*FileId);
|
DeviceId = FsGetDeviceId(*FileId);
|
||||||
Volume = ExtVolumes[DeviceId];
|
Volume = ExtVolumes[DeviceId];
|
||||||
|
|
||||||
TRACE("ExtOpen() FileName = %s\n", Path);
|
TRACE("ExtOpen() FileName = \"%s\"\n", Path);
|
||||||
|
|
||||||
/* Call the internal open method */
|
/* Call the internal open method */
|
||||||
// Status = ExtOpenFile(Volume, Path, &FileHandle);
|
// Status = ExtOpenFile(Volume, Path, &FileHandle);
|
||||||
|
@ -1327,7 +1327,7 @@ const DEVVTBL* ExtMount(ULONG DeviceId)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if SuperBlock is valid. If yes, return Ext function table. */
|
/* Check if SuperBlock is valid. If yes, return Ext function table. */
|
||||||
if (SuperBlock.magic != EXT_MAGIC)
|
if (SuperBlock.Magic != EXT_SUPERBLOCK_MAGIC)
|
||||||
{
|
{
|
||||||
FrLdrTempFree(Volume, TAG_EXT_VOLUME);
|
FrLdrTempFree(Volume, TAG_EXT_VOLUME);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1350,4 +1350,4 @@ const DEVVTBL* ExtMount(ULONG DeviceId)
|
||||||
return &ExtFuncTable;
|
return &ExtFuncTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif // _M_ARM
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue