diff --git a/reactos/drivers/fs/ext2/blockdev.c b/reactos/drivers/fs/ext2/blockdev.c new file mode 100644 index 00000000000..50e9492f0cb --- /dev/null +++ b/reactos/drivers/fs/ext2/blockdev.c @@ -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 +#include + +#define NDEBUG +#include + +#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; +} + + diff --git a/reactos/drivers/fs/ext2/dir.c b/reactos/drivers/fs/ext2/dir.c new file mode 100644 index 00000000000..22384bd3caa --- /dev/null +++ b/reactos/drivers/fs/ext2/dir.c @@ -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 +#include +#include + +//#define NDEBUG +#include + +#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); +} diff --git a/reactos/drivers/fs/ext2/ext2fs.h b/reactos/drivers/fs/ext2/ext2fs.h new file mode 100644 index 00000000000..4e310a6ed6f --- /dev/null +++ b/reactos/drivers/fs/ext2/ext2fs.h @@ -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); + diff --git a/reactos/drivers/fs/ext2/file.c b/reactos/drivers/fs/ext2/file.c new file mode 100644 index 00000000000..0d6e0a9b399 --- /dev/null +++ b/reactos/drivers/fs/ext2/file.c @@ -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 +#include +#include + +#define NDEBUG +#include + +#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(;;); +} diff --git a/reactos/drivers/fs/ext2/inode.c b/reactos/drivers/fs/ext2/inode.c new file mode 100644 index 00000000000..77942d5344c --- /dev/null +++ b/reactos/drivers/fs/ext2/inode.c @@ -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 +#include +#include + +#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); +} diff --git a/reactos/drivers/fs/ext2/makefile b/reactos/drivers/fs/ext2/makefile new file mode 100644 index 00000000000..a6019785da6 --- /dev/null +++ b/reactos/drivers/fs/ext2/makefile @@ -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 diff --git a/reactos/drivers/fs/ext2/rw.c b/reactos/drivers/fs/ext2/rw.c new file mode 100644 index 00000000000..51659963f03 --- /dev/null +++ b/reactos/drivers/fs/ext2/rw.c @@ -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 +#include +#include + +#define NDEBUG +#include + +#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); +} diff --git a/reactos/drivers/fs/ext2/super.c b/reactos/drivers/fs/ext2/super.c new file mode 100644 index 00000000000..1cfef69a752 --- /dev/null +++ b/reactos/drivers/fs/ext2/super.c @@ -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 +#include +#include + +#define NDEBUG +#include + +#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); +} +