From a1a1d0917e2453ca8a355ce893fab85c43fdf143 Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Thu, 26 May 2016 18:17:19 +0000 Subject: [PATCH] [FS_REC] Add support for ReiserFS volumes. Patch by Peter Hater. This is done for ReiserFS support! Enjoy :-) CORE-11005 #resolve svn path=/trunk/; revision=71417 --- .../drivers/filesystems/fs_rec/CMakeLists.txt | 1 + reactos/drivers/filesystems/fs_rec/fs_rec.c | 16 +++ reactos/drivers/filesystems/fs_rec/fs_rec.h | 8 ++ reactos/drivers/filesystems/fs_rec/reiserfs.c | 122 ++++++++++++++++++ reactos/drivers/filesystems/fs_rec/reiserfs.h | 76 +++++++++++ 5 files changed, 223 insertions(+) create mode 100644 reactos/drivers/filesystems/fs_rec/reiserfs.c create mode 100644 reactos/drivers/filesystems/fs_rec/reiserfs.h diff --git a/reactos/drivers/filesystems/fs_rec/CMakeLists.txt b/reactos/drivers/filesystems/fs_rec/CMakeLists.txt index 4901c8b8ee0..4e2bfa51db5 100644 --- a/reactos/drivers/filesystems/fs_rec/CMakeLists.txt +++ b/reactos/drivers/filesystems/fs_rec/CMakeLists.txt @@ -6,6 +6,7 @@ list(APPEND SOURCE fat.c fs_rec.c ntfs.c + reiserfs.c udfs.c fs_rec.h) diff --git a/reactos/drivers/filesystems/fs_rec/fs_rec.c b/reactos/drivers/filesystems/fs_rec/fs_rec.c index b564e4b3a2a..c4ba8b93380 100644 --- a/reactos/drivers/filesystems/fs_rec/fs_rec.c +++ b/reactos/drivers/filesystems/fs_rec/fs_rec.c @@ -170,6 +170,12 @@ FsRecFsControl(IN PDEVICE_OBJECT DeviceObject, Status = FsRecBtrfsFsControl(DeviceObject, Irp); break; + case FS_TYPE_REISERFS: + + /* Send REISERFS command */ + Status = FsRecReiserfsFsControl(DeviceObject, Irp); + break; + default: /* Unrecognized FS */ @@ -398,6 +404,16 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject, FILE_DEVICE_DISK_FILE_SYSTEM); if (NT_SUCCESS(Status)) DeviceCount++; + /* Register REISERFS */ + Status = FsRecRegisterFs(DriverObject, + NULL, + NULL, + L"\\Reiserfs", + L"\\FileSystem\\ReiserfsRecognizer", + FS_TYPE_REISERFS, + FILE_DEVICE_DISK_FILE_SYSTEM); + if (NT_SUCCESS(Status)) DeviceCount++; + /* Return appropriate Status */ return (DeviceCount > 0) ? STATUS_SUCCESS : STATUS_IMAGE_ALREADY_LOADED; } diff --git a/reactos/drivers/filesystems/fs_rec/fs_rec.h b/reactos/drivers/filesystems/fs_rec/fs_rec.h index c440e4f063d..6e4cf77892b 100644 --- a/reactos/drivers/filesystems/fs_rec/fs_rec.h +++ b/reactos/drivers/filesystems/fs_rec/fs_rec.h @@ -175,6 +175,7 @@ typedef enum _FILE_SYSTEM_TYPE FS_TYPE_UDFS, FS_TYPE_EXT2, FS_TYPE_BTRFS, + FS_TYPE_REISERFS, } FILE_SYSTEM_TYPE, *PFILE_SYSTEM_TYPE; /* FS Recognizer State */ @@ -236,6 +237,13 @@ FsRecBtrfsFsControl( IN PIRP Irp ); +NTSTATUS +NTAPI +FsRecReiserfsFsControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp +); + BOOLEAN NTAPI FsRecGetDeviceSectors( diff --git a/reactos/drivers/filesystems/fs_rec/reiserfs.c b/reactos/drivers/filesystems/fs_rec/reiserfs.c new file mode 100644 index 00000000000..89bf0dc42f2 --- /dev/null +++ b/reactos/drivers/filesystems/fs_rec/reiserfs.c @@ -0,0 +1,122 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS File System Recognizer + * FILE: drivers/filesystems/fs_rec/btrfs.c + * PURPOSE: Btrfs Recognizer + * PROGRAMMER: Peter Hater + * Pierre Schweitzer (pierre@reactos.org) + */ + +/* INCLUDES *****************************************************************/ + +#include "fs_rec.h" +#include "reiserfs.h" + +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +BOOLEAN +NTAPI +FsRecIsReiserfsVolume(IN PRFSD_SUPER_BLOCK sb) +{ + UCHAR sz_MagicKey[] = REISER2FS_SUPER_MAGIC_STRING; + UCHAR currentChar; + int i; + + // If any characters read from disk don't match the expected magic key, we don't have a ReiserFS volume. + for (i = 0; i < MAGIC_KEY_LENGTH; i++) + { + currentChar = sb->s_magic[i]; + if (currentChar != sz_MagicKey[i]) + { + return FALSE; + } + } + + return TRUE; +} + +NTSTATUS +NTAPI +FsRecReiserfsFsControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + NTSTATUS Status; + PDEVICE_OBJECT MountDevice; + PRFSD_SUPER_BLOCK Spb = NULL; + ULONG SectorSize; + LARGE_INTEGER Offset; + BOOLEAN DeviceError = FALSE; + PAGED_CODE(); + + /* Get the I/O Stack and check the function type */ + Stack = IoGetCurrentIrpStackLocation(Irp); + switch (Stack->MinorFunction) + { + case IRP_MN_MOUNT_VOLUME: + + /* Assume failure */ + Status = STATUS_UNRECOGNIZED_VOLUME; + + /* Get the device object and request the sector size */ + MountDevice = Stack->Parameters.MountVolume.DeviceObject; + if (FsRecGetDeviceSectorSize(MountDevice, &SectorSize)) + { + /* Try to read the superblock */ + Offset.QuadPart = REISERFS_DISK_OFFSET_IN_BYTES; + if (FsRecReadBlock(MountDevice, + &Offset, + SectorSize, + SectorSize, + (PVOID)&Spb, + &DeviceError)) + { + /* Check if it's an actual BTRFS volume */ + if (FsRecIsReiserfsVolume(Spb)) + { + /* It is! */ + Status = STATUS_FS_DRIVER_REQUIRED; + } + } + + /* Free the boot sector if we have one */ + ExFreePool(Spb); + } + else + { + /* We have some sort of failure in the storage stack */ + DeviceError = TRUE; + } + + /* Check if we have an error on the stack */ + if (DeviceError) + { + /* Was this because of a floppy? */ + if (MountDevice->Characteristics & FILE_FLOPPY_DISKETTE) + { + /* Let the FS try anyway */ + Status = STATUS_FS_DRIVER_REQUIRED; + } + } + + break; + + case IRP_MN_LOAD_FILE_SYSTEM: + + /* Load the file system */ + Status = FsRecLoadFileSystem(DeviceObject, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\reiserfs"); + break; + + default: + + /* Invalid request */ + Status = STATUS_INVALID_DEVICE_REQUEST; + } + + /* Return Status */ + return Status; +} diff --git a/reactos/drivers/filesystems/fs_rec/reiserfs.h b/reactos/drivers/filesystems/fs_rec/reiserfs.h new file mode 100644 index 00000000000..646b9e642a9 --- /dev/null +++ b/reactos/drivers/filesystems/fs_rec/reiserfs.h @@ -0,0 +1,76 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS File System Recognizer + * FILE: drivers/filesystems/fs_rec/btrfs.h + * PURPOSE: BTRFS Header File + * PROGRAMMER: Peter Hater + * Pierre Schweitzer (pierre@reactos.org) + */ + +#include +struct journal_params { + // Block number of the block containing the first journal node. + UINT32 jp_journal_1st_block; /* where does journal start from on its device */ + + // Journal device number (?? for if the journal is on a seperate drive ??) + UINT32 jp_journal_dev; /* journal device st_rdev */ + + // Original journal size. (Needed when using partition on systems w/ different default journal sizes). + UINT32 jp_journal_size; /* size of the journal */ + + UINT32 jp_journal_trans_max; /* max number of blocks in a transaction. */ + UINT32 jp_journal_magic; /* random value made on fs creation (this was sb_journal_block_count) */ + UINT32 jp_journal_max_batch; /* max number of blocks to batch into a trans */ + UINT32 jp_journal_max_commit_age; /* in seconds, how old can an async commit be */ + UINT32 jp_journal_max_trans_age; /* in seconds, how old can a transaction be */ +}; + +typedef struct _RFSD_SUPER_BLOCK +{ + // The number of blocks in the partition + UINT32 s_blocks_count; /* blocks count */ //[mark] was _s_blocks_count + + // The number of free blocks in the partition + UINT32 s_free_blocks_count; /* free blocks count */ //[mark] was _s_free_blocks + + // Block number of the block containing the root node + UINT32 s_root_block; /* root block number */ + + struct journal_params s_journal; + + // The size (in bytes) of a block + UINT16 s_blocksize; /* block size */ + + UINT16 s_oid_maxsize; /* max size of object id array, see get_objectid() commentary */ + UINT16 s_oid_cursize; /* current size of object id array */ + UINT16 s_umount_state; /* this is set to 1 when filesystem was umounted, to 2 - when not */ + char s_magic[10]; /* reiserfs magic string indicates that + * file system is reiserfs: + * "ReIsErFs" or "ReIsEr2Fs" or "ReIsEr3Fs" */ + + // State of the partition: valid(1), error (2) + UINT16 s_fs_state; /* it is set to used by fsck to mark which phase of rebuilding is done */ + + UINT32 s_hash_function_code; /* indicate, what hash function is being use + * to sort names in a directory*/ + UINT16 s_tree_height; /* height of disk tree */ + UINT16 s_bmap_nr; /* amount of bitmap blocks needed to address + * each block of file system */ + + // The reiserfs version number + UINT16 s_version; /* this field is only reliable on filesystem + * with non-standard journal */ + UINT16 s_reserved_for_journal; /* size in blocks of journal area on main + * device, we need to keep after + * making fs with non-standard journal */ +} RFSD_SUPER_BLOCK, *PRFSD_SUPER_BLOCK; +#include + +C_ASSERT(FIELD_OFFSET(RFSD_SUPER_BLOCK, s_blocksize) == 44); +C_ASSERT(FIELD_OFFSET(RFSD_SUPER_BLOCK, s_magic) == 52); + +#define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024) +#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs" +#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs" +#define REISER2FS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs" +#define MAGIC_KEY_LENGTH 9