[FS_REC]
authorPierre Schweitzer <pierre@reactos.org>
Thu, 26 May 2016 18:17:19 +0000 (18:17 +0000)
committerPierre Schweitzer <pierre@reactos.org>
Thu, 26 May 2016 18:17:19 +0000 (18:17 +0000)
Add support for ReiserFS volumes.
Patch by Peter Hater.

This is done for ReiserFS support! Enjoy :-)

CORE-11005 #resolve

svn path=/trunk/; revision=71417

reactos/drivers/filesystems/fs_rec/CMakeLists.txt
reactos/drivers/filesystems/fs_rec/fs_rec.c
reactos/drivers/filesystems/fs_rec/fs_rec.h
reactos/drivers/filesystems/fs_rec/reiserfs.c [new file with mode: 0644]
reactos/drivers/filesystems/fs_rec/reiserfs.h [new file with mode: 0644]

index 4901c8b..4e2bfa5 100644 (file)
@@ -6,6 +6,7 @@ list(APPEND SOURCE
     fat.c
     fs_rec.c
     ntfs.c
+    reiserfs.c
     udfs.c
     fs_rec.h)
 
index b564e4b..c4ba8b9 100644 (file)
@@ -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;
 }
index c440e4f..6e4cf77 100644 (file)
@@ -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 (file)
index 0000000..89bf0dc
--- /dev/null
@@ -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 <debug.h>
+
+/* 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 (file)
index 0000000..646b9e6
--- /dev/null
@@ -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 <pshpack1.h>
+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 <poppack.h>
+
+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