Beginnings of ext2fs driver

svn path=/trunk/; revision=141
This commit is contained in:
David Welch 1999-01-01 21:39:43 +00:00
parent 3244132cc7
commit de8fc633f8
8 changed files with 969 additions and 0 deletions

View 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,
&sectorNumber,
&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,
&sectorNumber,
&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;
}

View 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);
}

View 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);

View 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(;;);
}

View 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);
}

View 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

View 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);
}

View 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);
}