mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
Beginnings of ext2fs driver
svn path=/trunk/; revision=141
This commit is contained in:
parent
3244132cc7
commit
de8fc633f8
8 changed files with 969 additions and 0 deletions
154
reactos/drivers/fs/ext2/blockdev.c
Normal file
154
reactos/drivers/fs/ext2/blockdev.c
Normal file
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/vfat/blockdev.c
|
||||
* PURPOSE: Temporary sector reading support
|
||||
* PROGRAMMER: David Welch (welch@mcmail.com)
|
||||
* UPDATE HISTORY:
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <internal/string.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#include "ext2fs.h"
|
||||
|
||||
/* FUNCTIONS ***************************************************************/
|
||||
|
||||
BOOLEAN Ext2ReadSectors(IN PDEVICE_OBJECT pDeviceObject,
|
||||
IN ULONG DiskSector,
|
||||
IN ULONG SectorCount,
|
||||
IN PVOID Buffer)
|
||||
{
|
||||
LARGE_INTEGER sectorNumber;
|
||||
PIRP irp;
|
||||
IO_STATUS_BLOCK ioStatus;
|
||||
KEVENT event;
|
||||
NTSTATUS status;
|
||||
ULONG sectorSize;
|
||||
int j;
|
||||
|
||||
DPRINT("VFATReadSector(pDeviceObject %x, DiskSector %d, Buffer %x)\n",
|
||||
pDeviceObject,DiskSector,Buffer);
|
||||
|
||||
SET_LARGE_INTEGER_HIGH_PART(sectorNumber, 0);
|
||||
SET_LARGE_INTEGER_LOW_PART(sectorNumber, DiskSector * BLOCKSIZE);
|
||||
|
||||
DPRINT("DiskSector:%ld BLKSZ:%ld sectorNumber:%ld:%ld\n",
|
||||
(unsigned long) DiskSector,
|
||||
(unsigned long) BLOCKSIZE,
|
||||
(unsigned long) GET_LARGE_INTEGER_HIGH_PART(sectorNumber),
|
||||
(unsigned long) GET_LARGE_INTEGER_LOW_PART(sectorNumber));
|
||||
|
||||
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
||||
|
||||
sectorSize = BLOCKSIZE*SectorCount;
|
||||
|
||||
|
||||
DPRINT("Building synchronous FSD Request...\n");
|
||||
irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
|
||||
pDeviceObject,
|
||||
Buffer,
|
||||
sectorSize,
|
||||
§orNumber,
|
||||
&event,
|
||||
&ioStatus );
|
||||
|
||||
if (!irp) {
|
||||
DbgPrint("READ failed!!!\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DPRINT("Calling IO Driver...\n");
|
||||
status = IoCallDriver(pDeviceObject,
|
||||
irp);
|
||||
|
||||
DPRINT("Waiting for IO Operation...\n");
|
||||
if (status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(&event,
|
||||
Suspended,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
DPRINT("Getting IO Status...\n");
|
||||
status = ioStatus.Status;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DbgPrint("IO failed!!! Error code: %d(%x)\n", status, status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN VFATWriteSectors(IN PDEVICE_OBJECT pDeviceObject,
|
||||
IN ULONG DiskSector,
|
||||
IN ULONG SectorCount,
|
||||
IN UCHAR* Buffer)
|
||||
{
|
||||
LARGE_INTEGER sectorNumber;
|
||||
PIRP irp;
|
||||
IO_STATUS_BLOCK ioStatus;
|
||||
KEVENT event;
|
||||
NTSTATUS status;
|
||||
ULONG sectorSize;
|
||||
PULONG mbr;
|
||||
int j;
|
||||
|
||||
DPRINT("VFATWriteSector(pDeviceObject %x, DiskSector %d, Buffer %x)\n",
|
||||
pDeviceObject,DiskSector,Buffer);
|
||||
|
||||
SET_LARGE_INTEGER_HIGH_PART(sectorNumber, 0);
|
||||
SET_LARGE_INTEGER_LOW_PART(sectorNumber, DiskSector * BLOCKSIZE);
|
||||
|
||||
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
||||
|
||||
sectorSize = BLOCKSIZE*SectorCount;
|
||||
|
||||
|
||||
DPRINT("Building synchronous FSD Request...\n");
|
||||
irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
|
||||
pDeviceObject,
|
||||
Buffer,
|
||||
sectorSize,
|
||||
§orNumber,
|
||||
&event,
|
||||
&ioStatus );
|
||||
|
||||
if (!irp) {
|
||||
DbgPrint("WRITE failed!!!\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DPRINT("Calling IO Driver...\n");
|
||||
status = IoCallDriver(pDeviceObject,
|
||||
irp);
|
||||
|
||||
DPRINT("Waiting for IO Operation...\n");
|
||||
if (status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(&event,
|
||||
Suspended,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
DPRINT("Getting IO Status...\n");
|
||||
status = ioStatus.Status;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DbgPrint("IO failed!!! Error code: %d(%x)\n", status, status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
ExFreePool(mbr);
|
||||
DPRINT("Block request succeeded\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
151
reactos/drivers/fs/ext2/dir.c
Normal file
151
reactos/drivers/fs/ext2/dir.c
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/ext2/super.c
|
||||
* PURPOSE: ext2 filesystem
|
||||
* PROGRAMMER: David Welch (welch@mcmail.com)
|
||||
* UPDATE HISTORY:
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <internal/string.h>
|
||||
#include <wstring.h>
|
||||
|
||||
//#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#include "ext2fs.h"
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
BOOL Ext2ScanDir(PDEVICE_EXTENSION DeviceExt,
|
||||
struct ext2_inode* dir,
|
||||
PCH filename,
|
||||
struct ext2_dir_entry* ret)
|
||||
{
|
||||
ULONG i;
|
||||
char* buffer;
|
||||
ULONG offset;
|
||||
char name[255];
|
||||
struct ext2_dir_entry* current;
|
||||
ULONG block;
|
||||
|
||||
DPRINT("Ext2ScanDir(dir %x, filename %s, ret %x)\n",dir,filename,ret);
|
||||
|
||||
buffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
|
||||
|
||||
for (i=0; (block = Ext2BlockMap(DeviceExt, dir, i)) != 0; i++)
|
||||
{
|
||||
DPRINT("block %d\n",block);
|
||||
Ext2ReadSectors(DeviceExt->StorageDevice,
|
||||
block,
|
||||
1,
|
||||
buffer);
|
||||
|
||||
offset = 0;
|
||||
while (offset < BLOCKSIZE)
|
||||
{
|
||||
current = &buffer[offset];
|
||||
|
||||
strncpy(name,current->name,current->name_len);
|
||||
name[current->name_len]=0;
|
||||
|
||||
DPRINT("Scanning offset %d inode %d name %s\n",
|
||||
offset,current->inode,name);
|
||||
|
||||
DPRINT("Comparing %s %s\n",name,filename);
|
||||
if (strcmp(name,filename)==0)
|
||||
{
|
||||
DPRINT("Match found\n");
|
||||
memcpy(ret,current,sizeof(struct ext2_dir_entry));
|
||||
ExFreePool(buffer);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
offset = offset + current->rec_len;
|
||||
assert(current->rec_len != 0);
|
||||
DPRINT("offset %d\n",offset);
|
||||
}
|
||||
DPRINT("Onto next block\n");
|
||||
}
|
||||
DPRINT("No match\n");
|
||||
ExFreePool(buffer);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
void unicode_to_ansi(PCH StringA, PWSTR StringW)
|
||||
{
|
||||
while((*StringW)!=0)
|
||||
{
|
||||
*StringA = *StringW;
|
||||
StringA++;
|
||||
StringW++;
|
||||
}
|
||||
*StringA = 0;
|
||||
}
|
||||
|
||||
NTSTATUS Ext2OpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||
PWSTR FileName)
|
||||
/*
|
||||
* FUNCTION: Opens a file
|
||||
*/
|
||||
{
|
||||
struct ext2_inode parent_inode;
|
||||
struct ext2_dir_entry entry;
|
||||
char name[255];
|
||||
ULONG current_inode = 2;
|
||||
char* current_segment;
|
||||
PEXT2_FCB Fcb;
|
||||
|
||||
DPRINT("Ext2OpenFile(DeviceExt %x, FileObject %x, FileName %w)\n",
|
||||
DeviceExt,FileObject,FileName);
|
||||
|
||||
Fcb = ExAllocatePool(NonPagedPool, sizeof(EXT2_FCB));
|
||||
|
||||
unicode_to_ansi(name,FileName);
|
||||
DbgPrint("name %s\n",name);
|
||||
|
||||
current_segment = strtok(name,"\\");
|
||||
do
|
||||
{
|
||||
Ext2ReadInode(DeviceExt,
|
||||
current_inode,
|
||||
&parent_inode);
|
||||
if (!Ext2ScanDir(DeviceExt,&parent_inode,current_segment,&entry))
|
||||
{
|
||||
ExFreePool(Fcb);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
current_inode = entry.inode;
|
||||
current_segment = strtok(NULL,"\\");
|
||||
} while(current_segment!=NULL);
|
||||
DPRINT("Found file\n");
|
||||
|
||||
Ext2ReadInode(DeviceExt,
|
||||
current_inode,
|
||||
&Fcb->inode);
|
||||
FileObject->FsContext = Fcb;
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS Ext2Create(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
PFILE_OBJECT FileObject = Stack->FileObject;
|
||||
NTSTATUS Status;
|
||||
PDEVICE_EXTENSION DeviceExt;
|
||||
|
||||
DPRINT("Ext2Create(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
|
||||
|
||||
DeviceExt = DeviceObject->DeviceExtension;
|
||||
Status = Ext2OpenFile(DeviceExt,FileObject,FileObject->FileName.Buffer);
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return(Status);
|
||||
}
|
242
reactos/drivers/fs/ext2/ext2fs.h
Normal file
242
reactos/drivers/fs/ext2/ext2fs.h
Normal file
|
@ -0,0 +1,242 @@
|
|||
BOOLEAN Ext2ReadSectors(IN PDEVICE_OBJECT pDeviceObject,
|
||||
IN ULONG DiskSector,
|
||||
IN ULONG SectorCount,
|
||||
IN PVOID Buffer);
|
||||
|
||||
#define BLOCKSIZE (1024)
|
||||
|
||||
struct ext2_super_block {
|
||||
ULONG s_inodes_count; /* Inodes count */
|
||||
ULONG s_blocks_count; /* Blocks count */
|
||||
ULONG s_r_blocks_count; /* Reserved blocks count */
|
||||
ULONG s_free_blocks_count; /* Free blocks count */
|
||||
ULONG s_free_inodes_count; /* Free inodes count */
|
||||
ULONG s_first_data_block; /* First Data Block */
|
||||
ULONG s_log_block_size; /* Block size */
|
||||
LONG s_log_frag_size; /* Fragment size */
|
||||
ULONG s_blocks_per_group; /* # Blocks per group */
|
||||
ULONG s_frags_per_group; /* # Fragments per group */
|
||||
ULONG s_inodes_per_group; /* # Inodes per group */
|
||||
ULONG s_mtime; /* Mount time */
|
||||
ULONG s_wtime; /* Write time */
|
||||
USHORT s_mnt_count; /* Mount count */
|
||||
SHORT s_max_mnt_count; /* Maximal mount count */
|
||||
USHORT s_magic; /* Magic signature */
|
||||
USHORT s_state; /* File system state */
|
||||
USHORT s_errors; /* Behaviour when detecting errors */
|
||||
USHORT s_minor_rev_level; /* minor revision level */
|
||||
ULONG s_lastcheck; /* time of last check */
|
||||
ULONG s_checkinterval; /* max. time between checks */
|
||||
ULONG s_creator_os; /* OS */
|
||||
ULONG s_rev_level; /* Revision level */
|
||||
USHORT s_def_resuid; /* Default uid for reserved blocks */
|
||||
USHORT 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...
|
||||
*/
|
||||
ULONG s_first_ino; /* First non-reserved inode */
|
||||
USHORT s_inode_size; /* size of inode structure */
|
||||
USHORT s_block_group_nr; /* block group # of this superblock */
|
||||
ULONG s_feature_compat; /* compatible feature set */
|
||||
ULONG s_feature_incompat; /* incompatible feature set */
|
||||
ULONG s_feature_ro_compat; /* readonly-compatible feature set */
|
||||
ULONG s_reserved[230]; /* Padding to the end of the block */
|
||||
};
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
/*
|
||||
* The second extended file system magic number
|
||||
*/
|
||||
#define EXT2_SUPER_MAGIC 0xEF53
|
||||
|
||||
/*
|
||||
* 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)
|
||||
|
||||
|
||||
/*
|
||||
* Structure of an inode on the disk
|
||||
*/
|
||||
struct ext2_inode {
|
||||
USHORT i_mode; /* File mode */
|
||||
USHORT i_uid; /* Owner Uid */
|
||||
ULONG i_size; /* Size in bytes */
|
||||
ULONG i_atime; /* Access time */
|
||||
ULONG i_ctime; /* Creation time */
|
||||
ULONG i_mtime; /* Modification time */
|
||||
ULONG i_dtime; /* Deletion Time */
|
||||
USHORT i_gid; /* Group Id */
|
||||
USHORT i_links_count; /* Links count */
|
||||
ULONG i_blocks; /* Blocks count */
|
||||
ULONG i_flags; /* File flags */
|
||||
union {
|
||||
struct {
|
||||
ULONG l_i_reserved1;
|
||||
} linux1;
|
||||
struct {
|
||||
ULONG h_i_translator;
|
||||
} hurd1;
|
||||
struct {
|
||||
ULONG m_i_reserved1;
|
||||
} masix1;
|
||||
} osd1; /* OS dependent 1 */
|
||||
ULONG i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
|
||||
ULONG i_version; /* File version (for NFS) */
|
||||
ULONG i_file_acl; /* File ACL */
|
||||
ULONG i_dir_acl; /* Directory ACL */
|
||||
ULONG i_faddr; /* Fragment address */
|
||||
union {
|
||||
struct {
|
||||
UCHAR l_i_frag; /* Fragment number */
|
||||
UCHAR l_i_fsize; /* Fragment size */
|
||||
USHORT i_pad1;
|
||||
ULONG l_i_reserved2[2];
|
||||
} linux2;
|
||||
struct {
|
||||
UCHAR h_i_frag; /* Fragment number */
|
||||
UCHAR h_i_fsize; /* Fragment size */
|
||||
USHORT h_i_mode_high;
|
||||
USHORT h_i_uid_high;
|
||||
USHORT h_i_gid_high;
|
||||
ULONG h_i_author;
|
||||
} hurd2;
|
||||
struct {
|
||||
UCHAR m_i_frag; /* Fragment number */
|
||||
UCHAR m_i_fsize; /* Fragment size */
|
||||
USHORT m_pad1;
|
||||
ULONG m_i_reserved2[2];
|
||||
} masix2;
|
||||
} osd2; /* OS dependent 2 */
|
||||
};
|
||||
|
||||
#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_reserved2 osd2.linux2.l_i_reserved2
|
||||
#endif
|
||||
|
||||
#ifdef __hurd__
|
||||
#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
|
||||
#endif
|
||||
|
||||
#ifdef __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
|
||||
|
||||
/*
|
||||
* 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_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
|
||||
|
||||
|
||||
/*
|
||||
* Structure of a blocks group descriptor
|
||||
*/
|
||||
struct ext2_group_desc
|
||||
{
|
||||
ULONG bg_block_bitmap; /* Blocks bitmap block */
|
||||
ULONG bg_inode_bitmap; /* Inodes bitmap block */
|
||||
ULONG bg_inode_table; /* Inodes table block */
|
||||
USHORT bg_free_blocks_count; /* Free blocks count */
|
||||
USHORT bg_free_inodes_count; /* Free inodes count */
|
||||
USHORT bg_used_dirs_count; /* Directories count */
|
||||
USHORT bg_pad;
|
||||
ULONG bg_reserved[3];
|
||||
};
|
||||
|
||||
#define EXT2_NAME_LEN 255
|
||||
|
||||
struct ext2_dir_entry {
|
||||
ULONG inode; /* Inode number */
|
||||
USHORT rec_len; /* Directory entry length */
|
||||
USHORT name_len; /* Name length */
|
||||
char name[EXT2_NAME_LEN]; /* File name */
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PDEVICE_OBJECT StorageDevice;
|
||||
struct ext2_super_block* superblock;
|
||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
||||
|
||||
|
||||
VOID Ext2ReadInode(PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG ino,
|
||||
struct ext2_inode* inode);
|
||||
struct ext2_group_desc* Ext2LoadGroupDesc(PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG block_group);
|
||||
|
||||
typedef struct _EXT2_FCB
|
||||
{
|
||||
struct ext2_inode inode;
|
||||
} EXT2_FCB, *PEXT2_FCB;
|
||||
|
||||
ULONG Ext2BlockMap(PDEVICE_EXTENSION DeviceExt,
|
||||
struct ext2_inode* inode,
|
||||
ULONG offset);
|
||||
NTSTATUS Ext2OpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||
PWSTR FileName);
|
||||
NTSTATUS Ext2ReadFile(PDEVICE_EXTENSION DeviceExt,
|
||||
PFILE_OBJECT FileObject,
|
||||
PVOID Buffer,
|
||||
ULONG Length,
|
||||
LARGE_INTEGER Offset);
|
||||
NTSTATUS Ext2Create(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
||||
|
55
reactos/drivers/fs/ext2/file.c
Normal file
55
reactos/drivers/fs/ext2/file.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/ext2/super.c
|
||||
* PURPOSE: ext2 filesystem
|
||||
* PROGRAMMER: David Welch (welch@mcmail.com)
|
||||
* UPDATE HISTORY:
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <internal/string.h>
|
||||
#include <wstring.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#include "ext2fs.h"
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
#define addr_per_block (BLOCKSIZE / sizeof(ULONG))
|
||||
|
||||
ULONG Ext2BlockMap(PDEVICE_EXTENSION DeviceExt,
|
||||
struct ext2_inode* inode,
|
||||
ULONG offset)
|
||||
{
|
||||
ULONG block;
|
||||
PULONG TempBuffer;
|
||||
|
||||
DPRINT("Ext2BlockMap(DeviceExt %x, inode %x, offset %d)\n",
|
||||
DeviceExt,inode,offset);
|
||||
if (offset < EXT2_NDIR_BLOCKS)
|
||||
{
|
||||
block = inode->i_block[offset];
|
||||
DPRINT("block %d\n",block);
|
||||
return(block);
|
||||
}
|
||||
offset = offset - EXT2_NDIR_BLOCKS;
|
||||
if (offset < addr_per_block)
|
||||
{
|
||||
block = inode->i_block[EXT2_IND_BLOCK];
|
||||
TempBuffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
|
||||
Ext2ReadSectors(DeviceExt->StorageDevice,
|
||||
block,
|
||||
1,
|
||||
TempBuffer);
|
||||
block = TempBuffer[offset];
|
||||
ExFreePool(TempBuffer);
|
||||
return(block);
|
||||
}
|
||||
DbgPrint("Failed at %s:%d\n",__FILE__,__LINE__);
|
||||
for(;;);
|
||||
}
|
78
reactos/drivers/fs/ext2/inode.c
Normal file
78
reactos/drivers/fs/ext2/inode.c
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/ext2/inode.c
|
||||
* PURPOSE: Manipulating inodes
|
||||
* PROGRAMMER: David Welch (welch@cwcom.net)
|
||||
* UPDATE HISTORY:
|
||||
* 26/12/98: Created
|
||||
*/
|
||||
|
||||
/* INCLUDES ****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <internal/debug.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ext2fs.h"
|
||||
|
||||
/* FUNCTIONS ***************************************************************/
|
||||
|
||||
struct ext2_group_desc* Ext2LoadGroupDesc(PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG block_group)
|
||||
{
|
||||
struct ext2_group_desc* buffer;
|
||||
ULONG block;
|
||||
struct ext2_group_desc* gdp;
|
||||
|
||||
buffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
|
||||
|
||||
block = block_group / (BLOCKSIZE / sizeof(struct ext2_group_desc));
|
||||
|
||||
Ext2ReadSectors(DeviceExt->StorageDevice,
|
||||
2 + block,
|
||||
1,
|
||||
buffer);
|
||||
|
||||
gdp = &buffer[block_group % (BLOCKSIZE / sizeof(struct ext2_group_desc))];
|
||||
|
||||
DPRINT("gdp->bg_free_blocks_count %d\n",gdp->bg_free_blocks_count);
|
||||
DPRINT("gdp->bg_inode_table %d\n",gdp->bg_inode_table);
|
||||
|
||||
return(gdp);
|
||||
|
||||
}
|
||||
|
||||
#define INODES_PER_BLOCK (BLOCKSIZE / sizeof(struct ext2_inode))
|
||||
|
||||
VOID Ext2ReadInode(PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG ino,
|
||||
struct ext2_inode* inode)
|
||||
{
|
||||
ULONG block_group;
|
||||
struct ext2_group_desc* gdp;
|
||||
ULONG offset;
|
||||
struct ext2_inode* buffer;
|
||||
|
||||
DPRINT("Ext2ReadInode(DeviceExt %x, ino %d, inode %x)\n",
|
||||
DeviceExt,ino,inode);
|
||||
|
||||
block_group = (ino - 1) / DeviceExt->superblock->s_inodes_per_group;
|
||||
|
||||
gdp = Ext2LoadGroupDesc(DeviceExt, block_group);
|
||||
|
||||
|
||||
|
||||
offset = (ino - 1) % DeviceExt->superblock->s_inodes_per_group;
|
||||
|
||||
buffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
|
||||
Ext2ReadSectors(DeviceExt->StorageDevice,
|
||||
gdp->bg_inode_table + (offset / INODES_PER_BLOCK),
|
||||
1,
|
||||
buffer);
|
||||
memcpy(inode,&buffer[offset % INODES_PER_BLOCK],sizeof(struct ext2_inode));
|
||||
|
||||
DPRINT("inode->i_uid %d\n",inode->i_uid);
|
||||
DPRINT("inode->i_links_count %d\n",inode->i_links_count);
|
||||
DPRINT("inode->i_blocks %d\n",inode->i_blocks);
|
||||
}
|
4
reactos/drivers/fs/ext2/makefile
Normal file
4
reactos/drivers/fs/ext2/makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
OBJECTS = super.o blockdev.o inode.o file.o dir.o rw.o
|
||||
|
||||
all: $(OBJECTS)
|
||||
$(LD) -r $(OBJECTS) -o ext2fs.sys
|
96
reactos/drivers/fs/ext2/rw.c
Normal file
96
reactos/drivers/fs/ext2/rw.c
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/ext2/super.c
|
||||
* PURPOSE: ext2 filesystem
|
||||
* PROGRAMMER: David Welch (welch@mcmail.com)
|
||||
* UPDATE HISTORY:
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <internal/string.h>
|
||||
#include <wstring.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#include "ext2fs.h"
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS Ext2ReadFile(PDEVICE_EXTENSION DeviceExt,
|
||||
PFILE_OBJECT FileObject,
|
||||
PVOID Buffer,
|
||||
ULONG Length,
|
||||
LARGE_INTEGER OffsetL)
|
||||
/*
|
||||
* FUNCTION: Reads data from a file
|
||||
*/
|
||||
{
|
||||
PEXT2_FCB Fcb;
|
||||
PVOID TempBuffer;
|
||||
ULONG Offset = OffsetL;
|
||||
ULONG block;
|
||||
ULONG Delta;
|
||||
ULONG i;
|
||||
|
||||
DPRINT("Ext2ReadFile(DeviceExt %x, FileObject %x, Buffer %x, Length %d, \n"
|
||||
"OffsetL %d)\n",DeviceExt,FileObject,Buffer,Length,(ULONG)OffsetL);
|
||||
|
||||
Fcb = (PEXT2_FCB)FileObject->FsContext;
|
||||
TempBuffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
|
||||
|
||||
if (Offset >= Fcb->inode.i_size)
|
||||
{
|
||||
ExFreePool(TempBuffer);
|
||||
return(STATUS_END_OF_FILE);
|
||||
}
|
||||
if ((Offset + Length) > Fcb->inode.i_size)
|
||||
{
|
||||
Length = Fcb->inode.i_size - Offset;
|
||||
}
|
||||
|
||||
CHECKPOINT;
|
||||
if ((Offset % BLOCKSIZE) != 0)
|
||||
{
|
||||
block = Ext2BlockMap(DeviceExt, &Fcb->inode, Offset / BLOCKSIZE);
|
||||
Delta = min(BLOCKSIZE - (Offset % BLOCKSIZE),Length);
|
||||
Ext2ReadSectors(DeviceExt->StorageDevice,
|
||||
block,
|
||||
1,
|
||||
TempBuffer);
|
||||
memcpy(Buffer, TempBuffer + (Offset % BLOCKSIZE), Delta);
|
||||
Length = Length - Delta;
|
||||
Offset = Offset + Delta;
|
||||
Buffer = Buffer + Delta;
|
||||
}
|
||||
CHECKPOINT;
|
||||
for (i=0; i<(Length/BLOCKSIZE); i++)
|
||||
{
|
||||
block = Ext2BlockMap(DeviceExt, &Fcb->inode,
|
||||
(Offset / BLOCKSIZE)+i);
|
||||
Ext2ReadSectors(DeviceExt->StorageDevice,
|
||||
block,
|
||||
1,
|
||||
Buffer);
|
||||
Length = Length - BLOCKSIZE;
|
||||
Offset = Offset + BLOCKSIZE;
|
||||
Buffer = Buffer + BLOCKSIZE;
|
||||
}
|
||||
CHECKPOINT;
|
||||
if ((Length % BLOCKSIZE) != 0)
|
||||
{
|
||||
block = Ext2BlockMap(DeviceExt, &Fcb->inode, Offset / BLOCKSIZE);
|
||||
Ext2ReadSectors(DeviceExt->StorageDevice,
|
||||
block,
|
||||
1,
|
||||
TempBuffer);
|
||||
memcpy(Buffer,TempBuffer,Length);
|
||||
}
|
||||
|
||||
ExFreePool(TempBuffer);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
189
reactos/drivers/fs/ext2/super.c
Normal file
189
reactos/drivers/fs/ext2/super.c
Normal file
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/ext2/super.c
|
||||
* PURPOSE: ext2 filesystem
|
||||
* PROGRAMMER: David Welch (welch@mcmail.com)
|
||||
* UPDATE HISTORY:
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <internal/string.h>
|
||||
#include <wstring.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#include "ext2fs.h"
|
||||
|
||||
/* GLOBALS *****************************************************************/
|
||||
|
||||
static PDRIVER_OBJECT DriverObject;
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
NTSTATUS Ext2CloseFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject)
|
||||
/*
|
||||
* FUNCTION: Closes a file
|
||||
*/
|
||||
{
|
||||
}
|
||||
|
||||
NTSTATUS Ext2Close(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
PFILE_OBJECT FileObject = Stack->FileObject;
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = Ext2CloseFile(DeviceExtension,FileObject);
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
NTSTATUS Ext2Write(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
DPRINT("FsdWrite(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
|
||||
|
||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||
Irp->IoStatus.Information = 0;
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
NTSTATUS Ext2Read(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
ULONG Length;
|
||||
PVOID Buffer;
|
||||
ULONG Offset;
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
PFILE_OBJECT FileObject = Stack->FileObject;
|
||||
PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("FsdRead(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
|
||||
|
||||
Length = Stack->Parameters.Read.Length;
|
||||
Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
|
||||
Offset = Stack->Parameters.Read.ByteOffset;
|
||||
|
||||
Status = Ext2ReadFile(DeviceExt,FileObject,Buffer,Length,Offset);
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = Length;
|
||||
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
||||
|
||||
return(Status);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS Ext2Mount(PDEVICE_OBJECT DeviceToMount)
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PDEVICE_EXTENSION DeviceExt;
|
||||
PVOID BlockBuffer;
|
||||
struct ext2_super_block* superblock;
|
||||
|
||||
DPRINT("Ext2Mount(DeviceToMount %x)\n",DeviceToMount);
|
||||
|
||||
BlockBuffer = ExAllocatePool(NonPagedPool,BLOCKSIZE);
|
||||
Ext2ReadSectors(DeviceToMount,
|
||||
1,
|
||||
1,
|
||||
BlockBuffer);
|
||||
superblock = BlockBuffer;
|
||||
|
||||
if (superblock->s_magic != EXT2_SUPER_MAGIC)
|
||||
{
|
||||
ExFreePool(BlockBuffer);
|
||||
return(STATUS_UNRECOGNIZED_VOLUME);
|
||||
}
|
||||
DPRINT("Volume recognized\n");
|
||||
DPRINT("s_inodes_count %d\n",superblock->s_inodes_count);
|
||||
DPRINT("s_blocks_count %d\n",superblock->s_blocks_count);
|
||||
|
||||
IoCreateDevice(DriverObject,
|
||||
sizeof(DEVICE_EXTENSION),
|
||||
NULL,
|
||||
FILE_DEVICE_FILE_SYSTEM,
|
||||
0,
|
||||
FALSE,
|
||||
&DeviceObject);
|
||||
DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
|
||||
DeviceExt = (PVOID)DeviceObject->DeviceExtension;
|
||||
|
||||
DeviceExt->StorageDevice = IoAttachDeviceToDeviceStack(DeviceObject,
|
||||
DeviceToMount);
|
||||
DeviceExt->superblock = superblock;
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS Ext2FileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
PVPB vpb = Stack->Parameters.Mount.Vpb;
|
||||
PDEVICE_OBJECT DeviceToMount = Stack->Parameters.Mount.DeviceObject;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = Ext2Mount(DeviceToMount);
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
NTSTATUS DriverEntry(PDRIVER_OBJECT _DriverObject,
|
||||
PUNICODE_STRING RegistryPath)
|
||||
/*
|
||||
* FUNCTION: Called by the system to initalize the driver
|
||||
* ARGUMENTS:
|
||||
* DriverObject = object describing this driver
|
||||
* RegistryPath = path to our configuration entries
|
||||
* RETURNS: Success or failure
|
||||
*/
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
NTSTATUS ret;
|
||||
UNICODE_STRING DeviceNameU;
|
||||
ANSI_STRING DeviceNameA;
|
||||
|
||||
DbgPrint("Ext2 FSD 0.0.1\n");
|
||||
|
||||
DriverObject = _DriverObject;
|
||||
|
||||
RtlInitAnsiString(&DeviceNameA,"\\Device\\Ext2Fsd");
|
||||
RtlAnsiStringToUnicodeString(&DeviceNameU,&DeviceNameA,TRUE);
|
||||
ret = IoCreateDevice(DriverObject,
|
||||
0,
|
||||
&DeviceNameU,
|
||||
FILE_DEVICE_FILE_SYSTEM,
|
||||
0,
|
||||
FALSE,
|
||||
&DeviceObject);
|
||||
if (ret!=STATUS_SUCCESS)
|
||||
{
|
||||
return(ret);
|
||||
}
|
||||
|
||||
DeviceObject->Flags=0;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = Ext2Close;
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = Ext2Create;
|
||||
DriverObject->MajorFunction[IRP_MJ_READ] = Ext2Read;
|
||||
DriverObject->MajorFunction[IRP_MJ_WRITE] = Ext2Write;
|
||||
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
|
||||
Ext2FileSystemControl;
|
||||
DriverObject->DriverUnload = NULL;
|
||||
|
||||
IoRegisterFileSystem(DeviceObject);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
Loading…
Reference in a new issue