mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 09:13:00 +00:00
Bring back ext2 code from branch
It does not compile yet svn path=/trunk/; revision=32283
This commit is contained in:
commit
0ba562cefa
43 changed files with 26255 additions and 0 deletions
7
reactos/drivers/filesystems/ext2/ext2fs.rc
Normal file
7
reactos/drivers/filesystems/ext2/ext2fs.rc
Normal file
|
@ -0,0 +1,7 @@
|
|||
/* $Id: ext2fs.rc 12852 2005-01-06 13:58:04Z mf $ */
|
||||
|
||||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "Linux ext2 IFS Driver\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "ext2fs\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "ext2fs.sys\0"
|
||||
#include <reactos/version.rc>
|
68
reactos/drivers/filesystems/ext2/inc/errmsg.h
Normal file
68
reactos/drivers/filesystems/ext2/inc/errmsg.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* File: errmsg.msg
|
||||
*
|
||||
* Product: Ext2 FSD
|
||||
*
|
||||
* Module: Ext2 FSD Event Log Messages
|
||||
*
|
||||
* Description:
|
||||
* Contains error strings in a format understandable to the message compiler.
|
||||
* Please compile (using mc) with the -c option which will set the
|
||||
* "Customer" bit in all errors.
|
||||
* Use values beginning at 0xA000 (e.g. 0xA001) for the Ext2 FSD
|
||||
* errors.
|
||||
* Do NOT use %1 for insertion strings. The I/O manager assumes that
|
||||
* the first insertion string is the name of the driver/device.
|
||||
*
|
||||
*
|
||||
*************************************************************************/
|
||||
//
|
||||
// Values are 32 bit values layed out as follows:
|
||||
//
|
||||
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
// +---+-+-+-----------------------+-------------------------------+
|
||||
// |Sev|C|R| Facility | Code |
|
||||
// +---+-+-+-----------------------+-------------------------------+
|
||||
//
|
||||
// where
|
||||
//
|
||||
// Sev - is the severity code
|
||||
//
|
||||
// 00 - Success
|
||||
// 01 - Informational
|
||||
// 10 - Warning
|
||||
// 11 - Error
|
||||
//
|
||||
// C - is the Customer code flag
|
||||
//
|
||||
// R - is a reserved bit
|
||||
//
|
||||
// Facility - is the facility code
|
||||
//
|
||||
// Code - is the facility's status code
|
||||
//
|
||||
//
|
||||
// Define the facility codes
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// Define the severity codes
|
||||
//
|
||||
#define STATUS_SEVERITY_WARNING 0x2
|
||||
#define STATUS_SEVERITY_SUCCESS 0x0
|
||||
#define STATUS_SEVERITY_INFORMATIONAL 0x1
|
||||
#define STATUS_SEVERITY_ERROR 0x3
|
||||
|
||||
|
||||
//
|
||||
// MessageId: EXT2_ERROR_INTERNAL_ERROR
|
||||
//
|
||||
// MessageText:
|
||||
//
|
||||
// The Ext2 FSD encountered an internal error. Please check log data information.
|
||||
//
|
||||
#define EXT2_ERROR_INTERNAL_ERROR ((ULONG)0xE004A001L)
|
||||
|
615
reactos/drivers/filesystems/ext2/inc/ext2_fs.h
Normal file
615
reactos/drivers/filesystems/ext2/inc/ext2_fs.h
Normal file
|
@ -0,0 +1,615 @@
|
|||
/*
|
||||
* linux/include/linux/ext2_fs.h
|
||||
*
|
||||
* Copyright (C) 1992, 1993, 1994, 1995
|
||||
* Remy Card (card@masi.ibp.fr)
|
||||
* Laboratoire MASI - Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* from
|
||||
*
|
||||
* linux/include/linux/minix_fs.h
|
||||
*
|
||||
* Copyright (C) 1991, 1992 Linus Torvalds
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_EXT2_FS_H
|
||||
#define _LINUX_EXT2_FS_H
|
||||
|
||||
// #include <linux/types.h>
|
||||
|
||||
/*
|
||||
* The second extended filesystem constants/structures
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Define EXT2_PREALLOCATE to preallocate data blocks for expanding files
|
||||
*/
|
||||
#define EXT2_PREALLOCATE
|
||||
#define EXT2_DEFAULT_PREALLOC_BLOCKS 8
|
||||
|
||||
/*
|
||||
* The second extended file system version
|
||||
*/
|
||||
#define EXT2FS_DATE "95/08/09"
|
||||
#define EXT2FS_VERSION "0.5b"
|
||||
|
||||
/*
|
||||
* Debug code
|
||||
*/
|
||||
|
||||
/*
|
||||
* Special inodes numbers
|
||||
*/
|
||||
#define EXT2_BAD_INO 1 /* Bad blocks inode */
|
||||
#define EXT2_ROOT_INO 2 /* Root inode */
|
||||
#define EXT2_ACL_IDX_INO 3 /* ACL inode */
|
||||
#define EXT2_ACL_DATA_INO 4 /* ACL inode */
|
||||
#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
|
||||
#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
|
||||
|
||||
/* First non-reserved inode for old ext2 filesystems */
|
||||
#define EXT2_GOOD_OLD_FIRST_INO 11
|
||||
|
||||
/*
|
||||
* The second extended file system magic number
|
||||
*/
|
||||
#define EXT2_SUPER_MAGIC 0xEF53
|
||||
|
||||
/*
|
||||
* Maximal count of links to a file
|
||||
*/
|
||||
#define EXT2_LINK_MAX 32000
|
||||
|
||||
/*
|
||||
* Macro-instructions used to manage several block sizes
|
||||
*/
|
||||
#define EXT2_MIN_BLOCK_SIZE 1024
|
||||
#define EXT2_MAX_BLOCK_SIZE 4096
|
||||
#define EXT2_MIN_BLOCK_LOG_SIZE 10
|
||||
#ifdef __KERNEL__
|
||||
# define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize)
|
||||
#else
|
||||
# define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
|
||||
#endif
|
||||
#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
|
||||
#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
|
||||
#ifdef __KERNEL__
|
||||
# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
|
||||
#else
|
||||
# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
|
||||
#endif
|
||||
#ifdef __KERNEL__
|
||||
#define EXT2_ADDR_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_addr_per_block_bits)
|
||||
#define EXT2_INODE_SIZE(s) ((s)->u.ext2_sb.s_inode_size)
|
||||
#define EXT2_FIRST_INO(s) ((s)->u.ext2_sb.s_first_ino)
|
||||
#else
|
||||
#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
|
||||
EXT2_GOOD_OLD_INODE_SIZE : \
|
||||
(s)->s_inode_size)
|
||||
#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
|
||||
EXT2_GOOD_OLD_FIRST_INO : \
|
||||
(s)->s_first_ino)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macro-instructions used to manage fragments
|
||||
*/
|
||||
#define EXT2_MIN_FRAG_SIZE 1024
|
||||
#define EXT2_MAX_FRAG_SIZE 4096
|
||||
#define EXT2_MIN_FRAG_LOG_SIZE 10
|
||||
#ifdef __KERNEL__
|
||||
# define EXT2_FRAG_SIZE(s) ((s)->u.ext2_sb.s_frag_size)
|
||||
# define EXT2_FRAGS_PER_BLOCK(s) ((s)->u.ext2_sb.s_frags_per_block)
|
||||
#else
|
||||
# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
|
||||
# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ACL structures
|
||||
*/
|
||||
struct ext2_acl_header /* Header of Access Control Lists */
|
||||
{
|
||||
__u32 aclh_size;
|
||||
__u32 aclh_file_count;
|
||||
__u32 aclh_acle_count;
|
||||
__u32 aclh_first_acle;
|
||||
};
|
||||
|
||||
struct ext2_acl_entry /* Access Control List Entry */
|
||||
{
|
||||
__u32 acle_size;
|
||||
__u16 acle_perms; /* Access permissions */
|
||||
__u16 acle_type; /* Type of entry */
|
||||
__u16 acle_tag; /* User or group identity */
|
||||
__u16 acle_pad1;
|
||||
__u32 acle_next; /* Pointer on next entry for the */
|
||||
/* same inode or on next free entry */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure of a blocks group descriptor
|
||||
*/
|
||||
struct ext2_group_desc
|
||||
{
|
||||
__u32 bg_block_bitmap; /* Blocks bitmap block */
|
||||
__u32 bg_inode_bitmap; /* Inodes bitmap block */
|
||||
__u32 bg_inode_table; /* Inodes table block */
|
||||
__u16 bg_free_blocks_count; /* Free blocks count */
|
||||
__u16 bg_free_inodes_count; /* Free inodes count */
|
||||
__u16 bg_used_dirs_count; /* Directories count */
|
||||
__u16 bg_pad;
|
||||
__u32 bg_reserved[3];
|
||||
};
|
||||
|
||||
/*
|
||||
* Macro-instructions used to manage group descriptors
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
# define EXT2_BLOCKS_PER_GROUP(s) ((s)->u.ext2_sb.s_blocks_per_group)
|
||||
# define EXT2_DESC_PER_BLOCK(s) ((s)->u.ext2_sb.s_desc_per_block)
|
||||
# define EXT2_INODES_PER_GROUP(s) ((s)->u.ext2_sb.s_inodes_per_group)
|
||||
# define EXT2_DESC_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_desc_per_block_bits)
|
||||
#else
|
||||
# define EXT2_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group)
|
||||
# define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
|
||||
# define EXT2_INODES_PER_GROUP(s) ((s)->s_inodes_per_group)
|
||||
#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_NOATIME_FL 0x00000080 /* do not update atime */
|
||||
/* Reserved for compression usage... */
|
||||
#define EXT2_DIRTY_FL 0x00000100
|
||||
#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
|
||||
#define EXT2_NOCOMP_FL 0x00000400 /* Don't compress */
|
||||
#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */
|
||||
/* End compression flags --- maybe not all used */
|
||||
#define EXT2_BTREE_FL 0x00001000 /* btree format dir */
|
||||
#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
|
||||
|
||||
#define EXT2_FL_USER_VISIBLE 0x00001FFF /* User visible flags */
|
||||
#define EXT2_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */
|
||||
|
||||
/*
|
||||
* ioctl commands
|
||||
*/
|
||||
#define EXT2_IOC_GETFLAGS _IOR('f', 1, long)
|
||||
#define EXT2_IOC_SETFLAGS _IOW('f', 2, long)
|
||||
#define EXT2_IOC_GETVERSION _IOR('v', 1, long)
|
||||
#define EXT2_IOC_SETVERSION _IOW('v', 2, long)
|
||||
|
||||
/*
|
||||
* Structure of an inode on the disk
|
||||
*/
|
||||
struct ext2_inode {
|
||||
__u16 i_mode; /* File mode */
|
||||
__u16 i_uid; /* Low 16 bits of Owner Uid */
|
||||
__u32 i_size; /* Size in bytes */
|
||||
__u32 i_atime; /* Access time */
|
||||
__u32 i_ctime; /* Creation time */
|
||||
__u32 i_mtime; /* Modification time */
|
||||
__u32 i_dtime; /* Deletion Time */
|
||||
__u16 i_gid; /* Low 16 bits of Group Id */
|
||||
__u16 i_links_count; /* Links count */
|
||||
__u32 i_blocks; /* Blocks count */
|
||||
__u32 i_flags; /* File flags */
|
||||
union {
|
||||
struct {
|
||||
__u32 l_i_reserved1;
|
||||
} linux1;
|
||||
struct {
|
||||
__u32 h_i_translator;
|
||||
} hurd1;
|
||||
struct {
|
||||
__u32 m_i_reserved1;
|
||||
} masix1;
|
||||
} osd1; /* OS dependent 1 */
|
||||
__u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
|
||||
__u32 i_generation; /* File version (for NFS) */
|
||||
__u32 i_file_acl; /* File ACL */
|
||||
__u32 i_dir_acl; /* Directory ACL */
|
||||
__u32 i_faddr; /* Fragment address */
|
||||
union {
|
||||
struct {
|
||||
__u8 l_i_frag; /* Fragment number */
|
||||
__u8 l_i_fsize; /* Fragment size */
|
||||
__u16 i_pad1;
|
||||
__u16 l_i_uid_high; /* these 2 fields */
|
||||
__u16 l_i_gid_high; /* were reserved2[0] */
|
||||
__u32 l_i_reserved2;
|
||||
} linux2;
|
||||
struct {
|
||||
__u8 h_i_frag; /* Fragment number */
|
||||
__u8 h_i_fsize; /* Fragment size */
|
||||
__u16 h_i_mode_high;
|
||||
__u16 h_i_uid_high;
|
||||
__u16 h_i_gid_high;
|
||||
__u32 h_i_author;
|
||||
} hurd2;
|
||||
struct {
|
||||
__u8 m_i_frag; /* Fragment number */
|
||||
__u8 m_i_fsize; /* Fragment size */
|
||||
__u16 m_pad1;
|
||||
__u32 m_i_reserved2[2];
|
||||
} masix2;
|
||||
} osd2; /* OS dependent 2 */
|
||||
};
|
||||
|
||||
#define i_size_high i_dir_acl
|
||||
|
||||
#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_uid_low i_uid
|
||||
#define i_gid_low i_gid
|
||||
#define i_uid_high osd2.linux2.l_i_uid_high
|
||||
#define i_gid_high osd2.linux2.l_i_gid_high
|
||||
#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
|
||||
|
||||
/*
|
||||
* File system states
|
||||
*/
|
||||
#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */
|
||||
#define EXT2_ERROR_FS 0x0002 /* Errors detected */
|
||||
|
||||
/*
|
||||
* Mount flags
|
||||
*/
|
||||
#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */
|
||||
#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */
|
||||
#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */
|
||||
#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */
|
||||
#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
|
||||
#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
|
||||
#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
|
||||
#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
|
||||
|
||||
#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
|
||||
#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
|
||||
#define test_opt(sb, opt) ((sb)->u.ext2_sb.s_mount_opt & \
|
||||
EXT2_MOUNT_##opt)
|
||||
/*
|
||||
* Maximal mount counts between two filesystem checks
|
||||
*/
|
||||
#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
|
||||
#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */
|
||||
|
||||
/*
|
||||
* Behaviour when detecting errors
|
||||
*/
|
||||
#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */
|
||||
#define EXT2_ERRORS_RO 2 /* Remount fs read-only */
|
||||
#define EXT2_ERRORS_PANIC 3 /* Panic */
|
||||
#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE
|
||||
|
||||
/*
|
||||
* Structure of the super block
|
||||
*/
|
||||
struct ext2_super_block {
|
||||
__u32 s_inodes_count; /* Inodes count */
|
||||
__u32 s_blocks_count; /* Blocks count */
|
||||
__u32 s_r_blocks_count; /* Reserved blocks count */
|
||||
__u32 s_free_blocks_count; /* Free blocks count */
|
||||
__u32 s_free_inodes_count; /* Free inodes count */
|
||||
__u32 s_first_data_block; /* First Data Block */
|
||||
__u32 s_log_block_size; /* Block size */
|
||||
__s32 s_log_frag_size; /* Fragment size */
|
||||
__u32 s_blocks_per_group; /* # Blocks per group */
|
||||
__u32 s_frags_per_group; /* # Fragments per group */
|
||||
__u32 s_inodes_per_group; /* # Inodes per group */
|
||||
__u32 s_mtime; /* Mount time */
|
||||
__u32 s_wtime; /* Write time */
|
||||
__u16 s_mnt_count; /* Mount count */
|
||||
__s16 s_max_mnt_count; /* Maximal mount count */
|
||||
__u16 s_magic; /* Magic signature */
|
||||
__u16 s_state; /* File system state */
|
||||
__u16 s_errors; /* Behaviour when detecting errors */
|
||||
__u16 s_minor_rev_level; /* minor revision level */
|
||||
__u32 s_lastcheck; /* time of last check */
|
||||
__u32 s_checkinterval; /* max. time between checks */
|
||||
__u32 s_creator_os; /* OS */
|
||||
__u32 s_rev_level; /* Revision level */
|
||||
__u16 s_def_resuid; /* Default uid for reserved blocks */
|
||||
__u16 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...
|
||||
*/
|
||||
__u32 s_first_ino; /* First non-reserved inode */
|
||||
__u16 s_inode_size; /* size of inode structure */
|
||||
__u16 s_block_group_nr; /* block group # of this superblock */
|
||||
__u32 s_feature_compat; /* compatible feature set */
|
||||
__u32 s_feature_incompat; /* incompatible feature set */
|
||||
__u32 s_feature_ro_compat; /* readonly-compatible feature set */
|
||||
__u8 s_uuid[16]; /* 128-bit uuid for volume */
|
||||
char s_volume_name[16]; /* volume name */
|
||||
char s_last_mounted[64]; /* directory where last mounted */
|
||||
__u32 s_algorithm_usage_bitmap; /* For compression */
|
||||
/*
|
||||
* Performance hints. Directory preallocation should only
|
||||
* happen if the EXT2_COMPAT_PREALLOC flag is on.
|
||||
*/
|
||||
__u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
|
||||
__u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
|
||||
__u16 s_padding1;
|
||||
__u32 s_reserved[204]; /* Padding to the end of the block */
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#define EXT2_SB(sb) (&((sb)->u.ext2_sb))
|
||||
#else
|
||||
/* Assume that user mode programs are passing in an ext2fs superblock, not
|
||||
* a kernel struct super_block. This will allow us to call the feature-test
|
||||
* macros from user land. */
|
||||
#define EXT2_SB(sb) (sb)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
#define EXT2_GOOD_OLD_INODE_SIZE 128
|
||||
|
||||
/*
|
||||
* Feature set definitions
|
||||
*/
|
||||
|
||||
#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \
|
||||
( EXT2_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask) )
|
||||
#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \
|
||||
( EXT2_SB(sb)->s_es->s_feature_ro_compat & cpu_to_le32(mask) )
|
||||
#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \
|
||||
( EXT2_SB(sb)->s_es->s_feature_incompat & cpu_to_le32(mask) )
|
||||
#define EXT2_SET_COMPAT_FEATURE(sb,mask) \
|
||||
EXT2_SB(sb)->s_es->s_feature_compat |= cpu_to_le32(mask)
|
||||
#define EXT2_SET_RO_COMPAT_FEATURE(sb,mask) \
|
||||
EXT2_SB(sb)->s_es->s_feature_ro_compat |= cpu_to_le32(mask)
|
||||
#define EXT2_SET_INCOMPAT_FEATURE(sb,mask) \
|
||||
EXT2_SB(sb)->s_es->s_feature_incompat |= cpu_to_le32(mask)
|
||||
#define EXT2_CLEAR_COMPAT_FEATURE(sb,mask) \
|
||||
EXT2_SB(sb)->s_es->s_feature_compat &= ~cpu_to_le32(mask)
|
||||
#define EXT2_CLEAR_RO_COMPAT_FEATURE(sb,mask) \
|
||||
EXT2_SB(sb)->s_es->s_feature_ro_compat &= ~cpu_to_le32(mask)
|
||||
#define EXT2_CLEAR_INCOMPAT_FEATURE(sb,mask) \
|
||||
EXT2_SB(sb)->s_es->s_feature_incompat &= ~cpu_to_le32(mask)
|
||||
|
||||
#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
|
||||
|
||||
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
|
||||
#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
|
||||
#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
|
||||
|
||||
#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
|
||||
#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
|
||||
|
||||
#define EXT2_FEATURE_COMPAT_SUPP 0
|
||||
#define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE
|
||||
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
|
||||
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
|
||||
EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
|
||||
|
||||
/*
|
||||
* Default values for user and/or group using reserved blocks
|
||||
*/
|
||||
#define EXT2_DEF_RESUID 0
|
||||
#define EXT2_DEF_RESGID 0
|
||||
|
||||
/*
|
||||
* Structure of a directory entry
|
||||
*/
|
||||
#define EXT2_NAME_LEN 255
|
||||
|
||||
struct ext2_dir_entry {
|
||||
__u32 inode; /* Inode number */
|
||||
__u16 rec_len; /* Directory entry length */
|
||||
__u16 name_len; /* Name length */
|
||||
char name[EXT2_NAME_LEN]; /* File name */
|
||||
};
|
||||
|
||||
/*
|
||||
* The new version of the directory entry. Since EXT2 structures are
|
||||
* stored in intel byte order, and the name_len field could never be
|
||||
* bigger than 255 chars, it's safe to reclaim the extra byte for the
|
||||
* file_type field.
|
||||
*/
|
||||
struct ext2_dir_entry_2 {
|
||||
__u32 inode; /* Inode number */
|
||||
__u16 rec_len; /* Directory entry length */
|
||||
__u8 name_len; /* Name length */
|
||||
__u8 file_type;
|
||||
char name[EXT2_NAME_LEN]; /* File name */
|
||||
};
|
||||
|
||||
/*
|
||||
* Ext2 directory file types. Only the low 3 bits are used. The
|
||||
* other bits are reserved for now.
|
||||
*/
|
||||
#define EXT2_FT_UNKNOWN 0
|
||||
#define EXT2_FT_REG_FILE 1
|
||||
#define EXT2_FT_DIR 2
|
||||
#define EXT2_FT_CHRDEV 3
|
||||
#define EXT2_FT_BLKDEV 4
|
||||
#define EXT2_FT_FIFO 5
|
||||
#define EXT2_FT_SOCK 6
|
||||
#define EXT2_FT_SYMLINK 7
|
||||
|
||||
#define EXT2_FT_MAX 8
|
||||
|
||||
/*
|
||||
* EXT2_DIR_PAD defines the directory entries boundaries
|
||||
*
|
||||
* NOTE: It must be a multiple of 4
|
||||
*/
|
||||
#define EXT2_DIR_PAD 4
|
||||
#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
|
||||
#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
|
||||
~EXT2_DIR_ROUND)
|
||||
|
||||
#ifdef __KERNEL__
|
||||
/*
|
||||
* Function prototypes
|
||||
*/
|
||||
|
||||
/*
|
||||
* Ok, these declarations are also in <linux/kernel.h> but none of the
|
||||
* ext2 source programs needs to include it so they are duplicated here.
|
||||
*/
|
||||
# define NORET_TYPE /**/
|
||||
# define ATTRIB_NORET __attribute__((noreturn))
|
||||
# define NORET_AND noreturn,
|
||||
|
||||
/* acl.c */
|
||||
extern int ext2_permission (struct inode *, int);
|
||||
|
||||
/* balloc.c */
|
||||
extern int ext2_bg_has_super(struct super_block *sb, int group);
|
||||
extern unsigned long ext2_bg_num_gdb(struct super_block *sb, int group);
|
||||
extern int ext2_new_block (struct inode *, unsigned long,
|
||||
__u32 *, __u32 *, int *);
|
||||
extern void ext2_free_blocks (struct inode *, unsigned long,
|
||||
unsigned long);
|
||||
extern unsigned long ext2_count_free_blocks (struct super_block *);
|
||||
extern void ext2_check_blocks_bitmap (struct super_block *);
|
||||
extern struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
|
||||
unsigned int block_group,
|
||||
struct buffer_head ** bh);
|
||||
|
||||
/* bitmap.c */
|
||||
extern unsigned long ext2_count_free (struct buffer_head *, unsigned);
|
||||
|
||||
/* dir.c */
|
||||
extern int ext2_check_dir_entry (const char *, struct inode *,
|
||||
struct ext2_dir_entry_2 *, struct buffer_head *,
|
||||
unsigned long);
|
||||
|
||||
/* file.c */
|
||||
extern int ext2_read (struct inode *, struct file *, char *, int);
|
||||
extern int ext2_write (struct inode *, struct file *, char *, int);
|
||||
|
||||
/* fsync.c */
|
||||
extern int ext2_sync_file (struct file *, struct dentry *, int);
|
||||
extern int ext2_fsync_inode (struct inode *, int);
|
||||
|
||||
/* ialloc.c */
|
||||
extern struct inode * ext2_new_inode (const struct inode *, int);
|
||||
extern void ext2_free_inode (struct inode *);
|
||||
extern unsigned long ext2_count_free_inodes (struct super_block *);
|
||||
extern void ext2_check_inodes_bitmap (struct super_block *);
|
||||
|
||||
/* inode.c */
|
||||
|
||||
extern struct buffer_head * ext2_getblk (struct inode *, long, int, int *);
|
||||
extern struct buffer_head * ext2_bread (struct inode *, int, int, int *);
|
||||
|
||||
extern void ext2_read_inode (struct inode *);
|
||||
extern void ext2_write_inode (struct inode *, int);
|
||||
extern void ext2_put_inode (struct inode *);
|
||||
extern void ext2_delete_inode (struct inode *);
|
||||
extern int ext2_sync_inode (struct inode *);
|
||||
extern void ext2_discard_prealloc (struct inode *);
|
||||
|
||||
/* ioctl.c */
|
||||
extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
|
||||
unsigned long);
|
||||
|
||||
/* namei.c */
|
||||
extern struct inode_operations ext2_dir_inode_operations;
|
||||
|
||||
/* super.c */
|
||||
extern void ext2_error (struct super_block *, const char *, const char *, ...)
|
||||
__attribute__ ((format (printf, 3, 4)));
|
||||
extern NORET_TYPE void ext2_panic (struct super_block *, const char *,
|
||||
const char *, ...)
|
||||
__attribute__ ((NORET_AND format (printf, 3, 4)));
|
||||
extern void ext2_warning (struct super_block *, const char *, const char *, ...)
|
||||
__attribute__ ((format (printf, 3, 4)));
|
||||
extern void ext2_update_dynamic_rev (struct super_block *sb);
|
||||
extern void ext2_put_super (struct super_block *);
|
||||
extern void ext2_write_super (struct super_block *);
|
||||
extern int ext2_remount (struct super_block *, int *, char *);
|
||||
extern struct super_block * ext2_read_super (struct super_block *,void *,int);
|
||||
extern int ext2_statfs (struct super_block *, struct statfs *);
|
||||
|
||||
/* truncate.c */
|
||||
extern void ext2_truncate (struct inode *);
|
||||
|
||||
/*
|
||||
* Inodes and files operations
|
||||
*/
|
||||
|
||||
/* dir.c */
|
||||
extern struct file_operations ext2_dir_operations;
|
||||
|
||||
/* file.c */
|
||||
extern struct inode_operations ext2_file_inode_operations;
|
||||
extern struct file_operations ext2_file_operations;
|
||||
|
||||
/* symlink.c */
|
||||
extern struct inode_operations ext2_fast_symlink_inode_operations;
|
||||
|
||||
extern struct address_space_operations ext2_aops;
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _LINUX_EXT2_FS_H */
|
250
reactos/drivers/filesystems/ext2/inc/ext2fsd.h
Normal file
250
reactos/drivers/filesystems/ext2/inc/ext2fsd.h
Normal file
|
@ -0,0 +1,250 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* File: ext2fsd.h
|
||||
*
|
||||
* Module: Ext2 File System Driver (Kernel mode execution only)
|
||||
*
|
||||
* Description:
|
||||
* The main include file for the Ext2 file system driver.
|
||||
*
|
||||
* Author: Manoj Paul Joseph
|
||||
*
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#ifndef _EXT2_FSD_H_
|
||||
#define _EXT2_FSD_H_
|
||||
|
||||
#define EXT2_POOL_WITH_TAG
|
||||
|
||||
|
||||
// some constant definitions
|
||||
#define EXT2_PANIC_IDENTIFIER (0x86427531)
|
||||
|
||||
// any directory information EXT2 obtains from the local file system
|
||||
// will use a buffer of the following size ... (in KB)
|
||||
#define EXT2_READ_DIR_BUFFER_LENGTH (512)
|
||||
#define EXT2_MAXCLOSABLE_FCBS_UL 20
|
||||
#define EXT2_MAXCLOSABLE_FCBS_LL 10
|
||||
|
||||
// Some type definitions...
|
||||
// These are used later...
|
||||
|
||||
typedef unsigned char UCHAR;
|
||||
typedef unsigned int UINT;
|
||||
typedef UCHAR BYTE;
|
||||
typedef UCHAR BOOLEAN; // winnt
|
||||
typedef BOOLEAN * PBOOLEAN; // winnt
|
||||
typedef void * PVOID64; // winnt
|
||||
typedef long LONG;
|
||||
typedef LONG HRESULT;
|
||||
|
||||
|
||||
#if defined(_M_IX86)
|
||||
#define FASTCALL _fastcall
|
||||
#else
|
||||
#define FASTCALL
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// Common include files - should be in the include dir of the MS supplied IFS Kit
|
||||
#include <ntifs.h>
|
||||
#include <ntdddisk.h>
|
||||
|
||||
|
||||
/* REACTOS FIXME */
|
||||
#undef DeleteFile
|
||||
/* This is deprecated and should be changed in the EXT2FS driver. */
|
||||
#define RtlLargeIntegerLessThan(a, b) (a).QuadPart < (b).QuadPart
|
||||
#define RtlLargeIntegerGreaterThan(a, b) (a).QuadPart > (b).QuadPart
|
||||
|
||||
|
||||
// the following include files should be in the inc sub-dir associated with this driver
|
||||
#include "ext2metadata.h"
|
||||
#include "struct.h"
|
||||
#include "protos.h"
|
||||
#include "errmsg.h"
|
||||
|
||||
|
||||
// global variables - minimize these
|
||||
extern Ext2Data Ext2GlobalData;
|
||||
|
||||
// try-finally simulation
|
||||
#define try_return(S) { S; goto try_exit; }
|
||||
#define try_return1(S) { S; goto try_exit1; }
|
||||
#define try_return2(S) { S; goto try_exit2; }
|
||||
|
||||
// some global (helpful) macros
|
||||
#define Ext2IsFlagOn(Flags,SingleFlag) ((BOOLEAN)((((Flags) & (SingleFlag)) != 0)))
|
||||
#define Ext2SetFlag(Flag, Value) ((Flag) |= (Value))
|
||||
#define Ext2ClearFlag(Flag, Value) ((Flag) &= ~(Value))
|
||||
|
||||
#define Ext2QuadAlign(Value) ((((uint32)(Value)) + 7) & 0xfffffff8)
|
||||
|
||||
// to perform a bug-check (panic), the following macro is used
|
||||
#define Ext2Panic(arg1, arg2, arg3) \
|
||||
(KeBugCheckEx(EXT2_PANIC_IDENTIFIER, EXT2_BUG_CHECK_ID | __LINE__, (uint32)(arg1), (uint32)(arg2), (uint32)(arg3)))
|
||||
|
||||
// a convenient macro (must be invoked in the context of the thread that acquired the resource)
|
||||
#define Ext2ReleaseResource(Resource) \
|
||||
(ExReleaseResourceForThreadLite((Resource), ExGetCurrentResourceThread()))
|
||||
|
||||
// each file has a unique bug-check identifier associated with it.
|
||||
// Here is a list of constant definitions for these identifiers
|
||||
#define EXT2_FILE_INIT (0x00000001)
|
||||
#define EXT2_FILE_REGISTRY (0x00000002)
|
||||
#define EXT2_FILE_CREATE (0x00000003)
|
||||
#define EXT2_FILE_CLEANUP (0x00000004)
|
||||
#define EXT2_FILE_CLOSE (0x00000005)
|
||||
#define EXT2_FILE_READ (0x00000006)
|
||||
#define EXT2_FILE_WRITE (0x00000007)
|
||||
#define EXT2_FILE_INFORMATION (0x00000008)
|
||||
#define EXT2_FILE_FLUSH (0x00000009)
|
||||
#define EXT2_FILE_VOL_INFORMATION (0x0000000A)
|
||||
#define EXT2_FILE_DIR_CONTROL (0x0000000B)
|
||||
#define EXT2_FILE_FILE_CONTROL (0x0000000C)
|
||||
#define EXT2_FILE_DEVICE_CONTROL (0x0000000D)
|
||||
#define EXT2_FILE_SHUTDOWN (0x0000000E)
|
||||
#define EXT2_FILE_LOCK_CONTROL (0x0000000F)
|
||||
#define EXT2_FILE_SECURITY (0x00000010)
|
||||
#define EXT2_FILE_EXT_ATTR (0x00000011)
|
||||
#define EXT2_FILE_MISC (0x00000012)
|
||||
#define EXT2_FILE_FAST_IO (0x00000013)
|
||||
#define EXT2_FILE_IO (0x00000014)
|
||||
#define EXT2_FILE_METADATA_IO (0x00000015)
|
||||
|
||||
|
||||
|
||||
#if DBG
|
||||
#define Ext2BreakPoint() DbgBreakPoint()
|
||||
#else
|
||||
#define Ext2BreakPoint()
|
||||
#endif
|
||||
|
||||
#define Ext2RaiseStatus(IRPCONTEXT,STATUS) \
|
||||
{ \
|
||||
(IRPCONTEXT)->ExceptionStatus = (STATUS); \
|
||||
ExRaiseStatus( (STATUS) ); \
|
||||
}
|
||||
|
||||
#ifdef EXT2_POOL_WITH_TAG
|
||||
#define Ext2AllocatePool(PoolType,NumberOfBytes) \
|
||||
ExAllocatePoolWithTag( PoolType, NumberOfBytes, '2txE' )
|
||||
#else
|
||||
#define Ext2AllocatePool(PoolType,NumberOfBytes) \
|
||||
ExAllocatePool( PoolType, NumberOfBytes )
|
||||
#endif
|
||||
|
||||
|
||||
#if DBG
|
||||
|
||||
//
|
||||
// Trace types...
|
||||
// Any number of these may be enabled...
|
||||
//
|
||||
#define DEBUG_TRACE_IRQL (0x00000001)
|
||||
#define DEBUG_TRACE_IRP_ENTRY (0x00000002)
|
||||
#define DEBUG_TRACE_RESOURCE_ACQUIRE (0x00000004)
|
||||
#define DEBUG_TRACE_RESOURCE_RELEASE (0x00000008)
|
||||
#define DEBUG_TRACE_RESOURCE_RETRY (0x00000010)
|
||||
#define DEBUG_TRACE_ASYNC (0x00000020)
|
||||
#define DEBUG_TRACE_MOUNT (0x00000040)
|
||||
#define DEBUG_TRACE_RESOURCE_STATE (0x00000080)
|
||||
#define DEBUG_TRACE_MISC (0x00000100)
|
||||
#define DEBUG_TRACE_FILE_OBJ (0x00000200)
|
||||
#define DEBUG_TRACE_FILE_NAME (0x00000400)
|
||||
#define DEBUG_TRACE_SPECIAL (0x00000800)
|
||||
#define DEBUG_TRACE_ERROR (0x00001000)
|
||||
#define DEBUG_TRACE_READ_DETAILS (0x00002000)
|
||||
#define DEBUG_TRACE_WRITE_DETAILS (0x00004000)
|
||||
#define DEBUG_TRACE_FILEINFO (0x00008000)
|
||||
#define DEBUG_TRACE_DIRINFO (0x00010000)
|
||||
#define DEBUG_TRACE_REFERENCE (0x00020000)
|
||||
#define DEBUG_TRACE_FSCTRL (0x00040000)
|
||||
#define DEBUG_TRACE_FREE (0x00080000)
|
||||
#define DEBUG_TRACE_LINENO (0x00100000)
|
||||
#define DEBUG_TRACE_TRIPLE (0x00200000)
|
||||
|
||||
#define DEBUG_TRACE_ALL (0xffffffff)
|
||||
#define DEBUG_TRACE_NONE 0
|
||||
//
|
||||
// The permitted DebugTrace types...
|
||||
//
|
||||
#define PERMITTED_DEBUG_TRACE_TYPES /* DEBUG_TRACE_TRIPLE */ DEBUG_TRACE_ALL
|
||||
/*
|
||||
#define PERMITTED_DEBUG_TRACE_TYPES DEBUG_TRACE_ERROR | DEBUG_TRACE_IRP_ENTRY | \
|
||||
DEBUG_TRACE_FILE_NAME | DEBUG_TRACE_SPECIAL | \
|
||||
DEBUG_TRACE_ASYNC
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#define DebugTrace( TYPE, X, Y ) \
|
||||
{ \
|
||||
if( ( TYPE ) & ( PERMITTED_DEBUG_TRACE_TYPES ) ) \
|
||||
{ \
|
||||
DbgPrint("\n "); \
|
||||
DbgPrint(X,Y); \
|
||||
if( ( DEBUG_TRACE_IRQL ) & ( PERMITTED_DEBUG_TRACE_TYPES ) ) \
|
||||
{ \
|
||||
DbgPrint( " IRQL = %d ", KeGetCurrentIrql( ) ); \
|
||||
} \
|
||||
if( ( DEBUG_TRACE_LINENO ) & ( PERMITTED_DEBUG_TRACE_TYPES ) ) \
|
||||
{ \
|
||||
DbgPrint( " [%s] Line No = %ld", __FILE__, __LINE__ ); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
#define DebugTraceState( STR, X1, X2, X3) \
|
||||
{ \
|
||||
if( ( DEBUG_TRACE_RESOURCE_STATE ) & ( PERMITTED_DEBUG_TRACE_TYPES ) ) \
|
||||
{ \
|
||||
DbgPrint("\nState: "); \
|
||||
DbgPrint( STR, X1, X2, X3 ); \
|
||||
if( ( DEBUG_TRACE_IRQL ) & ( PERMITTED_DEBUG_TRACE_TYPES ) ) \
|
||||
{ \
|
||||
DbgPrint( " IRQL = %d ", KeGetCurrentIrql( ) ); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define AssertFCB( PtrFCB ) \
|
||||
{ \
|
||||
if( !(PtrFCB) || (PtrFCB)->NodeIdentifier.NodeType != EXT2_NODE_TYPE_FCB ) \
|
||||
{ \
|
||||
Ext2BreakPoint(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define AssertVCB( PtrVCB ) \
|
||||
{ \
|
||||
if( !(PtrVCB) || (PtrVCB)->NodeIdentifier.NodeType != EXT2_NODE_TYPE_VCB ) \
|
||||
{ \
|
||||
Ext2BreakPoint(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define AssertFCBorVCB( PtrVCBorFCB ) \
|
||||
{ \
|
||||
if( !(PtrVCBorFCB) || \
|
||||
( (PtrVCBorFCB)->NodeIdentifier.NodeType != EXT2_NODE_TYPE_VCB && \
|
||||
(PtrVCBorFCB)->NodeIdentifier.NodeType != EXT2_NODE_TYPE_FCB ) ) \
|
||||
{ \
|
||||
Ext2BreakPoint(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#else
|
||||
#define DebugTrace( TYPE, X, Y )
|
||||
#define DebugTraceState( STR, X1, X2, X3 )
|
||||
#define AssertFCB( PtrFCB )
|
||||
#define AssertVCB( PtrVCB )
|
||||
#define AssertFCBorVCB( PtrVCBorFCB )
|
||||
|
||||
#endif
|
||||
|
||||
#endif // _EXT2_FSD_H_
|
115
reactos/drivers/filesystems/ext2/inc/ext2metadata.h
Normal file
115
reactos/drivers/filesystems/ext2/inc/ext2metadata.h
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* File: ext2metadata.h
|
||||
*
|
||||
* Module: Ext2 File System Driver (Kernel mode execution only)
|
||||
*
|
||||
* Description:
|
||||
* Contains the definitions for the Ext2 Metadata structures.
|
||||
*
|
||||
* Author: Manoj Paul Joseph
|
||||
*
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef EXT2_METADATA_STRUCTURES
|
||||
#define EXT2_METADATA_STRUCTURES
|
||||
|
||||
//
|
||||
// Some type definitions...
|
||||
// These are used in the ext2_fs.h header file
|
||||
//
|
||||
typedef unsigned int __u32 ;
|
||||
typedef signed int __s32 ;
|
||||
typedef unsigned short int __u16 ;
|
||||
typedef signed short int __s16 ;
|
||||
typedef unsigned char __u8 ;
|
||||
|
||||
//
|
||||
//******************************************************
|
||||
//
|
||||
// Using Remy Card's (slightly modified) Ext2 header...
|
||||
//
|
||||
#include "ext2_fs.h"
|
||||
//
|
||||
//******************************************************
|
||||
//
|
||||
|
||||
typedef struct ext2_super_block EXT2_SUPER_BLOCK;
|
||||
typedef EXT2_SUPER_BLOCK * PEXT2_SUPER_BLOCK;
|
||||
|
||||
typedef struct ext2_inode EXT2_INODE;
|
||||
typedef EXT2_INODE * PEXT2_INODE;
|
||||
|
||||
typedef struct ext2_group_desc EXT2_GROUP_DESCRIPTOR;
|
||||
typedef EXT2_GROUP_DESCRIPTOR * PEXT2_GROUP_DESCRIPTOR;
|
||||
|
||||
typedef struct ext2_dir_entry_2 EXT2_DIR_ENTRY;
|
||||
typedef EXT2_DIR_ENTRY * PEXT2_DIR_ENTRY;
|
||||
|
||||
//
|
||||
// Ext2 Supported File Types...
|
||||
//
|
||||
#define IMODE_FIFO 0x01
|
||||
#define IMODE_CHARDEV 0x02
|
||||
#define IMODE_DIR 0x04
|
||||
#define IMODE_BLOCKDEV 0x06
|
||||
#define IMODE_FILE 0x08
|
||||
#define IMODE_SLINK 0x0A
|
||||
#define IMODE_SOCKET 0x0C
|
||||
|
||||
#define _MKMODE(m) ( ( (m) >> 12 ) & 0x000F)
|
||||
#define Ext2IsModeRegularFile(m) ( _MKMODE(m) == IMODE_FILE )
|
||||
#define Ext2IsModeDirectory(m) ( _MKMODE(m) == IMODE_DIR )
|
||||
#define Ext2IsModeSymbolicLink(m) ( _MKMODE(m) == IMODE_SLINK )
|
||||
#define Ext2IsModePipe(m) ( _MKMODE(m) == IMODE_FIFO )
|
||||
#define Ext2IsModeCharacterDevice(m) ( _MKMODE(m) == IMODE_CHARDEV )
|
||||
#define Ext2IsModeBlockDevice(m) ( _MKMODE(m) == IMODE_BLOCKDEV )
|
||||
#define Ext2IsModeSocket(m) ( _MKMODE(m) == IMODE_SOCKET )
|
||||
|
||||
#define Ext2IsModeHidden(m) ( (m & 0x124) == 0) // No Read Permission
|
||||
#define Ext2IsModeReadOnly(m) ( (m & 0x92) == 0) // No write Permission
|
||||
|
||||
#define Ext2SetModeHidden(m) m = (m & (~0x124)); // Turn off Read Permission
|
||||
#define Ext2SetModeReadOnly(m) m = (m & (~0x92)); // Turn off write Permission
|
||||
#define Ext2SetModeReadWrite(m) m = (m & 0x1ff); // Set read/write Permission
|
||||
|
||||
|
||||
//
|
||||
// Define the Packed and Unpacked BIOS Parameter Block
|
||||
//
|
||||
typedef struct _PACKED_BIOS_PARAMETER_BLOCK {
|
||||
UCHAR BytesPerSector[2]; // offset = 0x000 0
|
||||
UCHAR SectorsPerCluster[1]; // offset = 0x002 2
|
||||
UCHAR ReservedSectors[2]; // offset = 0x003 3
|
||||
UCHAR Fats[1]; // offset = 0x005 5
|
||||
UCHAR RootEntries[2]; // offset = 0x006 6
|
||||
UCHAR Sectors[2]; // offset = 0x008 8
|
||||
UCHAR Media[1]; // offset = 0x00A 10
|
||||
UCHAR SectorsPerFat[2]; // offset = 0x00B 11
|
||||
UCHAR SectorsPerTrack[2]; // offset = 0x00D 13
|
||||
UCHAR Heads[2]; // offset = 0x00F 15
|
||||
UCHAR HiddenSectors[4]; // offset = 0x011 17
|
||||
UCHAR LargeSectors[4]; // offset = 0x015 21
|
||||
} PACKED_BIOS_PARAMETER_BLOCK; // sizeof = 0x019 25
|
||||
typedef PACKED_BIOS_PARAMETER_BLOCK *PPACKED_BIOS_PARAMETER_BLOCK;
|
||||
|
||||
//
|
||||
// Define the boot sector
|
||||
//
|
||||
typedef struct _PACKED_BOOT_SECTOR {
|
||||
UCHAR Jump[3]; // offset = 0x000 0
|
||||
UCHAR Oem[8]; // offset = 0x003 3
|
||||
PACKED_BIOS_PARAMETER_BLOCK PackedBpb; // offset = 0x00B 11
|
||||
UCHAR PhysicalDriveNumber; // offset = 0x024 36
|
||||
UCHAR CurrentHead; // offset = 0x025 37
|
||||
UCHAR Signature; // offset = 0x026 38
|
||||
UCHAR Id[4]; // offset = 0x027 39
|
||||
UCHAR VolumeLabel[11]; // offset = 0x02B 43
|
||||
UCHAR SystemId[8]; // offset = 0x036 54
|
||||
} PACKED_BOOT_SECTOR; // sizeof = 0x03E 62
|
||||
|
||||
typedef PACKED_BOOT_SECTOR *PPACKED_BOOT_SECTOR;
|
||||
|
||||
|
||||
#endif
|
782
reactos/drivers/filesystems/ext2/inc/protos.h
Normal file
782
reactos/drivers/filesystems/ext2/inc/protos.h
Normal file
|
@ -0,0 +1,782 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* File: protos.h
|
||||
*
|
||||
* Module: Ext2 File System Driver (Kernel mode execution only)
|
||||
*
|
||||
* Description:
|
||||
* Contains the prototypes for functions in this sample FSD.
|
||||
*
|
||||
* Author: Manoj Paul Joseph
|
||||
*
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef _EXT2_PROTOS_H_
|
||||
#define _EXT2_PROTOS_H_
|
||||
|
||||
#ifdef __REACTOS__
|
||||
typedef PIO_STACK_LOCATION PEXTENDED_IO_STACK_LOCATION;
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
* Prototypes for the file sfsdinit.c
|
||||
*************************************************************************/
|
||||
extern NTSTATUS STDCALL DriverEntry(
|
||||
PDRIVER_OBJECT DriverObject, // created by the I/O sub-system
|
||||
PUNICODE_STRING RegistryPath); // path to the registry key
|
||||
|
||||
extern void STDCALL Ext2FsdInitializeFunctionPointers(
|
||||
PDRIVER_OBJECT DriverObject); // created by the I/O sub-system
|
||||
|
||||
|
||||
extern VOID STDCALL Ext2QueueHandlerThread(
|
||||
IN PVOID StartContext);
|
||||
|
||||
/*************************************************************************
|
||||
* Prototypes for the file fsctrl.c
|
||||
*************************************************************************/
|
||||
|
||||
extern NTSTATUS STDCALL Ext2FileSystemControl(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2VerifyVolume (
|
||||
IN PIRP Irp,
|
||||
IN PIO_STACK_LOCATION IrpSp );
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Prototypes for the file create.c
|
||||
*************************************************************************/
|
||||
extern NTSTATUS STDCALL Ext2Create(
|
||||
PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
PIRP Irp); // I/O Request Packet
|
||||
|
||||
extern NTSTATUS STDCALL Ext2CommonCreate(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp,
|
||||
BOOLEAN FirstAttempt );
|
||||
|
||||
extern NTSTATUS STDCALL Ext2OpenVolume(
|
||||
PtrExt2VCB PtrVCB, // volume to be opened
|
||||
PtrExt2IrpContext PtrIrpContext, // IRP context
|
||||
PIRP PtrIrp, // original/user IRP
|
||||
unsigned short ShareAccess, // share access
|
||||
PIO_SECURITY_CONTEXT PtrSecurityContext, // caller's context (incl access)
|
||||
PFILE_OBJECT PtrNewFileObject); // I/O Mgr. created file object
|
||||
|
||||
extern NTSTATUS STDCALL Ext2OpenRootDirectory(
|
||||
PtrExt2VCB PtrVCB, // volume to be opened
|
||||
PtrExt2IrpContext PtrIrpContext, // IRP context
|
||||
PIRP PtrIrp, // original/user IRP
|
||||
unsigned short ShareAccess, // share access
|
||||
PIO_SECURITY_CONTEXT PtrSecurityContext, // caller's context (incl access)
|
||||
PFILE_OBJECT PtrNewFileObject); // I/O Mgr. created file object
|
||||
|
||||
extern void STDCALL Ext2InitializeFCB(
|
||||
PtrExt2FCB PtrNewFCB, // FCB structure to be initialized
|
||||
PtrExt2VCB PtrVCB, // logical volume (VCB) pointer
|
||||
PtrExt2ObjectName PtrObjectName, // name of the object
|
||||
uint32 Flags, // is this a file/directory, etc.
|
||||
PFILE_OBJECT PtrFileObject);// optional file object to be initialized
|
||||
|
||||
extern PtrExt2FCB STDCALL Ext2LocateChildFCBInCore(
|
||||
PtrExt2VCB PtrVCB,
|
||||
PUNICODE_STRING PtrName,
|
||||
ULONG ParentInodeNo );
|
||||
|
||||
extern PtrExt2FCB STDCALL Ext2LocateFCBInCore(
|
||||
PtrExt2VCB PtrVCB,
|
||||
ULONG InodeNo );
|
||||
|
||||
|
||||
extern ULONG STDCALL Ext2LocateFileInDisk(
|
||||
PtrExt2VCB PtrVCB,
|
||||
PUNICODE_STRING PtrCurrentName,
|
||||
PtrExt2FCB PtrParentFCB,
|
||||
ULONG *Type );
|
||||
|
||||
extern ULONG STDCALL Ext2CreateFile(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PtrExt2VCB PtrVCB,
|
||||
PUNICODE_STRING PtrName,
|
||||
PtrExt2FCB PtrParentFCB,
|
||||
ULONG Type);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2OverwriteFile(
|
||||
PtrExt2FCB PtrFCB,
|
||||
PtrExt2IrpContext PtrIrpContext);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2SupersedeFile(
|
||||
PtrExt2FCB PtrFCB,
|
||||
PtrExt2IrpContext PtrIrpContext);
|
||||
|
||||
/*************************************************************************
|
||||
* Prototypes for the file misc.c
|
||||
*************************************************************************/
|
||||
extern NTSTATUS STDCALL Ext2InitializeZones(
|
||||
void);
|
||||
|
||||
extern void STDCALL Ext2DestroyZones(
|
||||
void);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2IsIrpTopLevel(
|
||||
PIRP Irp); // the IRP sent to our dispatch routine
|
||||
|
||||
extern long STDCALL Ext2ExceptionFilter(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PEXCEPTION_POINTERS PtrExceptionPointers);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2ExceptionHandler(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP Irp);
|
||||
|
||||
extern void STDCALL Ext2LogEvent(
|
||||
NTSTATUS Ext2EventLogId, // the Ext2 private message id
|
||||
NTSTATUS RC); // any NT error code we wish to log ...
|
||||
|
||||
extern PtrExt2ObjectName STDCALL Ext2AllocateObjectName(
|
||||
void);
|
||||
|
||||
extern void STDCALL Ext2ReleaseObjectName(
|
||||
PtrExt2ObjectName PtrObjectName);
|
||||
|
||||
extern PtrExt2CCB STDCALL Ext2AllocateCCB(
|
||||
void );
|
||||
|
||||
extern PtrExt2FCB STDCALL Ext2GetUsedFCB(
|
||||
PtrExt2VCB PtrVCB );
|
||||
|
||||
extern BOOLEAN STDCALL Ext2CloseClosableFCB(
|
||||
PtrExt2FCB PtrFCB );
|
||||
|
||||
extern void STDCALL Ext2ReleaseCCB(
|
||||
PtrExt2CCB PtrCCB);
|
||||
|
||||
extern PtrExt2FCB STDCALL Ext2AllocateFCB(
|
||||
void);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2CreateNewFCB(
|
||||
PtrExt2FCB *ReturnedFCB,
|
||||
LARGE_INTEGER AllocationSize,
|
||||
LARGE_INTEGER EndOfFile,
|
||||
PFILE_OBJECT PtrFileObject,
|
||||
PtrExt2VCB PtrVCB,
|
||||
PtrExt2ObjectName PtrObjectName);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2CreateNewCCB(
|
||||
PtrExt2CCB *ReturnedCCB,
|
||||
PtrExt2FCB PtrFCB,
|
||||
PFILE_OBJECT PtrFileObject);
|
||||
|
||||
extern void STDCALL Ext2ReleaseFCB(
|
||||
PtrExt2FCB PtrFCB);
|
||||
|
||||
extern PtrExt2FileLockInfo STDCALL Ext2AllocateByteLocks(
|
||||
void);
|
||||
|
||||
extern void STDCALL Ext2ReleaseByteLocks(
|
||||
PtrExt2FileLockInfo PtrByteLocks);
|
||||
|
||||
extern PtrExt2IrpContext STDCALL Ext2AllocateIrpContext(
|
||||
PIRP Irp,
|
||||
PDEVICE_OBJECT PtrTargetDeviceObject);
|
||||
|
||||
extern void STDCALL Ext2ReleaseIrpContext(
|
||||
PtrExt2IrpContext PtrIrpContext);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2PostRequest(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp);
|
||||
|
||||
extern void STDCALL Ext2CommonDispatch(
|
||||
void *Context); // actually an IRPContext structure
|
||||
|
||||
extern void STDCALL Ext2InitializeVCB(
|
||||
PDEVICE_OBJECT PtrVolumeDeviceObject,
|
||||
PDEVICE_OBJECT PtrTargetDeviceObject,
|
||||
PVPB PtrVPB,
|
||||
PLARGE_INTEGER AllocationSize);
|
||||
|
||||
extern void STDCALL Ext2CompleteRequest(
|
||||
IN PIRP Irp OPTIONAL,
|
||||
IN NTSTATUS Status
|
||||
);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2DenyAccess(
|
||||
IN PIRP Irp
|
||||
);
|
||||
extern NTSTATUS STDCALL Ext2GetFCB_CCB_VCB_FromFileObject(
|
||||
IN PFILE_OBJECT PtrFileObject,
|
||||
OUT PtrExt2FCB *PPtrFCB,
|
||||
OUT PtrExt2CCB *PPtrCCB,
|
||||
OUT PtrExt2VCB *PPtrVCB );
|
||||
|
||||
extern void STDCALL Ext2CopyUnicodeString(
|
||||
IN OUT PUNICODE_STRING PtrDestinationString,
|
||||
IN PUNICODE_STRING PtrSourceString );
|
||||
|
||||
extern void STDCALL Ext2CopyWideCharToUnicodeString(
|
||||
IN OUT PUNICODE_STRING PtrDestinationString,
|
||||
IN PCWSTR PtrSourceString );
|
||||
|
||||
extern void STDCALL Ext2CopyCharToUnicodeString(
|
||||
IN OUT PUNICODE_STRING PtrDestinationString,
|
||||
IN PCSTR PtrSourceString,
|
||||
IN USHORT SourceStringLength );
|
||||
|
||||
extern void STDCALL Ext2CopyZCharToUnicodeString(
|
||||
IN OUT PUNICODE_STRING PtrDestinationString,
|
||||
IN PCSTR PtrSourceString );
|
||||
|
||||
extern void STDCALL Ext2DeallocateUnicodeString(
|
||||
PUNICODE_STRING PtrUnicodeString );
|
||||
|
||||
extern void STDCALL Ext2ZerooutUnicodeString(
|
||||
PUNICODE_STRING PtrUnicodeString );
|
||||
|
||||
extern BOOLEAN STDCALL Ext2SaveBCB(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PBCB PtrBCB,
|
||||
PFILE_OBJECT PtrFileObject);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2FlushSavedBCBs(
|
||||
PtrExt2IrpContext PtrIrpContext);
|
||||
|
||||
extern BOOLEAN STDCALL AssertBCB(
|
||||
PBCB PtrBCB);
|
||||
|
||||
extern ULONG STDCALL Ext2Align(
|
||||
ULONG NumberToBeAligned,
|
||||
ULONG Alignment);
|
||||
|
||||
extern LONGLONG STDCALL Ext2Align64(
|
||||
LONGLONG NumberToBeAligned,
|
||||
LONGLONG Alignment);
|
||||
|
||||
extern ULONG STDCALL Ext2GetCurrentTime();
|
||||
|
||||
/*************************************************************************
|
||||
* Prototypes for the file cleanup.c
|
||||
*************************************************************************/
|
||||
extern NTSTATUS STDCALL Ext2Cleanup(
|
||||
PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
PIRP Irp); // I/O Request Packet
|
||||
|
||||
extern NTSTATUS STDCALL Ext2CommonCleanup(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp,
|
||||
BOOLEAN FirstAttempt );
|
||||
|
||||
/*************************************************************************
|
||||
* Prototypes for the file close.c
|
||||
*************************************************************************/
|
||||
extern NTSTATUS STDCALL Ext2Close(
|
||||
PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
PIRP Irp); // I/O Request Packet
|
||||
|
||||
extern NTSTATUS STDCALL Ext2CommonClose(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp,
|
||||
BOOLEAN FirstAttempt );
|
||||
|
||||
/*************************************************************************
|
||||
* Prototypes for the file read.c
|
||||
*************************************************************************/
|
||||
extern NTSTATUS STDCALL Ext2Read(
|
||||
PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
PIRP Irp); // I/O Request Packet
|
||||
|
||||
extern NTSTATUS STDCALL Ext2CommonRead(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp,
|
||||
BOOLEAN FirstAttempt );
|
||||
|
||||
extern void * STDCALL Ext2GetCallersBuffer(
|
||||
PIRP PtrIrp);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2LockCallersBuffer(
|
||||
PIRP PtrIrp,
|
||||
BOOLEAN IsReadOperation,
|
||||
uint32 Length);
|
||||
|
||||
extern void STDCALL Ext2MdlComplete(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp,
|
||||
PIO_STACK_LOCATION PtrIoStackLocation,
|
||||
BOOLEAN ReadCompletion);
|
||||
|
||||
/*************************************************************************
|
||||
* Prototypes for the file write.c
|
||||
*************************************************************************/
|
||||
extern NTSTATUS STDCALL Ext2Write(
|
||||
PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
PIRP Irp); // I/O Request Packet
|
||||
|
||||
extern NTSTATUS STDCALL Ext2CommonWrite(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp);
|
||||
|
||||
extern void STDCALL Ext2DeferredWriteCallBack (
|
||||
void *Context1, // Should be PtrIrpContext
|
||||
void *Context2); // Should be PtrIrp
|
||||
|
||||
/*************************************************************************
|
||||
* Prototypes for the file fileinfo.c
|
||||
*************************************************************************/
|
||||
extern NTSTATUS STDCALL Ext2FileInfo(
|
||||
PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
PIRP Irp); // I/O Request Packet
|
||||
|
||||
extern NTSTATUS STDCALL Ext2CommonFileInfo(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2GetBasicInformation(
|
||||
PtrExt2FCB PtrFCB,
|
||||
PFILE_BASIC_INFORMATION PtrBuffer,
|
||||
long *PtrReturnedLength);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2GetStandardInformation(
|
||||
PtrExt2FCB PtrFCB,
|
||||
PFILE_STANDARD_INFORMATION PtrStdInformation,
|
||||
long *PtrReturnedLength);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2GetNetworkOpenInformation(
|
||||
PtrExt2FCB PtrFCB,
|
||||
PFILE_NETWORK_OPEN_INFORMATION PtrNetworkOpenInformation,
|
||||
long *PtrReturnedLength );
|
||||
|
||||
extern NTSTATUS STDCALL Ext2GetFullNameInformation(
|
||||
PtrExt2FCB PtrFCB,
|
||||
PtrExt2CCB PtrCCB,
|
||||
PFILE_NAME_INFORMATION PtrNameInformation,
|
||||
long *PtrReturnedLength);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2SetBasicInformation(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PtrExt2FCB PtrFCB,
|
||||
PFILE_OBJECT PtrFileObject,
|
||||
PFILE_BASIC_INFORMATION PtrFileInformation );
|
||||
|
||||
extern NTSTATUS STDCALL Ext2SetDispositionInformation(
|
||||
PtrExt2FCB PtrFCB,
|
||||
PtrExt2CCB PtrCCB,
|
||||
PtrExt2VCB PtrVCB,
|
||||
PFILE_OBJECT PtrFileObject,
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp,
|
||||
PFILE_DISPOSITION_INFORMATION PtrBuffer);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2SetAllocationInformation(
|
||||
PtrExt2FCB PtrFCB,
|
||||
PtrExt2CCB PtrCCB,
|
||||
PtrExt2VCB PtrVCB,
|
||||
PFILE_OBJECT PtrFileObject,
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp,
|
||||
PFILE_ALLOCATION_INFORMATION PtrBuffer);
|
||||
|
||||
/*************************************************************************
|
||||
* Prototypes for the file flush.c
|
||||
*************************************************************************/
|
||||
extern NTSTATUS STDCALL Ext2Flush(
|
||||
PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
PIRP Irp); // I/O Request Packet
|
||||
|
||||
extern NTSTATUS STDCALL Ext2CommonFlush(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp);
|
||||
|
||||
extern void STDCALL Ext2FlushAFile(
|
||||
PtrExt2NTRequiredFCB PtrReqdFCB,
|
||||
PIO_STATUS_BLOCK PtrIoStatus);
|
||||
|
||||
extern void STDCALL Ext2FlushLogicalVolume(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp,
|
||||
PtrExt2VCB PtrVCB);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2FlushCompletion(
|
||||
PDEVICE_OBJECT PtrDeviceObject,
|
||||
PIRP PtrIrp,
|
||||
PVOID Context);
|
||||
|
||||
/*************************************************************************
|
||||
* Prototypes for the file dircntrl.c
|
||||
*************************************************************************/
|
||||
extern NTSTATUS STDCALL Ext2DirControl(
|
||||
PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
PIRP Irp); // I/O Request Packet
|
||||
|
||||
extern NTSTATUS STDCALL Ext2CommonDirControl(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2QueryDirectory(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp,
|
||||
PEXTENDED_IO_STACK_LOCATION PtrIoStackLocation,
|
||||
PFILE_OBJECT PtrFileObject,
|
||||
PtrExt2FCB PtrFCB,
|
||||
PtrExt2CCB PtrCCB);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2NotifyChangeDirectory(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp,
|
||||
PEXTENDED_IO_STACK_LOCATION PtrIoStackLocation,
|
||||
PFILE_OBJECT PtrFileObject,
|
||||
PtrExt2FCB PtrFCB,
|
||||
PtrExt2CCB PtrCCB);
|
||||
|
||||
/*************************************************************************
|
||||
* Prototypes for the file devcntrl.c
|
||||
*************************************************************************/
|
||||
extern NTSTATUS STDCALL Ext2DeviceControl(
|
||||
PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
PIRP Irp); // I/O Request Packet
|
||||
|
||||
extern NTSTATUS STDCALL Ext2CommonDeviceControl(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2DevIoctlCompletion(
|
||||
PDEVICE_OBJECT PtrDeviceObject,
|
||||
PIRP PtrIrp,
|
||||
void *Context);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2HandleQueryPath(
|
||||
void *BufferPointer);
|
||||
|
||||
/*************************************************************************
|
||||
* Prototypes for the file shutdown.c
|
||||
*************************************************************************/
|
||||
extern NTSTATUS STDCALL Ext2Shutdown(
|
||||
PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
PIRP Irp); // I/O Request Packet
|
||||
|
||||
extern NTSTATUS STDCALL Ext2CommonShutdown(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp);
|
||||
|
||||
/*************************************************************************
|
||||
* Prototypes for the file volinfo.c
|
||||
*************************************************************************/
|
||||
extern NTSTATUS STDCALL Ext2QueryVolInfo(
|
||||
PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
PIRP Irp); // I/O Request Packet
|
||||
|
||||
NTSTATUS STDCALL Ext2SetVolInfo(
|
||||
IN PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
IN PIRP Irp); // I/O Request Packet
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Prototypes for the file fastio.c
|
||||
*************************************************************************/
|
||||
extern BOOLEAN STDCALL Ext2FastIoCheckIfPossible(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN PLARGE_INTEGER FileOffset,
|
||||
IN ULONG Length,
|
||||
IN BOOLEAN Wait,
|
||||
IN ULONG LockKey,
|
||||
IN BOOLEAN CheckForReadOperation,
|
||||
OUT PIO_STATUS_BLOCK IoStatus,
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2FastIoRead(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN PLARGE_INTEGER FileOffset,
|
||||
IN ULONG Length,
|
||||
IN BOOLEAN Wait,
|
||||
IN ULONG LockKey,
|
||||
OUT PVOID Buffer,
|
||||
OUT PIO_STATUS_BLOCK IoStatus,
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2FastIoWrite(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN PLARGE_INTEGER FileOffset,
|
||||
IN ULONG Length,
|
||||
IN BOOLEAN Wait,
|
||||
IN ULONG LockKey,
|
||||
OUT PVOID Buffer,
|
||||
OUT PIO_STATUS_BLOCK IoStatus,
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2FastIoQueryBasicInfo(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN BOOLEAN Wait,
|
||||
OUT PFILE_BASIC_INFORMATION Buffer,
|
||||
OUT PIO_STATUS_BLOCK IoStatus,
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2FastIoQueryStdInfo(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN BOOLEAN Wait,
|
||||
OUT PFILE_STANDARD_INFORMATION Buffer,
|
||||
OUT PIO_STATUS_BLOCK IoStatus,
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2FastIoLock(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN PLARGE_INTEGER FileOffset,
|
||||
IN PLARGE_INTEGER Length,
|
||||
PEPROCESS ProcessId,
|
||||
ULONG Key,
|
||||
BOOLEAN FailImmediately,
|
||||
BOOLEAN ExclusiveLock,
|
||||
OUT PIO_STATUS_BLOCK IoStatus,
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2FastIoUnlockSingle(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN PLARGE_INTEGER FileOffset,
|
||||
IN PLARGE_INTEGER Length,
|
||||
PEPROCESS ProcessId,
|
||||
ULONG Key,
|
||||
OUT PIO_STATUS_BLOCK IoStatus,
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2FastIoUnlockAll(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
PEPROCESS ProcessId,
|
||||
OUT PIO_STATUS_BLOCK IoStatus,
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2FastIoUnlockAllByKey(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
PEPROCESS ProcessId,
|
||||
ULONG Key,
|
||||
OUT PIO_STATUS_BLOCK IoStatus,
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
extern void STDCALL Ext2FastIoAcqCreateSec(
|
||||
IN PFILE_OBJECT FileObject);
|
||||
|
||||
extern void STDCALL Ext2FastIoRelCreateSec(
|
||||
IN PFILE_OBJECT FileObject);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2AcqLazyWrite(
|
||||
IN PVOID Context,
|
||||
IN BOOLEAN Wait);
|
||||
|
||||
extern void STDCALL Ext2RelLazyWrite(
|
||||
IN PVOID Context);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2AcqReadAhead(
|
||||
IN PVOID Context,
|
||||
IN BOOLEAN Wait);
|
||||
|
||||
extern void STDCALL Ext2RelReadAhead(
|
||||
IN PVOID Context);
|
||||
|
||||
// the remaining are only valid under NT Version 4.0 and later
|
||||
#if(_WIN32_WINNT >= 0x0400)
|
||||
|
||||
extern BOOLEAN STDCALL Ext2FastIoQueryNetInfo(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN BOOLEAN Wait,
|
||||
OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
|
||||
OUT PIO_STATUS_BLOCK IoStatus,
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2FastIoMdlRead(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN PLARGE_INTEGER FileOffset,
|
||||
IN ULONG Length,
|
||||
IN ULONG LockKey,
|
||||
OUT PMDL *MdlChain,
|
||||
OUT PIO_STATUS_BLOCK IoStatus,
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2FastIoMdlReadComplete(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
OUT PMDL MdlChain,
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2FastIoPrepareMdlWrite(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN PLARGE_INTEGER FileOffset,
|
||||
IN ULONG Length,
|
||||
IN ULONG LockKey,
|
||||
OUT PMDL *MdlChain,
|
||||
OUT PIO_STATUS_BLOCK IoStatus,
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2FastIoMdlWriteComplete(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN PLARGE_INTEGER FileOffset,
|
||||
OUT PMDL MdlChain,
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2FastIoAcqModWrite(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN PLARGE_INTEGER EndingOffset,
|
||||
OUT PERESOURCE *ResourceToRelease,
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2FastIoRelModWrite(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN PERESOURCE ResourceToRelease,
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2FastIoAcqCcFlush(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2FastIoRelCcFlush(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
#endif // (_WIN32_WINNT >= 0x0400)
|
||||
|
||||
/*************************************************************************
|
||||
* Prototypes for the file DiskIO.c
|
||||
*************************************************************************/
|
||||
extern NTSTATUS STDCALL Ext2ReadLogicalBlocks(
|
||||
PDEVICE_OBJECT PtrTargetDeviceObject, // the Target Device Object
|
||||
VOID *Buffer, // The Buffer that takes the data read in
|
||||
LARGE_INTEGER StartLogicalBlock, // The logical block from which reading is to start
|
||||
unsigned int NoOfLogicalBlocks); // The no. of logical blocks to be read
|
||||
|
||||
extern NTSTATUS STDCALL Ext2ReadPhysicalBlocks(
|
||||
PDEVICE_OBJECT PtrTargetDeviceObject, // the Target Device Object
|
||||
VOID *Buffer, // The Buffer that takes the data read in
|
||||
LARGE_INTEGER StartBlock, // The Physical block from which reading is to start
|
||||
unsigned int NoOfBlocks); // The no. of Physical blocks to be read
|
||||
|
||||
/*************************************************************************
|
||||
* Prototypes for the file metadata.c
|
||||
*************************************************************************/
|
||||
|
||||
extern void STDCALL Ext2InitializeFCBInodeInfo (
|
||||
PtrExt2FCB PtrFCB );
|
||||
|
||||
extern NTSTATUS STDCALL Ext2ReadInode(
|
||||
PtrExt2VCB PtrVcb, // the Volume Control Block
|
||||
uint32 InodeNo, // The Inode no
|
||||
PEXT2_INODE PtrInode ); // The Inode Buffer
|
||||
|
||||
extern NTSTATUS STDCALL Ext2WriteInode(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PtrExt2VCB PtrVcb, // the Volume Control Block
|
||||
uint32 InodeNo, // The Inode no
|
||||
PEXT2_INODE PtrInode // The Inode Buffer
|
||||
);
|
||||
|
||||
extern ULONG STDCALL Ext2AllocInode(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PtrExt2VCB PtrVCB,
|
||||
ULONG ParentINodeNo );
|
||||
|
||||
extern BOOLEAN STDCALL Ext2DeallocInode(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PtrExt2VCB PtrVCB,
|
||||
ULONG INodeNo );
|
||||
|
||||
extern BOOLEAN STDCALL Ext2MakeNewDirectoryEntry(
|
||||
PtrExt2IrpContext PtrIrpContext, // The Irp context
|
||||
PtrExt2FCB PtrParentFCB, // Parent Folder FCB
|
||||
PFILE_OBJECT PtrFileObject, // Parent Folder Object
|
||||
PUNICODE_STRING PtrName, // New entry's name
|
||||
ULONG Type, // The type of the new entry
|
||||
ULONG NewInodeNo); // The inode no of the new entry...
|
||||
|
||||
extern BOOLEAN STDCALL Ext2FreeDirectoryEntry(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PtrExt2FCB PtrParentFCB,
|
||||
PUNICODE_STRING PtrName);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2AddBlockToFile(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PtrExt2VCB PtrVCB,
|
||||
PtrExt2FCB PtrFCB,
|
||||
PFILE_OBJECT PtrFileObject,
|
||||
BOOLEAN UpdateFileSize);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2ReleaseDataBlocks(
|
||||
PtrExt2FCB PtrFCB,
|
||||
PtrExt2IrpContext PtrIrpContext);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2TruncateFileAllocationSize(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PtrExt2FCB PtrFCB,
|
||||
PFILE_OBJECT PtrFileObject,
|
||||
PLARGE_INTEGER PtrAllocationSize );
|
||||
|
||||
extern ULONG STDCALL Ext2AllocBlock(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PtrExt2VCB PtrVCB,
|
||||
ULONG Count);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2DeallocBlock(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PtrExt2VCB PtrVCB,
|
||||
ULONG BlockNo);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2UpdateFileSize(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PFILE_OBJECT PtrFileObject,
|
||||
PtrExt2FCB PtrFCB);
|
||||
|
||||
|
||||
extern BOOLEAN STDCALL Ext2DeleteFile(
|
||||
PtrExt2FCB PtrFCB,
|
||||
PtrExt2IrpContext PtrIrpContext);
|
||||
|
||||
extern BOOLEAN STDCALL Ext2IsDirectoryEmpty(
|
||||
PtrExt2FCB PtrFCB,
|
||||
PtrExt2CCB PtrCCB,
|
||||
PtrExt2IrpContext PtrIrpContext);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2RenameOrLinkFile(
|
||||
PtrExt2FCB PtrSourceFCB,
|
||||
PFILE_OBJECT PtrSourceFileObject,
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp,
|
||||
PFILE_RENAME_INFORMATION PtrRenameInfo);
|
||||
/*************************************************************************
|
||||
* Prototypes for the file io.c
|
||||
*************************************************************************/
|
||||
extern NTSTATUS STDCALL Ext2PassDownSingleReadWriteIRP(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp,
|
||||
PtrExt2VCB PtrVCB,
|
||||
LARGE_INTEGER ByteOffset,
|
||||
uint32 ReadWriteLength,
|
||||
BOOLEAN SynchronousIo);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2PassDownMultiReadWriteIRP(
|
||||
PEXT2_IO_RUN PtrIoRuns,
|
||||
UINT Count,
|
||||
ULONG TotalReadWriteLength,
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PtrExt2FCB PtrFCB,
|
||||
BOOLEAN SynchronousIo);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2SingleSyncCompletionRoutine(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Contxt
|
||||
);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2SingleAsyncCompletionRoutine (
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Contxt
|
||||
);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2MultiSyncCompletionRoutine(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Contxt);
|
||||
|
||||
extern NTSTATUS STDCALL Ext2MultiAsyncCompletionRoutine(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Contxt);
|
||||
|
||||
#endif // _EXT2_PROTOS_H_
|
16
reactos/drivers/filesystems/ext2/inc/resource.h
Normal file
16
reactos/drivers/filesystems/ext2/inc/resource.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by D:\Work\VC\Drivers\ext2FSD\src\ext2.rc
|
||||
//
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NO_MFC 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
674
reactos/drivers/filesystems/ext2/inc/struct.h
Normal file
674
reactos/drivers/filesystems/ext2/inc/struct.h
Normal file
|
@ -0,0 +1,674 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* File: struct.h
|
||||
*
|
||||
* Module: Ext2 File System Driver (Kernel mode execution only)
|
||||
*
|
||||
* Description:
|
||||
* This file contains structure definitions for the sample file system
|
||||
* driver. Note that all structures are prefixed with the letters
|
||||
* "Ext2". The structures are all aligned using normal alignment
|
||||
* used by the compiler (typically quad-word aligned).
|
||||
*
|
||||
* Author: Manoj Paul Joseph
|
||||
*
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef _EXT2_STRUCTURES_H_
|
||||
#define _EXT2_STRUCTURES_H_
|
||||
|
||||
/**************************************************************************
|
||||
some useful definitions
|
||||
**************************************************************************/
|
||||
#ifdef _CPU_X86_
|
||||
typedef char int8;
|
||||
typedef short int16;
|
||||
typedef int int32;
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned int uint32;
|
||||
|
||||
typedef PVOID PBCB;
|
||||
|
||||
// we will use the LARGE_INTEGER structure as defined by NT
|
||||
|
||||
#else // Please define appropriate types here
|
||||
|
||||
!!!! You must define your types here for compilation to proceed !!!!
|
||||
|
||||
#endif // if _CPU_X86_
|
||||
|
||||
/**************************************************************************
|
||||
some empty typedefs defined here so we can reference them easily
|
||||
**************************************************************************/
|
||||
struct _Ext2Identifier;
|
||||
struct _Ext2ObjectName;
|
||||
struct _Ext2ContextControlBlock;
|
||||
struct _Ext2NTRequiredFCB;
|
||||
struct _Ext2DiskDependentFCB;
|
||||
struct _Ext2FileControlBlock;
|
||||
struct _Ext2FileByteLocks;
|
||||
struct _Ext2VolumeControlBlock;
|
||||
struct _Ext2IrpContext;
|
||||
struct _Ext2Data;
|
||||
|
||||
/**************************************************************************
|
||||
each structure has a unique "node type" or signature associated with it
|
||||
**************************************************************************/
|
||||
#define EXT2_NODE_TYPE_OBJECT_NAME (0xfdecba01)
|
||||
#define EXT2_NODE_TYPE_CCB (0xfdecba02)
|
||||
#define EXT2_NODE_TYPE_FCB (0xfdecba03)
|
||||
#define EXT2_NODE_TYPE_LOCKS (0xfdecba04)
|
||||
#define EXT2_NODE_TYPE_VCB (0xfdecba05)
|
||||
#define EXT2_NODE_TYPE_IRP_CONTEXT (0xfdecba06)
|
||||
#define EXT2_NODE_TYPE_GLOBAL_DATA (0xfdecba07)
|
||||
#define EXT2_NODE_TYPE_IO_CONTEXT (0xfdecba08)
|
||||
#define EXT2_NODE_TYPE_SAVED_BCB (0xfdecba09)
|
||||
#define EXT2_NODE_TYPE_FREED (0x10101010)
|
||||
#define EXT2_NODE_TYPE_INVALID (0x10101010)
|
||||
|
||||
/**************************************************************************
|
||||
every structure has a node type, and a node size associated with it.
|
||||
The node type serves as a signature field. The size is used for
|
||||
consistency checking ...
|
||||
**************************************************************************/
|
||||
typedef struct _Ext2Identifier {
|
||||
uint32 NodeType; // a 32 bit identifier for the structure
|
||||
uint32 NodeSize; // computed as sizeof(structure)
|
||||
} Ext2Identifier, *PtrExt2Identifier;
|
||||
|
||||
/**************************************************************************
|
||||
Structures for byte-range lock support.
|
||||
**************************************************************************/
|
||||
typedef struct Ext2FileLockAnchor {
|
||||
LIST_ENTRY GrantedFileLockList;
|
||||
LIST_ENTRY PendingFileLockList;
|
||||
} Ext2FileLockAnchor, *PtrExt2FileLockAnchor;
|
||||
|
||||
typedef struct Ext2FileLockInfo {
|
||||
Ext2Identifier NodeIdentifier;
|
||||
uint32 FileLockFlags;
|
||||
PVOID OwningProcess;
|
||||
LARGE_INTEGER StartingOffset;
|
||||
LARGE_INTEGER Length;
|
||||
LARGE_INTEGER EndingOffset;
|
||||
ULONG Key;
|
||||
BOOLEAN ExclusiveLock;
|
||||
PIRP PendingIRP;
|
||||
LIST_ENTRY NextFileLockEntry;
|
||||
} Ext2FileLockInfo, *PtrExt2FileLockInfo;
|
||||
|
||||
#define EXT2_BYTE_LOCK_NOT_FROM_ZONE (0x80000000)
|
||||
#define EXT2_BYTE_LOCK_IS_PENDING (0x00000001)
|
||||
|
||||
/**************************************************************************
|
||||
Every open on-disk object must have a name associated with it
|
||||
This name has two components:
|
||||
(a) the path-name (prefix) that leads to this on-disk object
|
||||
(b) the name of the object itself
|
||||
Note that with multiply linked objects, a single object might be
|
||||
associated with more than one name structure.
|
||||
This sample FSD does not correctly support multiply linked objects.
|
||||
|
||||
This structure must be quad-word aligned because it is zone allocated.
|
||||
**************************************************************************/
|
||||
typedef struct _Ext2ObjectName {
|
||||
Ext2Identifier NodeIdentifier;
|
||||
uint32 ObjectNameFlags;
|
||||
// an absolute pathname of the object is stored below
|
||||
UNICODE_STRING ObjectName;
|
||||
} Ext2ObjectName, *PtrExt2ObjectName;
|
||||
|
||||
#define EXT2_OB_NAME_NOT_FROM_ZONE (0x80000000)
|
||||
|
||||
/**************************************************************************
|
||||
Each file open instance is represented by a context control block.
|
||||
For each successful create/open request; a file object and a CCB will
|
||||
be created.
|
||||
For open operations performed internally by the FSD, there may not
|
||||
exist file objects; but a CCB will definitely be created.
|
||||
|
||||
This structure must be quad-word aligned because it is zone allocated.
|
||||
**************************************************************************/
|
||||
typedef struct _Ext2ContextControlBlock {
|
||||
Ext2Identifier NodeIdentifier;
|
||||
// ptr to the associated FCB
|
||||
struct _Ext2FileControlBlock *PtrFCB;
|
||||
// all CCB structures for a FCB are linked together
|
||||
LIST_ENTRY NextCCB;
|
||||
// each CCB is associated with a file object
|
||||
PFILE_OBJECT PtrFileObject;
|
||||
// flags (see below) associated with this CCB
|
||||
uint32 CCBFlags;
|
||||
// current byte offset is required sometimes
|
||||
LARGE_INTEGER CurrentByteOffset;
|
||||
// if this CCB represents a directory object open, we may
|
||||
// need to maintain a search pattern
|
||||
|
||||
// PSTRING DirectorySearchPattern;
|
||||
UNICODE_STRING DirectorySearchPattern;
|
||||
|
||||
// The full path name for the file...
|
||||
UNICODE_STRING AbsolutePathName;
|
||||
|
||||
// Rename/Link Target file name
|
||||
// Used only in a Rename/Link operation
|
||||
UNICODE_STRING RenameLinkTargetFileName;
|
||||
|
||||
// we must maintain user specified file time values
|
||||
uint32 UserSpecifiedTime;
|
||||
|
||||
|
||||
} Ext2CCB, *PtrExt2CCB;
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
the following CCBFlags values are relevant. These flag
|
||||
values are bit fields; therefore we can test whether
|
||||
a bit position is set (1) or not set (0).
|
||||
**************************************************************************/
|
||||
|
||||
// some on-disk file/directories are opened by EXT2 itself
|
||||
// as opposed to being opened on behalf of a user process
|
||||
#define EXT2_CCB_OPENED_BY_EXT2 (0x00000001)
|
||||
// the file object specified synchronous access at create/open time.
|
||||
// this implies that EXT2 must maintain the current byte offset
|
||||
#define EXT2_CCB_OPENED_FOR_SYNC_ACCESS (0x00000002)
|
||||
// file object specified sequential access for this file
|
||||
#define EXT2_CCB_OPENED_FOR_SEQ_ACCESS (0x00000004)
|
||||
// the CCB has had an IRP_MJ_CLEANUP issued on it. we must
|
||||
// no longer allow the file object / CCB to be used in I/O requests.
|
||||
#define EXT2_CCB_CLEANED (0x00000008)
|
||||
// if we were invoked via the fast i/o path to perform file i/o;
|
||||
// we should set the CCB access/modification time at cleanup
|
||||
#define EXT2_CCB_ACCESSED (0x00000010)
|
||||
#define EXT2_CCB_MODIFIED (0x00000020)
|
||||
// if an application process set the file date time, we must
|
||||
// honor that request and *not* overwrite the values at cleanup
|
||||
#define EXT2_CCB_ACCESS_TIME_SET (0x00000040)
|
||||
#define EXT2_CCB_MODIFY_TIME_SET (0x00000080)
|
||||
#define EXT2_CCB_CREATE_TIME_SET (0x00000100)
|
||||
|
||||
#define EXT2_CCB_NOT_FROM_ZONE (0x80000000)
|
||||
|
||||
// this CCB was allocated for a "volume open" operation
|
||||
#define EXT2_CCB_VOLUME_OPEN (0x00000100)
|
||||
|
||||
/**************************************************************************
|
||||
each open file/directory/volume is represented by a file control block.
|
||||
NOTE: Currently, EXT2 does not handle multiply linked files correctly.
|
||||
In your FSD implementation, you must be careful about handling
|
||||
such on-disk files correctly i.e. a single (unique) FCB must
|
||||
represent an on-disk file/directory regardless of the path used
|
||||
to access the on-disk object.
|
||||
With the current EXT2 implementation, an on-disk file object
|
||||
with more than a single (hard) link will be treated incorrectly!
|
||||
|
||||
Each FCB can logically be divided into two:
|
||||
(a) a structure that must have a field of type FSRTL_COMMON_FCB_HEADER
|
||||
as the first field in the structure.
|
||||
This portion should also contain other structures/resources required
|
||||
by the NT Cache Manager
|
||||
We will call this structure the "NT Required" FCB. Note that this
|
||||
portion of the FCB must be allocated from non-paged pool.
|
||||
(b) the remainder of the FCB is dependent upon the particular FSD
|
||||
requirements.
|
||||
This portion of the FCB could possibly be allocated from paged
|
||||
memory, though in the sample FSD, it will always be allocated
|
||||
from non-paged pool.
|
||||
|
||||
FCB structures are protected by the MainResource as well as the
|
||||
PagingIoResource. Of course, if your FSD implementation requires
|
||||
it, you can associate other syncronization structures with the
|
||||
FCB.
|
||||
|
||||
This structure must be quad-word aligned because it is zone allocated.
|
||||
**************************************************************************/
|
||||
typedef struct _Ext2NTRequiredFCB
|
||||
{
|
||||
FSRTL_COMMON_FCB_HEADER CommonFCBHeader;
|
||||
SECTION_OBJECT_POINTERS SectionObject;
|
||||
ERESOURCE MainResource;
|
||||
ERESOURCE PagingIoResource;
|
||||
} Ext2NTRequiredFCB, *PtrExt2NTRequiredFCB;
|
||||
|
||||
typedef struct _Ext2DiskDependentFCB
|
||||
{
|
||||
// although the sample FSD does not maintain on-disk data structures,
|
||||
// this structure serves as a reminder of the logical separation that
|
||||
// your FSD can maintain between the disk dependent and the disk
|
||||
// independent portions of the FCB.
|
||||
uint16 DummyField; // placeholder
|
||||
} Ext2DiskDependentFCB, *PtrExt2DiskDependentFCB;
|
||||
|
||||
typedef struct _Ext2FileControlBlock
|
||||
{
|
||||
Ext2Identifier NodeIdentifier;
|
||||
// we will go ahead and embed the "NT Required FCB" right here.
|
||||
// Note though that it is just as acceptable to simply allocate
|
||||
// memory separately for the other half of the FCB and store a
|
||||
// pointer to the "NT Required" portion here instead of embedding
|
||||
// it ...
|
||||
Ext2NTRequiredFCB NTRequiredFCB;
|
||||
// the disk dependent portion of the FCB is embedded right here
|
||||
Ext2DiskDependentFCB DiskDependentFCB;
|
||||
// this FCB belongs to some mounted logical volume
|
||||
struct _Ext2VolumeControlBlock *PtrVCB;
|
||||
// to be able to access all open file(s) for a volume, we will
|
||||
// link all FCB structures for a logical volume together
|
||||
LIST_ENTRY NextFCB;
|
||||
|
||||
// to be used if this FCB is on the Closable FCB List...
|
||||
struct _ClosableFCBs
|
||||
{
|
||||
LIST_ENTRY ClosableFCBList;
|
||||
BOOLEAN OnClosableFCBList;
|
||||
}ClosableFCBs;
|
||||
|
||||
// some state information for the FCB is maintained using the
|
||||
// flags field
|
||||
uint32 FCBFlags;
|
||||
// all CCB's for this particular FCB are linked off the following
|
||||
// list head.
|
||||
LIST_ENTRY CCBListHead;
|
||||
// NT requires that a file system maintain and honor the various
|
||||
// SHARE_ACCESS modes ...
|
||||
SHARE_ACCESS FCBShareAccess;
|
||||
// to identify the lazy writer thread(s) we will grab and store
|
||||
// the thread id here when a request to acquire resource(s)
|
||||
// arrives ..
|
||||
uint32 LazyWriterThreadID;
|
||||
// whenever a file stream has a create/open operation performed,
|
||||
// the Reference count below is incremented AND the OpenHandle count
|
||||
// below is also incremented.
|
||||
// When an IRP_MJ_CLEANUP is received, the OpenHandle count below
|
||||
// is decremented.
|
||||
// When an IRP_MJ_CLOSE is received, the Reference count below is
|
||||
// decremented.
|
||||
// When the Reference count goes down to zero, the FCB can be de-allocated.
|
||||
// Note that a zero Reference count implies a zero OpenHandle count.
|
||||
// This invariant must always hold true ... (if it is really an invariant,
|
||||
// shoudn't the previous statement be redundant ... hmmm!!!)
|
||||
LONG ReferenceCount;
|
||||
LONG OpenHandleCount;
|
||||
// for the sample fsd, there exists a 1-1 correspondence between an
|
||||
// object name structure and a FCB
|
||||
PtrExt2ObjectName FCBName;
|
||||
// we will maintain some time information here to make our life easier
|
||||
LARGE_INTEGER CreationTime;
|
||||
LARGE_INTEGER LastAccessTime;
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
// Byte-range file lock support (we roll our own)
|
||||
Ext2FileLockAnchor FCBByteRangeLock;
|
||||
// The OPLOCK support package requires the following structure
|
||||
OPLOCK FCBOplock;
|
||||
|
||||
// The I-Node no of this file / folder
|
||||
ULONG INodeNo;
|
||||
ULONG ParentINodeNo;
|
||||
// Pointers to blocks
|
||||
uint32 IBlock[EXT2_N_BLOCKS];
|
||||
|
||||
USHORT LinkCount;
|
||||
union _DCBFCB
|
||||
{
|
||||
struct
|
||||
{
|
||||
PFILE_OBJECT PtrDirFileObject;
|
||||
} Dcb;
|
||||
|
||||
struct _FCB
|
||||
{
|
||||
PFILE_OBJECT PtrDirFileObject;
|
||||
// FCB specific stuff go here...
|
||||
} Fcb;
|
||||
|
||||
}DcbFcb;
|
||||
|
||||
} Ext2FCB, *PtrExt2FCB, Ext2DCB, *PtrExt2DCB;
|
||||
|
||||
/**************************************************************************
|
||||
the following FCBFlags values are relevant. These flag
|
||||
values are bit fields; therefore we can test whether
|
||||
a bit position is set (1) or not set (0).
|
||||
**************************************************************************/
|
||||
#define EXT2_FCB_IN_INIT (0x00000001)
|
||||
#define EXT2_FCB_IN_TEARDOWN (0x00000002)
|
||||
#define EXT2_FCB_PAGE_FILE (0x00000004)
|
||||
#define EXT2_FCB_DIRECTORY (0x00000008)
|
||||
#define EXT2_FCB_ROOT_DIRECTORY (0x00000018)
|
||||
#define EXT2_FCB_WRITE_THROUGH (0x00000020)
|
||||
#define EXT2_FCB_MAPPED (0x00000040)
|
||||
#define EXT2_FCB_FAST_IO_READ_IN_PROGESS (0x00000080)
|
||||
#define EXT2_FCB_FAST_IO_WRITE_IN_PROGESS (0x00000100)
|
||||
#define EXT2_FCB_DELETE_ON_CLOSE (0x00000200)
|
||||
#define EXT2_FCB_MODIFIED (0x00000400)
|
||||
#define EXT2_FCB_ACCESSED (0x00000800)
|
||||
#define EXT2_FCB_READ_ONLY (0x00001000)
|
||||
|
||||
#define EXT2_INITIALIZED_MAIN_RESOURCE (0x00002000)
|
||||
#define EXT2_INITIALIZED_PAGING_IO_RESOURCE (0x00004000)
|
||||
#define EXT2_FCB_BLOCKS_INITIALIZED (0x00008000)
|
||||
#define EXT2_FCB_SPECIAL_FILE (0x00010000)
|
||||
#define EXT2_FCB_HIDDEN_FILE (0x00020000)
|
||||
#define EXT2_FCB_NOT_FROM_ZONE (0x80000000)
|
||||
|
||||
|
||||
typedef struct _GroupDescriptors
|
||||
{
|
||||
uint32 InodeTablesBlock; /* Inodes table block => bg_inode_table */
|
||||
uint32 InodeBitmapBlock; /* Inodes bitmap block => bg_inode_bitmap */
|
||||
uint32 BlockBitmapBlock; /* Blocks bitmap block => bg_block_bitmap */
|
||||
uint32 FreeBlocksCount;
|
||||
uint32 FreeInodesCount;
|
||||
}Ext2GroupDescriptors, *PtrExt2GroupDescriptors;
|
||||
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
A logical volume is represented using the following structure.
|
||||
This structure is allocated as part of the device extension
|
||||
for a device object that this sample FSD will create, to represent
|
||||
the mounted logical volume.
|
||||
|
||||
NOTE: If you were to extend this sample FSD to be a "real" FSD,
|
||||
you would be worried about allocated clusters/sectiors,
|
||||
bitmaps providing such information for the mounted volume,
|
||||
dirty/modified clusters/sectiors etc.
|
||||
This sample FSD does not maintain such information in the
|
||||
in-memory VCB, though you may wish to consider it.
|
||||
**************************************************************************/
|
||||
typedef struct _Ext2VolumeControlBlock
|
||||
{
|
||||
Ext2Identifier NodeIdentifier;
|
||||
|
||||
// Required to use the Cache Manager.
|
||||
FSRTL_COMMON_FCB_HEADER CommonVCBHeader;
|
||||
SECTION_OBJECT_POINTERS SectionObject;
|
||||
// a resource to protect the fields contained within the VCB
|
||||
ERESOURCE VCBResource;
|
||||
|
||||
// a resource to synchronise paging io
|
||||
ERESOURCE PagingIoResource;
|
||||
|
||||
// Pointer to a stream file object created for the volume information
|
||||
// to be more easily read from secondary storage (with the support of
|
||||
// the NT Cache Manager).
|
||||
PFILE_OBJECT PtrStreamFileObject;
|
||||
|
||||
// each VCB is accessible off a global linked list
|
||||
LIST_ENTRY NextVCB;
|
||||
|
||||
// each VCB points to a VPB structure created by the NT I/O Manager
|
||||
PVPB PtrVPB;
|
||||
|
||||
// a set of flags that might mean something useful
|
||||
uint32 VCBFlags;
|
||||
|
||||
// A count of the number of open files/directories
|
||||
// As long as the count is != 0, the volume cannot
|
||||
// be dismounted or locked.
|
||||
uint32 VCBOpenCount;
|
||||
|
||||
// a global list of all FCB structures associated with the VCB
|
||||
LIST_ENTRY FCBListHead;
|
||||
|
||||
//
|
||||
// a list of FCBs created at the FSD's initiative...
|
||||
// These FCBs have a reference count of 0
|
||||
// This list should never be allowed to cross a limit...
|
||||
//
|
||||
struct Ext2ClosableFCB
|
||||
{
|
||||
LIST_ENTRY ClosableFCBListHead;
|
||||
ULONG Count;
|
||||
}ClosableFCBs;
|
||||
// we will maintain a global list of IRP's that are pending
|
||||
// because of a directory notify request.
|
||||
LIST_ENTRY NextNotifyIRP;
|
||||
// the above list is protected only by the mutex declared below
|
||||
KMUTEX NotifyIRPMutex;
|
||||
// for each mounted volume, we create a device object. Here then
|
||||
// is a back pointer to that device object
|
||||
PDEVICE_OBJECT VCBDeviceObject;
|
||||
// We also retain a pointer to the physical device object on which we
|
||||
// have mounted ourselves. The I/O Manager passes us a pointer to this
|
||||
// device object when requesting a mount operation.
|
||||
PDEVICE_OBJECT TargetDeviceObject;
|
||||
// the volume structure contains a pointer to the root directory FCB
|
||||
PtrExt2FCB PtrRootDirectoryFCB;
|
||||
// the complete name of the user visible drive letter we serve
|
||||
uint8 *PtrVolumePath;
|
||||
// For volume open operations, we do not create a FCB (we use the VCB
|
||||
// directly instead). Therefore, all CCB structures for the volume
|
||||
// open operation are linked directly off the VCB
|
||||
LIST_ENTRY VolumeOpenListHead;
|
||||
|
||||
|
||||
// Volume information
|
||||
ULONG BlocksCount;
|
||||
ULONG InodesCount;
|
||||
ULONG ReservedBlocksCount;
|
||||
ULONG FreeBlocksCount;
|
||||
ULONG FreeInodesCount;
|
||||
ULONG LogBlockSize; // Block size = 1024 << LogBlockSize
|
||||
|
||||
// Group Information Saved up in the VCB...
|
||||
PtrExt2GroupDescriptors PtrGroupDescriptors;
|
||||
ULONG NoOfGroups;
|
||||
|
||||
uint32 InodesPerGroup;
|
||||
uint32 BlocksPerGroup;
|
||||
|
||||
} Ext2VCB, *PtrExt2VCB;
|
||||
|
||||
// some valid flags for the VCB
|
||||
#define EXT2_VCB_FLAGS_VOLUME_MOUNTED (0x00000001)
|
||||
#define EXT2_VCB_FLAGS_VOLUME_LOCKED (0x00000002)
|
||||
#define EXT2_VCB_FLAGS_BEING_DISMOUNTED (0x00000004)
|
||||
#define EXT2_VCB_FLAGS_SHUTDOWN (0x00000008)
|
||||
#define EXT2_VCB_FLAGS_VOLUME_READ_ONLY (0x00000010)
|
||||
|
||||
#define EXT2_VCB_FLAGS_VCB_INITIALIZED (0x00000020)
|
||||
|
||||
typedef struct _EXT2_IO_CONTEXT
|
||||
{
|
||||
Ext2Identifier NodeIdentifier;
|
||||
ULONG ReadWriteLength;
|
||||
LONG Count;
|
||||
PIRP PtrMasterIrp;
|
||||
PKEVENT PtrSyncEvent;
|
||||
|
||||
} EXT2_IO_CONTEXT, *PEXT2_IO_CONTEXT;
|
||||
|
||||
|
||||
typedef struct _Ext2SavedBCBs
|
||||
{
|
||||
Ext2Identifier NodeIdentifier;
|
||||
PBCB PtrBCB;
|
||||
LIST_ENTRY SavedBCBsListEntry;
|
||||
|
||||
} EXT2_SAVED_BCBS, *PEXT2_SAVED_BCBS;
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
The IRP context encapsulates the current request. This structure is
|
||||
used in the "common" dispatch routines invoked either directly in
|
||||
the context of the original requestor, or indirectly in the context
|
||||
of a system worker thread.
|
||||
**************************************************************************/
|
||||
typedef struct _Ext2IrpContext
|
||||
{
|
||||
Ext2Identifier NodeIdentifier;
|
||||
uint32 IrpContextFlags;
|
||||
// copied from the IRP
|
||||
uint8 MajorFunction;
|
||||
// copied from the IRP
|
||||
uint8 MinorFunction;
|
||||
|
||||
// to queue this IRP for asynchronous processing
|
||||
WORK_QUEUE_ITEM WorkQueueItem;
|
||||
// the IRP for which this context structure was created
|
||||
PIRP Irp;
|
||||
// the target of the request (obtained from the IRP)
|
||||
PDEVICE_OBJECT TargetDeviceObject;
|
||||
// if an exception occurs, we will store the code here
|
||||
NTSTATUS SavedExceptionCode;
|
||||
|
||||
// This list entry is used if asnchronous processing is required...
|
||||
LIST_ENTRY ThreadQueueListEntry;
|
||||
|
||||
// This list entry is used if BCBs are to be saved and then flushed...
|
||||
// Could have been put somewhere else...
|
||||
LIST_ENTRY SavedBCBsListHead;
|
||||
ULONG SavedCount;
|
||||
|
||||
} Ext2IrpContext, *PtrExt2IrpContext;
|
||||
|
||||
#define EXT2_IRP_CONTEXT_CAN_BLOCK (0x00000001)
|
||||
#define EXT2_IRP_CONTEXT_WRITE_THROUGH (0x00000002)
|
||||
#define EXT2_IRP_CONTEXT_EXCEPTION (0x00000004)
|
||||
#define EXT2_IRP_CONTEXT_DEFERRED_WRITE (0x00000008)
|
||||
#define EXT2_IRP_CONTEXT_ASYNC_PROCESSING (0x00000010)
|
||||
#define EXT2_IRP_CONTEXT_NOT_TOP_LEVEL (0x00000020)
|
||||
|
||||
#define EXT2_IRP_CONTEXT_NOT_FROM_ZONE (0x80000000)
|
||||
|
||||
typedef struct _Ext2ThreadQueue
|
||||
{
|
||||
HANDLE QueueHandlerThread;
|
||||
|
||||
LIST_ENTRY ThreadQueueListHead; // This holds the Contexts
|
||||
// that are to be scheduled
|
||||
KSPIN_LOCK SpinLock; // To synchronize access to
|
||||
// the list
|
||||
KEVENT QueueEvent; // The Worker thread queue
|
||||
// package waits on this event
|
||||
} Ext2ThreadQueue;
|
||||
|
||||
/**************************************************************************
|
||||
we will store all of our global variables in one structure.
|
||||
Global variables are not specific to any mounted volume BUT
|
||||
by definition are required for successful operation of the
|
||||
FSD implementation.
|
||||
**************************************************************************/
|
||||
typedef struct _Ext2Data
|
||||
{
|
||||
Ext2Identifier NodeIdentifier;
|
||||
// the fields in this list are protected by the following resource
|
||||
ERESOURCE GlobalDataResource;
|
||||
// each driver has a driver object created for it by the NT I/O Mgr.
|
||||
// we are no exception to this rule.
|
||||
PDRIVER_OBJECT Ext2DriverObject;
|
||||
// we will create a device object for our FSD as well ...
|
||||
// Although not really required, it helps if a helper application
|
||||
// writen by us wishes to send us control information via
|
||||
// IOCTL requests ...
|
||||
PDEVICE_OBJECT Ext2DeviceObject;
|
||||
// we will keep a list of all logical volumes for our sample FSD
|
||||
LIST_ENTRY NextVCB;
|
||||
// the NT Cache Manager, the I/O Manager and we will conspire
|
||||
// to bypass IRP usage using the function pointers contained
|
||||
// in the following structure
|
||||
FAST_IO_DISPATCH Ext2FastIoDispatch;
|
||||
// The NT Cache Manager uses the following call backs to ensure
|
||||
// correct locking hierarchy is maintained
|
||||
CACHE_MANAGER_CALLBACKS CacheMgrCallBacks;
|
||||
// structures allocated from a zone need some fields here. Note
|
||||
// that under version 4.0, it might be better to use lookaside
|
||||
// lists
|
||||
KSPIN_LOCK ZoneAllocationSpinLock;
|
||||
ZONE_HEADER ObjectNameZoneHeader;
|
||||
ZONE_HEADER CCBZoneHeader;
|
||||
ZONE_HEADER FCBZoneHeader;
|
||||
ZONE_HEADER ByteLockZoneHeader;
|
||||
ZONE_HEADER IrpContextZoneHeader;
|
||||
void *ObjectNameZone;
|
||||
void *CCBZone;
|
||||
void *FCBZone;
|
||||
void *ByteLockZone;
|
||||
void *IrpContextZone;
|
||||
|
||||
// currently, there is a single default zone size value used for
|
||||
// all zones. This should ideally be changed by you to be 1 per
|
||||
// type of zone (e.g. a default size for the FCB zone might be
|
||||
// different from the default size for the ByteLock zone).
|
||||
|
||||
// Of course, you will need to use different values (min/max)
|
||||
// for lookaside lists (if you decide to use them instead)
|
||||
uint32 DefaultZoneSizeInNumStructs;
|
||||
|
||||
// some state information is maintained in the flags field
|
||||
uint32 Ext2Flags;
|
||||
|
||||
// Handle returned by the MUP is stored here.
|
||||
HANDLE MupHandle;
|
||||
|
||||
// Time difference
|
||||
LARGE_INTEGER TimeDiff;
|
||||
|
||||
// The Worker Thread package uses this structure...
|
||||
Ext2ThreadQueue ThreadQueue;
|
||||
|
||||
}Ext2Data, *PtrExt2Data;
|
||||
|
||||
// valid flag values for the global data structure
|
||||
#define EXT2_DATA_FLAGS_RESOURCE_INITIALIZED (0x00000001)
|
||||
#define EXT2_DATA_FLAGS_ZONES_INITIALIZED (0x00000002)
|
||||
|
||||
// a default size of the number of pages of non-paged pool allocated
|
||||
// for each of the zones ...
|
||||
|
||||
// Note that the values are absolutely arbitrary, the only information
|
||||
// worth using from the values themselves is that they increase for
|
||||
// larger systems (i.e. systems with more memory)
|
||||
#define EXT2_DEFAULT_ZONE_SIZE_SMALL_SYSTEM (0x4)
|
||||
#define EXT2_DEFAULT_ZONE_SIZE_MEDIUM_SYSTEM (0x8)
|
||||
#define EXT2_DEFAULT_ZONE_SIZE_LARGE_SYSTEM (0xc)
|
||||
|
||||
// another simplistic (brain dead ? :-) method used is to simply double
|
||||
// the values for a "server" machine
|
||||
|
||||
// So, for all you guys who "modified" the registry ;-) to change the
|
||||
// wkstation into a server, tough luck !
|
||||
#define EXT2_NTAS_MULTIPLE (0x2)
|
||||
|
||||
/***************************************************************************
|
||||
The following locking hierarchy is maintained in this sample filesystem
|
||||
driver:
|
||||
|
||||
(a) the global structure resource can be acquired at any time. However,
|
||||
it is an "end resource" i.e. once acquired, no other resource can
|
||||
be obtained until the global structure resource is released.
|
||||
(b) the logical volume resource must be acquired (if required) before
|
||||
any of the other resources are acquired.
|
||||
(c) a file control block can be acquired next (if required). If two
|
||||
FCB structures need to be acquired, the FCB "higher" in the directory
|
||||
tree must be acquired first.
|
||||
For a FCB, the "main resource" must be acquired first before a
|
||||
"paging i/o" resource is acquired.
|
||||
|
||||
Whenever a file is opened, the logical volume structure is referenced.
|
||||
This ensures that the volume cannot be dismounted while any file is open.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
typedef struct _IO_RUN
|
||||
{
|
||||
UINT LogicalBlock;
|
||||
UINT StartOffset;
|
||||
UINT EndOffset;
|
||||
PIRP PtrAssociatedIrp;
|
||||
|
||||
} EXT2_IO_RUN, *PEXT2_IO_RUN;
|
||||
|
||||
typedef struct _SIBlocks
|
||||
{
|
||||
PBCB PtrBCB;
|
||||
ULONG * PtrSIBlocks;
|
||||
} EXT2_SIBLOCKS, *PEXT2_SIBLOCKS;
|
||||
|
||||
#endif // has this file been included?
|
||||
|
215
reactos/drivers/filesystems/ext2/src/DiskIO.c
Normal file
215
reactos/drivers/filesystems/ext2/src/DiskIO.c
Normal file
|
@ -0,0 +1,215 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* File: DiskIO.c
|
||||
*
|
||||
* Module: Ext2 File System Driver (Kernel mode execution only)
|
||||
*
|
||||
* Description:
|
||||
* Should contain code to handle Disk IO.
|
||||
*
|
||||
*
|
||||
* Author: Manoj Paul Joseph
|
||||
*
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
#include "ext2fsd.h"
|
||||
|
||||
#define EXT2_BUG_CHECK_ID EXT2_FILE_DISK_IO
|
||||
|
||||
#define DEBUG_LEVEL ( DEBUG_TRACE_DISKIO )
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2ReadLogicalBlocks()
|
||||
*
|
||||
* Description:
|
||||
* The higherlevel functions will use this to read in logical blocks
|
||||
* This function deals with the logical to physical block translation
|
||||
*
|
||||
* LogicalBlock - This is a 1 based index.
|
||||
* That is, the first block is Block 1
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: The Status of the Read IO
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2ReadLogicalBlocks (
|
||||
PDEVICE_OBJECT PtrTargetDeviceObject, // the Target Device Object
|
||||
VOID *Buffer, // The Buffer that takes the data read in
|
||||
LARGE_INTEGER StartLogicalBlock, // The logical block from which reading is to start
|
||||
unsigned int NoOfLogicalBlocks // The no. of logical blocks to be read
|
||||
)
|
||||
{
|
||||
// The Status to be returned...
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
// The Device Object representing the mounted volume
|
||||
PDEVICE_OBJECT PtrVolumeDeviceObject = NULL;
|
||||
|
||||
// Volume Control Block
|
||||
PtrExt2VCB PtrVCB = NULL;
|
||||
|
||||
// Logical Block Size
|
||||
ULONG LogicalBlockSize;
|
||||
|
||||
// Physical Block Size
|
||||
ULONG PhysicalBlockSize;
|
||||
|
||||
// The starting Physical Block No...
|
||||
LARGE_INTEGER StartPhysicalBlock;
|
||||
|
||||
unsigned int NoOfPhysicalBlocks;
|
||||
|
||||
|
||||
|
||||
// Done with declerations...
|
||||
// Now for some code ;)
|
||||
|
||||
// Getting the Logical and Physical Sector sizes
|
||||
PtrVolumeDeviceObject = PtrTargetDeviceObject->Vpb->DeviceObject;
|
||||
ASSERT( PtrVolumeDeviceObject );
|
||||
PtrVCB = (PtrExt2VCB)(PtrVolumeDeviceObject->DeviceExtension);
|
||||
ASSERT(PtrVCB);
|
||||
ASSERT(PtrVCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB);
|
||||
|
||||
LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
|
||||
PhysicalBlockSize = PtrTargetDeviceObject->SectorSize;
|
||||
|
||||
NoOfPhysicalBlocks = NoOfLogicalBlocks * LogicalBlockSize / PhysicalBlockSize;
|
||||
|
||||
StartPhysicalBlock.QuadPart = ( StartLogicalBlock.QuadPart ) *
|
||||
( LogicalBlockSize / PhysicalBlockSize );
|
||||
|
||||
Status = Ext2ReadPhysicalBlocks( PtrTargetDeviceObject,
|
||||
Buffer, StartPhysicalBlock, NoOfPhysicalBlocks );
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2ReadPhysicalBlocks()
|
||||
*
|
||||
* Description:
|
||||
* The higherlevel functions will use this to read in physical blocks
|
||||
*
|
||||
* PhysicalBlock - This is a 0 based number.
|
||||
* That is, the first block is Block 0
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: The Status of the Read IO
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2ReadPhysicalBlocks (
|
||||
PDEVICE_OBJECT PtrTargetDeviceObject, // the Target Device Object
|
||||
VOID *Buffer, // The Buffer that takes the data read in
|
||||
LARGE_INTEGER StartPhysicalBlock, // The block from which reading is to start
|
||||
unsigned int NoOfBlocks // The no. of blocks to be read
|
||||
)
|
||||
{
|
||||
// The Status to be returned...
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
// Physical Block Size
|
||||
ULONG PhysicalBlockSize;
|
||||
|
||||
// No of bytes to read
|
||||
ULONG NumberOfBytesToRead;
|
||||
|
||||
// Synchronisation Event
|
||||
KEVENT Event;
|
||||
|
||||
// IRP
|
||||
PIRP Irp;
|
||||
|
||||
// Status Block
|
||||
IO_STATUS_BLOCK Iosb;
|
||||
|
||||
// Byte Offset
|
||||
LARGE_INTEGER ByteOffset;
|
||||
|
||||
// Done with declerations...
|
||||
// Now for some code ;)
|
||||
|
||||
// Getting the Physical Sector size
|
||||
PhysicalBlockSize = PtrTargetDeviceObject->SectorSize;
|
||||
|
||||
NumberOfBytesToRead = PhysicalBlockSize * NoOfBlocks;
|
||||
|
||||
ByteOffset.QuadPart = StartPhysicalBlock.QuadPart * PhysicalBlockSize;
|
||||
|
||||
try
|
||||
{
|
||||
//
|
||||
// Initialize the event we're going to use
|
||||
//
|
||||
KeInitializeEvent( &Event, NotificationEvent, FALSE );
|
||||
|
||||
//
|
||||
// Build the irp for the operation and also set the overrride flag
|
||||
//
|
||||
Irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ,
|
||||
PtrTargetDeviceObject,
|
||||
Buffer,
|
||||
NumberOfBytesToRead,
|
||||
&ByteOffset ,
|
||||
&Event,
|
||||
&Iosb );
|
||||
|
||||
if ( Irp == NULL )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MISC, " !!!! Unable to create an IRP", 0 );
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
try_return( Status );
|
||||
}
|
||||
|
||||
//
|
||||
// Call the device to do the read and wait for it to finish.
|
||||
//
|
||||
Status = IoCallDriver( PtrTargetDeviceObject, Irp );
|
||||
|
||||
//
|
||||
// Check if it is done already!!!!
|
||||
//
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
//
|
||||
// Read not done yet...
|
||||
// Wait till it is...
|
||||
//
|
||||
(VOID)KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL );
|
||||
Status = Iosb.Status;
|
||||
}
|
||||
|
||||
try_exit: NOTHING;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
if( Status == STATUS_VERIFY_REQUIRED )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MISC, " !!!! Verify Required! Failed to read disk",0 );
|
||||
}
|
||||
else if (Status == STATUS_INVALID_PARAMETER)
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MISC, " !!!! Invalid Parameter! Failed to read disk",0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MISC, " !!!! Failed to read disk! Status returned = %d", Status );
|
||||
}
|
||||
}
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
400
reactos/drivers/filesystems/ext2/src/cleanup.c
Normal file
400
reactos/drivers/filesystems/ext2/src/cleanup.c
Normal file
|
@ -0,0 +1,400 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* File: cleanup.c
|
||||
*
|
||||
* Module: Ext2 File System Driver (Kernel mode execution only)
|
||||
*
|
||||
* Description:
|
||||
* Should contain code to handle the "Cleanup" dispatch entry point.
|
||||
* This file serves as a placeholder. Please update this file as part
|
||||
* of designing and implementing your FSD.
|
||||
*
|
||||
* Author: Manoj Paul Joseph
|
||||
*
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
#include "ext2fsd.h"
|
||||
|
||||
// define the file specific bug-check id
|
||||
#define EXT2_BUG_CHECK_ID EXT2_FILE_CLEANUP
|
||||
#define DEBUG_LEVEL (DEBUG_TRACE_CLEANUP)
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2Cleanup()
|
||||
*
|
||||
* Description:
|
||||
* The I/O Manager will invoke this routine to handle a cleanup
|
||||
* request
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
|
||||
* to be deferred to a worker thread context)
|
||||
*
|
||||
* Return Value: Does not matter!
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2Cleanup(
|
||||
PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
PIRP Irp) // I/O Request Packet
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
PtrExt2IrpContext PtrIrpContext = NULL;
|
||||
BOOLEAN AreWeTopLevel = FALSE;
|
||||
|
||||
DebugTrace( DEBUG_TRACE_IRP_ENTRY, "Cleanup IRP Received...", 0);
|
||||
|
||||
FsRtlEnterFileSystem();
|
||||
ASSERT(DeviceObject);
|
||||
ASSERT(Irp);
|
||||
|
||||
// set the top level context
|
||||
AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
// get an IRP context structure and issue the request
|
||||
PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
|
||||
ASSERT(PtrIrpContext);
|
||||
|
||||
RC = Ext2CommonCleanup(PtrIrpContext, Irp, TRUE);
|
||||
|
||||
}
|
||||
except( Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation() ) )
|
||||
{
|
||||
|
||||
RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
|
||||
|
||||
Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
|
||||
}
|
||||
|
||||
if (AreWeTopLevel)
|
||||
{
|
||||
IoSetTopLevelIrp(NULL);
|
||||
}
|
||||
|
||||
FsRtlExitFileSystem();
|
||||
|
||||
return(RC);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2CommonCleanup()
|
||||
*
|
||||
* Description:
|
||||
* The actual work is performed here. This routine may be invoked in one'
|
||||
* of the two possible contexts:
|
||||
* (a) in the context of a system worker thread
|
||||
* (b) in the context of the original caller
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: Does not matter!
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2CommonCleanup(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp,
|
||||
BOOLEAN FirstAttempt )
|
||||
{
|
||||
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
PIO_STACK_LOCATION PtrIoStackLocation = NULL;
|
||||
PFILE_OBJECT PtrFileObject = NULL;
|
||||
PtrExt2FCB PtrFCB = NULL;
|
||||
PtrExt2CCB PtrCCB = NULL;
|
||||
PtrExt2VCB PtrVCB = NULL;
|
||||
PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
|
||||
PERESOURCE PtrResourceAcquired = NULL;
|
||||
IO_STATUS_BLOCK LocalIoStatus;
|
||||
|
||||
BOOLEAN CompleteIrp = TRUE;
|
||||
BOOLEAN PostRequest = FALSE;
|
||||
BOOLEAN AcquiredVCB = FALSE;
|
||||
BOOLEAN CanWait = FALSE;
|
||||
BOOLEAN BlockForResource;
|
||||
int i = 1;
|
||||
|
||||
try
|
||||
{
|
||||
// First, get a pointer to the current I/O stack location
|
||||
PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
|
||||
ASSERT(PtrIoStackLocation);
|
||||
|
||||
PtrFileObject = PtrIoStackLocation->FileObject;
|
||||
ASSERT(PtrFileObject);
|
||||
|
||||
if( !PtrFileObject->FsContext2 )
|
||||
{
|
||||
// This must be a Cleanup request received
|
||||
// as a result of IoCreateStreamFileObject
|
||||
// Only such a File object would have a NULL CCB
|
||||
|
||||
DebugTrace( DEBUG_TRACE_MISC, " === Cleanup with NULL CCB", 0);
|
||||
if( PtrFileObject )
|
||||
{
|
||||
DebugTrace( DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
|
||||
}
|
||||
try_return( RC );
|
||||
}
|
||||
|
||||
|
||||
Ext2GetFCB_CCB_VCB_FromFileObject (
|
||||
PtrFileObject, &PtrFCB, &PtrCCB, &PtrVCB );
|
||||
|
||||
if( PtrFCB && PtrFCB->FCBName && PtrFCB->FCBName->ObjectName.Length && PtrFCB->FCBName->ObjectName.Buffer )
|
||||
//if( PtrFileObject->FileName.Length && PtrFileObject->FileName.Buffer )
|
||||
{
|
||||
DebugTrace( DEBUG_TRACE_FILE_NAME, " === Cleanup File Name : -%S-", PtrFCB->FCBName->ObjectName.Buffer );
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace( DEBUG_TRACE_FILE_NAME, " === Cleanup Volume", 0);
|
||||
}
|
||||
|
||||
|
||||
PtrVCB = (PtrExt2VCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
|
||||
ASSERT(PtrVCB);
|
||||
ASSERT(PtrVCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB);
|
||||
|
||||
// (a) Acquiring the VCBResource Exclusively...
|
||||
// This is done to synchronise with the close and cleanup routines...
|
||||
BlockForResource = !FirstAttempt;
|
||||
if( !FirstAttempt )
|
||||
{
|
||||
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Going into a block to acquire VCB Exclusively [Cleanup]", 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Attempting to acquire VCB Exclusively [Cleanup]", 0);
|
||||
}
|
||||
|
||||
if( PtrFileObject )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
|
||||
}
|
||||
|
||||
i = 1;
|
||||
while( !AcquiredVCB )
|
||||
{
|
||||
DebugTraceState("VCB AC:0x%LX SW:0x%LX EX:0x%LX [Cleanup]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
|
||||
if( ! ExAcquireResourceExclusiveLite( &(PtrVCB->VCBResource), FALSE ) )
|
||||
{
|
||||
DebugTrace( DEBUG_TRACE_RESOURCE_ACQUIRE, "*** VCB Acquisition FAILED [Cleanup]", 0);
|
||||
if( BlockForResource && i != 1000 )
|
||||
{
|
||||
LARGE_INTEGER Delay;
|
||||
Delay.QuadPart = -500 * i;
|
||||
KeDelayExecutionThread( KernelMode, FALSE, &Delay );
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Retrying... after 50 * %ld ms [Cleanup]", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( i == 1000 )
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Reposting... [Cleanup]", 0 );
|
||||
PostRequest = TRUE;
|
||||
try_return( RC = STATUS_PENDING );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** VCB Acquired in [Cleanup]", 0);
|
||||
AcquiredVCB = TRUE;
|
||||
}
|
||||
i *= 10;
|
||||
}
|
||||
|
||||
|
||||
// (b) Acquire the file (FCB) exclusively
|
||||
if( PtrFCB && PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB )
|
||||
{
|
||||
// This FCB is an FCB indeed. ;)
|
||||
// So acquiring it exclusively...
|
||||
// This is done to synchronise with read/write routines...
|
||||
if( !FirstAttempt )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Going into a block to acquire FCB Exclusively [Cleanup]", 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Attempting to acquire FCB Exclusively [Cleanup]", 0);
|
||||
}
|
||||
if( PtrFileObject )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
|
||||
}
|
||||
|
||||
i = 1;
|
||||
while( !PtrResourceAcquired )
|
||||
{
|
||||
PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
|
||||
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [Cleanup]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
|
||||
if(! ExAcquireResourceExclusiveLite( &(PtrFCB->NTRequiredFCB.MainResource ), FALSE ) )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** FCB Acquisition FAILED [Cleanup]", 0);
|
||||
if( BlockForResource && i != 1000 )
|
||||
{
|
||||
LARGE_INTEGER Delay;
|
||||
Delay.QuadPart = -500 * i;
|
||||
KeDelayExecutionThread( KernelMode, FALSE, &Delay );
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Retrying... after 50 * %ld ms [Cleanup]", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( i == 1000 )
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Reposting... [Cleanup]", 0 );
|
||||
PostRequest = TRUE;
|
||||
try_return( RC = STATUS_PENDING );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** FCB acquired [Cleanup]", 0);
|
||||
PtrResourceAcquired = & ( PtrFCB->NTRequiredFCB.MainResource );
|
||||
}
|
||||
i *= 10;
|
||||
}
|
||||
|
||||
// (c) Flush file data to disk
|
||||
if ( PtrFileObject->PrivateCacheMap != NULL)
|
||||
{
|
||||
IO_STATUS_BLOCK Status;
|
||||
CcFlushCache( PtrFileObject->SectionObjectPointer, NULL, 0, &Status );
|
||||
}
|
||||
|
||||
// (d) Talk to the FSRTL package (if you use it) about pending oplocks.
|
||||
// (e) Notify the FSRTL package (if you use it) for use with pending
|
||||
// notification IRPs
|
||||
// (f) Unlock byte-range locks (if any were acquired by process)
|
||||
|
||||
// (g) Attempting to update time stamp values
|
||||
// Errors are ignored...
|
||||
// Not considered as critical errors...
|
||||
|
||||
/*
|
||||
if( PtrFCB->OpenHandleCount == 1 )
|
||||
{
|
||||
ULONG CreationTime, AccessTime, ModificationTime;
|
||||
EXT2_INODE Inode;
|
||||
|
||||
CreationTime = (ULONG) ( (PtrFCB->CreationTime.QuadPart
|
||||
- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
|
||||
AccessTime = (ULONG) ( (PtrFCB->LastAccessTime.QuadPart
|
||||
- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
|
||||
ModificationTime = (ULONG) ( (PtrFCB->LastWriteTime.QuadPart
|
||||
- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
|
||||
if( NT_SUCCESS( Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
|
||||
{
|
||||
// Update time stamps in the inode...
|
||||
Inode.i_ctime = CreationTime;
|
||||
Inode.i_atime = AccessTime;
|
||||
Inode.i_mtime = ModificationTime;
|
||||
|
||||
// Updating the inode...
|
||||
Ext2WriteInode( PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode );
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// (h) Inform the Cache Manager to uninitialize Cache Maps ...
|
||||
CcUninitializeCacheMap( PtrFileObject, NULL, NULL );
|
||||
|
||||
// (i) Decrementing the Open Handle count...
|
||||
if( PtrFCB->OpenHandleCount )
|
||||
{
|
||||
InterlockedDecrement( &PtrFCB->OpenHandleCount );
|
||||
}
|
||||
else
|
||||
{
|
||||
Ext2BreakPoint();
|
||||
}
|
||||
|
||||
PtrFCB->FCBFlags |= FO_CLEANUP_COMPLETE;
|
||||
|
||||
DebugTrace(DEBUG_TRACE_REFERENCE, "^^^^^ReferenceCount = 0x%lX [Cleanup]", PtrFCB->ReferenceCount );
|
||||
DebugTrace(DEBUG_TRACE_REFERENCE, "^^^^^OpenHandleCount = 0x%lX [Cleanup]", PtrFCB->OpenHandleCount );
|
||||
|
||||
// (j) Remove share access...
|
||||
// Will do that later ;)
|
||||
|
||||
// (k) Is this a close on delete file?
|
||||
// If so, delete the file...
|
||||
if( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_DELETE_ON_CLOSE) &&
|
||||
!PtrFCB->OpenHandleCount )
|
||||
{
|
||||
//
|
||||
// Have to delete this file...
|
||||
//
|
||||
Ext2DeleteFile( PtrFCB, PtrIrpContext );
|
||||
PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart = 0;
|
||||
PtrFCB->INodeNo = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This must be a volume close...
|
||||
// Just go ahead and complete this IRP...
|
||||
PtrVCB->VCBOpenCount--;
|
||||
DebugTrace(DEBUG_TRACE_MISC, "VCB Cleanup Requested !!!", 0);
|
||||
CompleteIrp = TRUE;
|
||||
}
|
||||
|
||||
try_return( RC );
|
||||
|
||||
try_exit: NOTHING;
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(PtrResourceAcquired)
|
||||
{
|
||||
Ext2ReleaseResource(PtrResourceAcquired);
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_RELEASE, "*** Resource Released [Cleanup]", 0);
|
||||
DebugTraceState( "Resource AC:0x%LX SW:0x%LX EX:0x%LX [Cleanup]",
|
||||
PtrResourceAcquired->ActiveCount,
|
||||
PtrResourceAcquired->NumberOfExclusiveWaiters,
|
||||
PtrResourceAcquired->NumberOfSharedWaiters );
|
||||
|
||||
if( PtrFileObject )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( AcquiredVCB )
|
||||
{
|
||||
ASSERT(PtrVCB);
|
||||
Ext2ReleaseResource(&(PtrVCB->VCBResource));
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_RELEASE, "*** VCB Released [Cleanup]", 0);
|
||||
DebugTraceState( "VCB AC:0x%LX SW:0x%LX EX:0x%LX [Cleanup]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
|
||||
AcquiredVCB = FALSE;
|
||||
if( PtrFileObject )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( PostRequest )
|
||||
{
|
||||
RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
|
||||
}
|
||||
if( RC != STATUS_PENDING )
|
||||
{
|
||||
Ext2ReleaseIrpContext( PtrIrpContext );
|
||||
// complete the IRP
|
||||
IoCompleteRequest( PtrIrp, IO_DISK_INCREMENT );
|
||||
}
|
||||
} // end of "finally" processing
|
||||
|
||||
return(RC);
|
||||
}
|
459
reactos/drivers/filesystems/ext2/src/close.c
Normal file
459
reactos/drivers/filesystems/ext2/src/close.c
Normal file
|
@ -0,0 +1,459 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* File: close.c
|
||||
*
|
||||
* Module: Ext2 File System Driver (Kernel mode execution only)
|
||||
*
|
||||
* Description:
|
||||
* Should contain code to handle the "Close" dispatch entry point.
|
||||
* This file serves as a placeholder. Please update this file as part
|
||||
* of designing and implementing your FSD.
|
||||
*
|
||||
* Author: Manoj Paul Joseph
|
||||
*
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
#include "ext2fsd.h"
|
||||
|
||||
// define the file specific bug-check id
|
||||
#define EXT2_BUG_CHECK_ID EXT2_FILE_CLOSE
|
||||
|
||||
#define DEBUG_LEVEL (DEBUG_TRACE_CLOSE)
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2Close()
|
||||
*
|
||||
* Description:
|
||||
* The I/O Manager will invoke this routine to handle a close
|
||||
* request
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
|
||||
* to be deferred to a worker thread context)
|
||||
*
|
||||
* Return Value: Does not matter!
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2Close(
|
||||
PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
PIRP Irp) // I/O Request Packet
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
PtrExt2IrpContext PtrIrpContext = NULL;
|
||||
BOOLEAN AreWeTopLevel = FALSE;
|
||||
|
||||
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Close IRP Received...", 0);
|
||||
|
||||
|
||||
FsRtlEnterFileSystem();
|
||||
|
||||
ASSERT(DeviceObject);
|
||||
ASSERT(Irp);
|
||||
|
||||
// set the top level context
|
||||
AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
// get an IRP context structure and issue the request
|
||||
PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
|
||||
ASSERT(PtrIrpContext);
|
||||
|
||||
RC = Ext2CommonClose(PtrIrpContext, Irp, TRUE);
|
||||
|
||||
}
|
||||
except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
|
||||
{
|
||||
|
||||
RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
|
||||
Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
|
||||
}
|
||||
|
||||
if (AreWeTopLevel)
|
||||
{
|
||||
IoSetTopLevelIrp(NULL);
|
||||
}
|
||||
|
||||
FsRtlExitFileSystem();
|
||||
|
||||
return(RC);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2CommonClose()
|
||||
*
|
||||
* Description:
|
||||
* The actual work is performed here. This routine may be invoked in one'
|
||||
* of the two possible contexts:
|
||||
* (a) in the context of a system worker thread
|
||||
* (b) in the context of the original caller
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: Does not matter!
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2CommonClose(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp,
|
||||
BOOLEAN FirstAttempt )
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
PIO_STACK_LOCATION PtrIoStackLocation = NULL;
|
||||
PFILE_OBJECT PtrFileObject = NULL;
|
||||
PtrExt2FCB PtrFCB = NULL;
|
||||
PtrExt2CCB PtrCCB = NULL;
|
||||
PtrExt2VCB PtrVCB = NULL;
|
||||
PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
|
||||
PERESOURCE PtrResourceAcquired = NULL;
|
||||
IO_STATUS_BLOCK LocalIoStatus;
|
||||
|
||||
BOOLEAN CompleteIrp = TRUE;
|
||||
BOOLEAN PostRequest = FALSE;
|
||||
BOOLEAN AcquiredVCB = FALSE;
|
||||
BOOLEAN CanWait = FALSE;
|
||||
BOOLEAN BlockForResource;
|
||||
int i = 1;
|
||||
|
||||
try
|
||||
{
|
||||
// First, get a pointer to the current I/O stack location
|
||||
PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
|
||||
ASSERT(PtrIoStackLocation);
|
||||
|
||||
PtrFileObject = PtrIoStackLocation->FileObject;
|
||||
ASSERT(PtrFileObject);
|
||||
|
||||
if( !PtrFileObject->FsContext2 )
|
||||
{
|
||||
// This must be a Cleanup request received
|
||||
// as a result of IoCreateStreamFileObject
|
||||
// Only such a File object would have a NULL CCB
|
||||
|
||||
DebugTrace( DEBUG_TRACE_SPECIAL, " === Close with NULL CCB", 0);
|
||||
if( PtrFileObject )
|
||||
{
|
||||
DebugTrace( DEBUG_TRACE_SPECIAL, "###### File Pointer 0x%LX [Close]", PtrFileObject);
|
||||
}
|
||||
Ext2BreakPoint();
|
||||
try_return( RC );
|
||||
}
|
||||
|
||||
// Get the FCB and CCB pointers
|
||||
|
||||
Ext2GetFCB_CCB_VCB_FromFileObject (
|
||||
PtrFileObject, &PtrFCB, &PtrCCB, &PtrVCB );
|
||||
|
||||
PtrVCB = (PtrExt2VCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
|
||||
ASSERT( PtrVCB );
|
||||
|
||||
if( PtrFCB && PtrFCB->FCBName && PtrFCB->FCBName->ObjectName.Length && PtrFCB->FCBName->ObjectName.Buffer )
|
||||
//if( PtrFileObject->FileName.Length && PtrFileObject->FileName.Buffer )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FILE_NAME, " === Close File Name : -%S-", PtrFCB->FCBName->ObjectName.Buffer );
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FILE_NAME, " === Close File Name : -null-", 0);
|
||||
}
|
||||
|
||||
// (a) Acquiring the VCBResource Exclusively...
|
||||
// This is done to synchronise with the close and cleanup routines...
|
||||
// if( ExTryToAcquireResourceExclusiveLite(&(PtrVCB->VCBResource) ) )
|
||||
|
||||
BlockForResource = !FirstAttempt;
|
||||
if( !FirstAttempt )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** Going into a block to acquire VCB Exclusively [Close]", 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire VCB Exclusively [Close]", 0);
|
||||
}
|
||||
if( PtrFileObject )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
|
||||
}
|
||||
i = 1;
|
||||
while( !AcquiredVCB )
|
||||
{
|
||||
DebugTraceState( "VCB AC:0x%LX SW:0x%LX EX:0x%LX [Close]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
|
||||
if(! ExAcquireResourceExclusiveLite( &(PtrVCB->VCBResource), FALSE ) )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** VCB Acquisition FAILED [Close]", 0);
|
||||
if( BlockForResource && i != 1000 )
|
||||
{
|
||||
LARGE_INTEGER Delay;
|
||||
|
||||
//KeSetPriorityThread( PsGetCurrentThread(),LOW_REALTIME_PRIORITY );
|
||||
|
||||
Delay.QuadPart = -500 * i;
|
||||
KeDelayExecutionThread( KernelMode, FALSE, &Delay );
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** Retrying... after 50 * %ld ms [Close]", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( i == 1000 )
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** Reposting... [Close]", 0 );
|
||||
PostRequest = TRUE;
|
||||
try_return( RC = STATUS_PENDING );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** VCB Acquired in [Close]", 0);
|
||||
AcquiredVCB = TRUE;
|
||||
}
|
||||
i *= 10;
|
||||
}
|
||||
|
||||
// (b) Acquire the file (FCB) exclusively
|
||||
if( PtrFCB && PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB )
|
||||
{
|
||||
// This FCB is an FCB indeed. ;)
|
||||
// So acquiring it exclusively...
|
||||
// This is done to synchronise with read/write routines...
|
||||
if( !FirstAttempt )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** Going into a block to acquire FCB Exclusively [Close]", 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire FCB Exclusively [Close]", 0);
|
||||
}
|
||||
if( PtrFileObject )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
|
||||
}
|
||||
i = 1;
|
||||
while( !PtrResourceAcquired )
|
||||
{
|
||||
PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
|
||||
|
||||
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [Close]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
|
||||
if(! ExAcquireResourceExclusiveLite( &(PtrFCB->NTRequiredFCB.MainResource ), FALSE ) )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Acquisition FAILED [Close]", 0);
|
||||
if( BlockForResource && i != 1000 )
|
||||
{
|
||||
LARGE_INTEGER Delay;
|
||||
|
||||
//KeSetPriorityThread( PsGetCurrentThread(),LOW_REALTIME_PRIORITY );
|
||||
|
||||
Delay.QuadPart = -500 * i;
|
||||
KeDelayExecutionThread( KernelMode, FALSE, &Delay );
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** Retrying... after 50 * %ld ms [Close]", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( i == 1000 )
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** Reposting... [Close]", 0 );
|
||||
PostRequest = TRUE;
|
||||
try_return( RC = STATUS_PENDING );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** FCB acquired [Close]", 0);
|
||||
PtrResourceAcquired = & ( PtrFCB->NTRequiredFCB.MainResource );
|
||||
}
|
||||
i *= 10;
|
||||
}
|
||||
|
||||
// (c) Delete the CCB structure (free memory)
|
||||
RemoveEntryList( &PtrCCB->NextCCB );
|
||||
Ext2ReleaseCCB( PtrCCB );
|
||||
PtrFileObject->FsContext2 = NULL;
|
||||
|
||||
// (d) Decrementing the Reference Count...
|
||||
if( PtrFCB->ReferenceCount )
|
||||
{
|
||||
InterlockedDecrement( &PtrFCB->ReferenceCount );
|
||||
}
|
||||
else
|
||||
{
|
||||
Ext2BreakPoint();
|
||||
}
|
||||
DebugTrace(DEBUG_TRACE_REFERENCE, "^^^^^ReferenceCount = 0x%lX [Close]", PtrFCB->ReferenceCount );
|
||||
DebugTrace(DEBUG_TRACE_REFERENCE, "^^^^^OpenHandleCount = 0x%lX [Close]", PtrFCB->OpenHandleCount );
|
||||
if( PtrFCB->ReferenceCount == 0 )
|
||||
{
|
||||
|
||||
// Attempting to update time stamp values
|
||||
// Errors are ignored...
|
||||
// Not considered as critical errors...
|
||||
|
||||
{
|
||||
ULONG CreationTime, AccessTime, ModificationTime;
|
||||
EXT2_INODE Inode;
|
||||
|
||||
CreationTime = (ULONG) ( (PtrFCB->CreationTime.QuadPart
|
||||
- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
|
||||
AccessTime = (ULONG) ( (PtrFCB->LastAccessTime.QuadPart
|
||||
- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
|
||||
ModificationTime = (ULONG) ( (PtrFCB->LastWriteTime.QuadPart
|
||||
- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
|
||||
if( NT_SUCCESS( Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
|
||||
{
|
||||
// Update time stamps in the inode...
|
||||
Inode.i_ctime = CreationTime;
|
||||
Inode.i_atime = AccessTime;
|
||||
Inode.i_mtime = ModificationTime;
|
||||
|
||||
// Updating the inode...
|
||||
Ext2WriteInode( NULL, PtrVCB, PtrFCB->INodeNo, &Inode );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( PtrFCB->INodeNo == EXT2_ROOT_INO )
|
||||
{
|
||||
//
|
||||
// Root Directory FCB
|
||||
// Preserve this
|
||||
// FSD has a File Object for this FCB...
|
||||
//
|
||||
DebugTrace(DEBUG_TRACE_MISC, "^^^^^Root Directory FCB ; leaveing it alone[Close]", 0);
|
||||
// Do nothing...
|
||||
|
||||
}
|
||||
else if( PtrFCB->DcbFcb.Dcb.PtrDirFileObject )
|
||||
{
|
||||
//
|
||||
// If this is a FCB created on the FSD's initiative
|
||||
// Leave it alone
|
||||
//
|
||||
DebugTrace(DEBUG_TRACE_MISC, "^^^^^FCB Created on the FSD's initiative; leaveing it alone[Close]", 0);
|
||||
if( !PtrFCB->ClosableFCBs.OnClosableFCBList )
|
||||
{
|
||||
InsertTailList( &PtrVCB->ClosableFCBs.ClosableFCBListHead,
|
||||
&PtrFCB->ClosableFCBs.ClosableFCBList );
|
||||
PtrVCB->ClosableFCBs.Count++;
|
||||
|
||||
PtrFCB->ClosableFCBs.OnClosableFCBList = TRUE;
|
||||
}
|
||||
|
||||
if( PtrVCB->ClosableFCBs.Count > EXT2_MAXCLOSABLE_FCBS_UL )
|
||||
{
|
||||
PtrExt2FCB PtrTempFCB = NULL;
|
||||
// Checking if Closable FCBs are too many in number...
|
||||
// Shouldn't block the
|
||||
// Should do this asynchronously...
|
||||
// Maybe later...
|
||||
PLIST_ENTRY PtrEntry = NULL;
|
||||
|
||||
PtrEntry = RemoveHeadList( &PtrVCB->ClosableFCBs.ClosableFCBListHead );
|
||||
|
||||
PtrTempFCB = CONTAINING_RECORD( PtrEntry, Ext2FCB, ClosableFCBs.ClosableFCBList );
|
||||
if( Ext2CloseClosableFCB( PtrTempFCB ) )
|
||||
{
|
||||
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [Close]", PtrTempFCB );
|
||||
ExFreePool( PtrTempFCB );
|
||||
PtrVCB->ClosableFCBs.Count--;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Put the FCB back in the list...
|
||||
InsertHeadList( &PtrVCB->ClosableFCBs.ClosableFCBListHead,
|
||||
&PtrTempFCB->ClosableFCBs.ClosableFCBList );
|
||||
}
|
||||
DebugTrace( DEBUG_TRACE_SPECIAL, "ClosableFCBs Count = %ld [Close]", PtrVCB->ClosableFCBs.Count );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove this FCB as well...
|
||||
DebugTrace(DEBUG_TRACE_MISC, "^^^^^Deleting FCB [Close]", 0);
|
||||
RemoveEntryList( &PtrFCB->NextFCB );
|
||||
|
||||
if ( PtrResourceAcquired )
|
||||
{
|
||||
Ext2ReleaseResource(PtrResourceAcquired);
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [Close]", 0);
|
||||
DebugTraceState( "Resource AC:0x%LX SW:0x%LX EX:0x%LX [Close]",
|
||||
PtrResourceAcquired->ActiveCount,
|
||||
PtrResourceAcquired->NumberOfExclusiveWaiters,
|
||||
PtrResourceAcquired->NumberOfSharedWaiters );
|
||||
|
||||
if( PtrFileObject )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
|
||||
}
|
||||
PtrResourceAcquired = FALSE;
|
||||
}
|
||||
Ext2ReleaseFCB( PtrFCB );
|
||||
}
|
||||
|
||||
}
|
||||
CompleteIrp = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This must be a volume close...
|
||||
// What do I do now? ;)
|
||||
DebugTrace(DEBUG_TRACE_MISC, "VCB Close Requested !!!", 0);
|
||||
CompleteIrp = TRUE;
|
||||
}
|
||||
try_return( RC );
|
||||
|
||||
try_exit: NOTHING;
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
if ( PtrResourceAcquired )
|
||||
{
|
||||
Ext2ReleaseResource(PtrResourceAcquired);
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [Close]", 0);
|
||||
DebugTraceState( "Resource AC:0x%LX SW:0x%LX EX:0x%LX [Close]",
|
||||
PtrResourceAcquired->ActiveCount,
|
||||
PtrResourceAcquired->NumberOfExclusiveWaiters,
|
||||
PtrResourceAcquired->NumberOfSharedWaiters );
|
||||
|
||||
if( PtrFileObject )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
|
||||
}
|
||||
PtrResourceAcquired = FALSE;
|
||||
}
|
||||
|
||||
if (AcquiredVCB)
|
||||
{
|
||||
ASSERT(PtrVCB);
|
||||
Ext2ReleaseResource(&(PtrVCB->VCBResource));
|
||||
DebugTraceState( "VCB AC:0x%LX SW:0x%LX EX:0x%LX [Close]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** VCB Released [Close]", 0);
|
||||
|
||||
AcquiredVCB = FALSE;
|
||||
if( PtrFileObject )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( PostRequest )
|
||||
{
|
||||
RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
|
||||
}
|
||||
else if( CompleteIrp && RC != STATUS_PENDING )
|
||||
{
|
||||
// complete the IRP
|
||||
IoCompleteRequest( PtrIrp, IO_DISK_INCREMENT );
|
||||
|
||||
Ext2ReleaseIrpContext( PtrIrpContext );
|
||||
}
|
||||
|
||||
} // end of "finally" processing
|
||||
|
||||
return(RC);
|
||||
}
|
1681
reactos/drivers/filesystems/ext2/src/create.c
Normal file
1681
reactos/drivers/filesystems/ext2/src/create.c
Normal file
File diff suppressed because it is too large
Load diff
210
reactos/drivers/filesystems/ext2/src/devcntrl.c
Normal file
210
reactos/drivers/filesystems/ext2/src/devcntrl.c
Normal file
|
@ -0,0 +1,210 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* File: devcntrl.c
|
||||
*
|
||||
* Module: Ext2 File System Driver (Kernel mode execution only)
|
||||
*
|
||||
* Description:
|
||||
* Contains code to handle the "Device IOCTL" dispatch entry point.
|
||||
*
|
||||
* Author: Manoj Paul Joseph
|
||||
*
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
#include "ext2fsd.h"
|
||||
|
||||
// define the file specific bug-check id
|
||||
#define EXT2_BUG_CHECK_ID EXT2_FILE_DEVICE_CONTROL
|
||||
#define DEBUG_LEVEL DEBUG_TRACE_DEVCTRL
|
||||
|
||||
|
||||
#if(_WIN32_WINNT < 0x0400)
|
||||
#define IOCTL_REDIR_QUERY_PATH CTL_CODE(FILE_DEVICE_NETWORK_FILE_SYSTEM, 99, METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
|
||||
typedef struct _QUERY_PATH_REQUEST
|
||||
{
|
||||
ULONG PathNameLength;
|
||||
PIO_SECURITY_CONTEXT SecurityContext;
|
||||
WCHAR FilePathName[1];
|
||||
} QUERY_PATH_REQUEST, *PQUERY_PATH_REQUEST;
|
||||
|
||||
typedef struct _QUERY_PATH_RESPONSE
|
||||
{
|
||||
ULONG LengthAccepted;
|
||||
} QUERY_PATH_RESPONSE, *PQUERY_PATH_RESPONSE;
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2DeviceControl()
|
||||
*
|
||||
* Description:
|
||||
* The I/O Manager will invoke this routine to handle a Device IOCTL
|
||||
* request
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
|
||||
* to be deferred to a worker thread context)
|
||||
*
|
||||
* Return Value: STATUS_SUCCESS/Error
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2DeviceControl(
|
||||
PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
PIRP Irp) // I/O Request Packet
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
PtrExt2IrpContext PtrIrpContext = NULL;
|
||||
BOOLEAN AreWeTopLevel = FALSE;
|
||||
|
||||
// Ext2BreakPoint();
|
||||
|
||||
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Device Control IRP Received...", 0);
|
||||
|
||||
FsRtlEnterFileSystem();
|
||||
ASSERT(DeviceObject);
|
||||
ASSERT(Irp);
|
||||
|
||||
// set the top level context
|
||||
AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
|
||||
|
||||
try {
|
||||
|
||||
// get an IRP context structure and issue the request
|
||||
PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
|
||||
ASSERT(PtrIrpContext);
|
||||
|
||||
RC = Ext2CommonDeviceControl(PtrIrpContext, Irp);
|
||||
|
||||
} except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
|
||||
|
||||
RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
|
||||
|
||||
Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
|
||||
}
|
||||
|
||||
if (AreWeTopLevel) {
|
||||
IoSetTopLevelIrp(NULL);
|
||||
}
|
||||
|
||||
FsRtlExitFileSystem();
|
||||
|
||||
return(RC);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2CommonDeviceControl()
|
||||
*
|
||||
* Description:
|
||||
* The actual work is performed here. This routine may be invoked in one'
|
||||
* of the two possible contexts:
|
||||
* (a) in the context of a system worker thread
|
||||
* (b) in the context of the original caller
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: STATUS_SUCCESS/Error
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2CommonDeviceControl(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp)
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
PIO_STACK_LOCATION PtrIoStackLocation = NULL;
|
||||
PIO_STACK_LOCATION PtrNextIoStackLocation = NULL;
|
||||
PFILE_OBJECT PtrFileObject = NULL;
|
||||
PtrExt2FCB PtrFCB = NULL;
|
||||
PtrExt2CCB PtrCCB = NULL;
|
||||
PtrExt2VCB PtrVCB = NULL;
|
||||
ULONG IoControlCode = 0;
|
||||
void *BufferPointer = NULL;
|
||||
|
||||
try
|
||||
{
|
||||
// First, get a pointer to the current I/O stack location
|
||||
PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
|
||||
ASSERT(PtrIoStackLocation);
|
||||
|
||||
PtrFileObject = PtrIoStackLocation->FileObject;
|
||||
ASSERT(PtrFileObject);
|
||||
|
||||
PtrCCB = (PtrExt2CCB)(PtrFileObject->FsContext2);
|
||||
ASSERT(PtrCCB);
|
||||
PtrFCB = PtrCCB->PtrFCB;
|
||||
ASSERT(PtrFCB);
|
||||
|
||||
|
||||
if( PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB )
|
||||
{
|
||||
PtrVCB = (PtrExt2VCB)(PtrFCB);
|
||||
}
|
||||
else
|
||||
{
|
||||
AssertFCB( PtrFCB );
|
||||
ASSERT(PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB);
|
||||
PtrVCB = PtrFCB->PtrVCB;
|
||||
}
|
||||
|
||||
// Get the IoControlCode value
|
||||
IoControlCode = PtrIoStackLocation->Parameters.DeviceIoControl.IoControlCode;
|
||||
|
||||
// You may wish to allow only volume open operations.
|
||||
|
||||
// Invoke the lower level driver in the chain.
|
||||
PtrNextIoStackLocation = IoGetNextIrpStackLocation(PtrIrp);
|
||||
*PtrNextIoStackLocation = *PtrIoStackLocation;
|
||||
// Set a completion routine.
|
||||
IoSetCompletionRoutine(PtrIrp, Ext2DevIoctlCompletion, NULL, TRUE, TRUE, TRUE);
|
||||
// Send the request.
|
||||
RC = IoCallDriver(PtrVCB->TargetDeviceObject, PtrIrp);
|
||||
|
||||
try_exit: NOTHING;
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Release the IRP context
|
||||
if (!(PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_EXCEPTION))
|
||||
{
|
||||
// Free up the Irp Context
|
||||
Ext2ReleaseIrpContext(PtrIrpContext);
|
||||
}
|
||||
}
|
||||
|
||||
return(RC);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2DevIoctlCompletion()
|
||||
*
|
||||
* Description:
|
||||
* Completion routine.
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: STATUS_SUCCESS
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2DevIoctlCompletion(
|
||||
PDEVICE_OBJECT PtrDeviceObject,
|
||||
PIRP PtrIrp,
|
||||
void *Context)
|
||||
{
|
||||
if (PtrIrp->PendingReturned) {
|
||||
IoMarkIrpPending(PtrIrp);
|
||||
}
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
937
reactos/drivers/filesystems/ext2/src/dircntrl.c
Normal file
937
reactos/drivers/filesystems/ext2/src/dircntrl.c
Normal file
|
@ -0,0 +1,937 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* File: dircntrl.c
|
||||
*
|
||||
* Module: Ext2 File System Driver (Kernel mode execution only)
|
||||
*
|
||||
* Description:
|
||||
* Contains code to handle the "directory control" dispatch entry point.
|
||||
*
|
||||
* Author: Manoj Paul Joseph
|
||||
*
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
#include "ext2fsd.h"
|
||||
|
||||
// define the file specific bug-check id
|
||||
#define EXT2_BUG_CHECK_ID EXT2_FILE_DIR_CONTROL
|
||||
|
||||
#define DEBUG_LEVEL (DEBUG_TRACE_DIRCTRL)
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2DirControl()
|
||||
*
|
||||
* Description:
|
||||
* The I/O Manager will invoke this routine to handle a directory control
|
||||
* request
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
|
||||
* to be deferred to a worker thread context)
|
||||
*
|
||||
* Return Value: STATUS_SUCCESS/Error
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2DirControl(
|
||||
PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
PIRP Irp) // I/O Request Packet
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
PtrExt2IrpContext PtrIrpContext = NULL;
|
||||
BOOLEAN AreWeTopLevel = FALSE;
|
||||
|
||||
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "DIR Control IRP received...", 0);
|
||||
|
||||
|
||||
FsRtlEnterFileSystem();
|
||||
|
||||
ASSERT(DeviceObject);
|
||||
ASSERT(Irp);
|
||||
|
||||
// set the top level context
|
||||
AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
|
||||
|
||||
try
|
||||
{
|
||||
// get an IRP context structure and issue the request
|
||||
PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
|
||||
ASSERT(PtrIrpContext);
|
||||
|
||||
RC = Ext2CommonDirControl(PtrIrpContext, Irp);
|
||||
|
||||
}
|
||||
except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
|
||||
{
|
||||
|
||||
RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
|
||||
|
||||
Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
|
||||
}
|
||||
|
||||
if (AreWeTopLevel) {
|
||||
IoSetTopLevelIrp(NULL);
|
||||
}
|
||||
|
||||
FsRtlExitFileSystem();
|
||||
|
||||
return(RC);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2CommonDirControl()
|
||||
*
|
||||
* Description:
|
||||
* The actual work is performed here. This routine may be invoked in one'
|
||||
* of the two possible contexts:
|
||||
* (a) in the context of a system worker thread
|
||||
* (b) in the context of the original caller
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: STATUS_SUCCESS/Error
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2CommonDirControl(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp)
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
PIO_STACK_LOCATION PtrIoStackLocation = NULL;
|
||||
PFILE_OBJECT PtrFileObject = NULL;
|
||||
PtrExt2FCB PtrFCB = NULL;
|
||||
PtrExt2CCB PtrCCB = NULL;
|
||||
PtrExt2VCB PtrVCB = NULL;
|
||||
|
||||
// First, get a pointer to the current I/O stack location
|
||||
PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
|
||||
ASSERT(PtrIoStackLocation);
|
||||
|
||||
PtrFileObject = PtrIoStackLocation->FileObject;
|
||||
ASSERT(PtrFileObject);
|
||||
|
||||
// Get the FCB and CCB pointers
|
||||
PtrCCB = (PtrExt2CCB)(PtrFileObject->FsContext2);
|
||||
ASSERT(PtrCCB);
|
||||
PtrFCB = PtrCCB->PtrFCB;
|
||||
|
||||
AssertFCB( PtrFCB );
|
||||
|
||||
|
||||
// Get some of the parameters supplied to us
|
||||
switch (PtrIoStackLocation->MinorFunction) {
|
||||
case IRP_MN_QUERY_DIRECTORY:
|
||||
#ifdef _GNU_NTIFS_
|
||||
RC = Ext2QueryDirectory(PtrIrpContext, PtrIrp, (PEXTENDED_IO_STACK_LOCATION)PtrIoStackLocation, PtrFileObject, PtrFCB, PtrCCB);
|
||||
#else
|
||||
RC = Ext2QueryDirectory(PtrIrpContext, PtrIrp, PtrIoStackLocation, PtrFileObject, PtrFCB, PtrCCB);
|
||||
#endif
|
||||
break;
|
||||
case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
|
||||
{
|
||||
RC = STATUS_NOT_IMPLEMENTED;
|
||||
PtrIrp->IoStatus.Status = RC;
|
||||
PtrIrp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT);
|
||||
}
|
||||
// RC = Ext2NotifyChangeDirectory(PtrIrpContext, PtrIrp, PtrIoStackLocation, PtrFileObject, PtrFCB, PtrCCB);
|
||||
break;
|
||||
default:
|
||||
// This should not happen.
|
||||
RC = STATUS_INVALID_DEVICE_REQUEST;
|
||||
PtrIrp->IoStatus.Status = RC;
|
||||
PtrIrp->IoStatus.Information = 0;
|
||||
|
||||
// Free up the Irp Context
|
||||
Ext2ReleaseIrpContext(PtrIrpContext);
|
||||
|
||||
// complete the IRP
|
||||
IoCompleteRequest(PtrIrp, IO_NO_INCREMENT);
|
||||
break;
|
||||
}
|
||||
|
||||
return(RC);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2QueryDirectory()
|
||||
*
|
||||
* Description:
|
||||
* Query directory request.
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: STATUS_SUCCESS/Error
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2QueryDirectory(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp,
|
||||
#ifdef _GNU_NTIFS_
|
||||
PEXTENDED_IO_STACK_LOCATION PtrIoStackLocation,
|
||||
#else
|
||||
PIO_STACK_LOCATION PtrIoStackLocation,
|
||||
#endif
|
||||
PFILE_OBJECT PtrFileObject,
|
||||
PtrExt2FCB PtrFCB,
|
||||
PtrExt2CCB PtrCCB)
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
BOOLEAN CompleteRequest = TRUE;
|
||||
BOOLEAN PostRequest = FALSE;
|
||||
PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
|
||||
BOOLEAN CanWait = FALSE;
|
||||
PtrExt2VCB PtrVCB = NULL;
|
||||
BOOLEAN AcquiredFCB = FALSE;
|
||||
unsigned long BufferLength = 0;
|
||||
unsigned long BufferIndex = 0;
|
||||
unsigned long FileIndex = 0;
|
||||
PUNICODE_STRING PtrSearchPattern = NULL;
|
||||
FILE_INFORMATION_CLASS FileInformationClass;
|
||||
BOOLEAN RestartScan = FALSE;
|
||||
BOOLEAN ReturnSingleEntry = FALSE;
|
||||
BOOLEAN IndexSpecified = FALSE;
|
||||
unsigned char *Buffer = NULL;
|
||||
BOOLEAN FirstTimeQuery = FALSE;
|
||||
unsigned long StartingIndexForSearch = 0;
|
||||
unsigned long BytesReturned = 0;
|
||||
BOOLEAN BufferUsedup = FALSE;
|
||||
|
||||
BOOLEAN SearchWithWildCards = FALSE;
|
||||
|
||||
PFILE_BOTH_DIR_INFORMATION BothDirInformation = NULL;
|
||||
PFILE_FULL_DIR_INFORMATION FullDirInformation = NULL;
|
||||
PFILE_DIRECTORY_INFORMATION DirectoryInformation = NULL;
|
||||
PFILE_NAMES_INFORMATION NamesInformation = NULL;
|
||||
|
||||
|
||||
PEXT2_DIR_ENTRY PtrDirEntry = NULL;
|
||||
PEXT2_INODE PtrInode = NULL;
|
||||
|
||||
unsigned long LogicalBlockSize;
|
||||
|
||||
unsigned long ThisBlock;
|
||||
|
||||
// The starting Physical Block No...
|
||||
//LARGE_INTEGER StartPhysicalBlock;
|
||||
LARGE_INTEGER StartBufferOffset ;
|
||||
ULONG PinBufferLength;
|
||||
|
||||
// Buffer Control Block
|
||||
PBCB PtrBCB = NULL;
|
||||
BYTE * PtrPinnedBlockBuffer = NULL;
|
||||
|
||||
unsigned int i,j;
|
||||
|
||||
DebugTrace(DEBUG_TRACE_MISC, " === Querying Directory %S", PtrFCB->FCBName->ObjectName.Buffer );
|
||||
|
||||
try
|
||||
{
|
||||
// Validate the sent-in FCB
|
||||
if ((PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) || !(PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY))
|
||||
{
|
||||
// We will only allow notify requests on directories.
|
||||
RC = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
|
||||
CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
|
||||
PtrVCB = PtrFCB->PtrVCB;
|
||||
|
||||
//
|
||||
// Asynchronous IO requested
|
||||
// Posting request...
|
||||
//
|
||||
/*
|
||||
* This is incorrect because posted IRP_MJ_DIRECTORY_CONTROL
|
||||
* requests aren't handled in the worker thread yet. I tried
|
||||
* adding handling of them to the worked routine, but there
|
||||
* were problems with accessing the PtrIoStackLocation->
|
||||
* Parameters.QueryDirectory.FileName variable.
|
||||
* -- Filip Navara, 18/08/2004
|
||||
*/
|
||||
#if 0
|
||||
if (!CanWait)
|
||||
{
|
||||
PostRequest = TRUE;
|
||||
try_return(RC = STATUS_PENDING);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Obtain the callers parameters
|
||||
BufferLength = PtrIoStackLocation->Parameters.QueryDirectory.Length;
|
||||
PtrSearchPattern = ( PUNICODE_STRING ) PtrIoStackLocation->Parameters.QueryDirectory.FileName;
|
||||
FileInformationClass = PtrIoStackLocation->Parameters.QueryDirectory.FileInformationClass;
|
||||
FileIndex = PtrIoStackLocation->Parameters.QueryDirectory.FileIndex;
|
||||
|
||||
// Some additional arguments that affect the FSD behavior
|
||||
RestartScan = (PtrIoStackLocation->Flags & SL_RESTART_SCAN);
|
||||
ReturnSingleEntry = (PtrIoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY);
|
||||
IndexSpecified = (PtrIoStackLocation->Flags & SL_INDEX_SPECIFIED);
|
||||
|
||||
//
|
||||
// Acquiring exclusive access to the FCB.
|
||||
// This is not mandatory
|
||||
//
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** Going into a block to acquire FCB Exclusively[DirCtrl]", 0);
|
||||
|
||||
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [DirCtrl]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
|
||||
ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource), TRUE);
|
||||
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** FCB acquired [DirCtrl]", 0);
|
||||
AcquiredFCB = TRUE;
|
||||
|
||||
// We must determine the buffer pointer to be used. Since this
|
||||
// routine could either be invoked directly in the context of the
|
||||
// calling thread, or in the context of a worker thread, here is
|
||||
// a general way of determining what we should use.
|
||||
Buffer = Ext2GetCallersBuffer ( PtrIrp );
|
||||
|
||||
// The method of determining where to look from and what to look for is
|
||||
// unfortunately extremely confusing. However, here is a methodology you
|
||||
// you can broadly adopt:
|
||||
// (a) You have to maintain a search buffer per CCB structure.
|
||||
// (b) This search buffer is initialized the very first time
|
||||
// a query directory operation is performed using the file object.
|
||||
// (For the sample FSD, the search buffer is stored in the
|
||||
// DirectorySearchPattern field)
|
||||
// However, the caller still has the option of "overriding" this stored
|
||||
// search pattern by supplying a new one in a query directory operation.
|
||||
//
|
||||
|
||||
if( PtrCCB->DirectorySearchPattern.Length )
|
||||
{
|
||||
if( PtrCCB->DirectorySearchPattern.Buffer[PtrCCB->DirectorySearchPattern.Length/2] != 0 )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MISC, "&&&&&&&&& PtrCCB->DirectorySearchPattern not NULL terminated!", 0);
|
||||
}
|
||||
DebugTrace(DEBUG_TRACE_MISC, " === Old Search pattern %S", PtrCCB->DirectorySearchPattern.Buffer );
|
||||
}
|
||||
|
||||
if (PtrSearchPattern != NULL)
|
||||
{
|
||||
// User has supplied a search pattern
|
||||
// Now validate that the search pattern is legitimate
|
||||
|
||||
if ( PtrCCB->DirectorySearchPattern.Length == 0 )
|
||||
{
|
||||
// This must be the very first query request.
|
||||
FirstTimeQuery = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We should ignore the search pattern in the CCB and instead,
|
||||
// use the user-supplied pattern for this particular query
|
||||
// directory request.
|
||||
Ext2DeallocateUnicodeString( &PtrCCB->DirectorySearchPattern );
|
||||
}
|
||||
|
||||
// Now, allocate enough memory to contain the caller
|
||||
// supplied search pattern and fill in the DirectorySearchPattern
|
||||
// field in the CCB
|
||||
Ext2CopyUnicodeString( &PtrCCB->DirectorySearchPattern, PtrSearchPattern );
|
||||
/*
|
||||
PtrCCB->DirectorySearchPattern = Ext2AllocatePool(PagedPool, sizeof( PtrSearchPattern ) );
|
||||
ASSERT(PtrCCB->DirectorySearchPattern);
|
||||
RtlCopyMemory( PtrCCB->DirectorySearchPattern, PtrSearchPattern, sizeof( PtrSearchPattern ) );
|
||||
*/
|
||||
}
|
||||
else if ( PtrCCB->DirectorySearchPattern.Length == 0 )
|
||||
{
|
||||
// This MUST be the first directory query operation (else the
|
||||
// DirectorySearchPattern field would never be empty. Also, the caller
|
||||
// has neglected to provide a pattern so we MUST invent one.
|
||||
// Use "*" (following NT conventions) as your search pattern
|
||||
// and store it in the PtrCCB->DirectorySearchPattern field.
|
||||
|
||||
/*
|
||||
PtrCCB->DirectorySearchPattern = Ext2AllocatePool(PagedPool, sizeof(L"*") );
|
||||
ASSERT(PtrCCB->DirectorySearchPattern);
|
||||
RtlCopyMemory( PtrCCB->DirectorySearchPattern, L"*", 4 );*/
|
||||
|
||||
Ext2CopyWideCharToUnicodeString( &PtrCCB->DirectorySearchPattern, L"*" );
|
||||
|
||||
FirstTimeQuery = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The caller has not supplied any search pattern...
|
||||
// Using previously supplied pattern
|
||||
PtrSearchPattern = &PtrCCB->DirectorySearchPattern;
|
||||
}
|
||||
|
||||
if( PtrCCB->DirectorySearchPattern.Buffer[PtrCCB->DirectorySearchPattern.Length/2] != 0 )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MISC, "&&&&&&&&& PtrCCB->DirectorySearchPattern not NULL terminated!", 0 );
|
||||
}
|
||||
DebugTrace(DEBUG_TRACE_MISC, " === Search pattern %S", PtrCCB->DirectorySearchPattern.Buffer );
|
||||
SearchWithWildCards = FsRtlDoesNameContainWildCards( PtrSearchPattern );
|
||||
|
||||
// There is one other piece of information that your FSD must store
|
||||
// in the CCB structure for query directory support. This is the index
|
||||
// value (i.e. the offset in your on-disk directory structure) from
|
||||
// which you should start searching.
|
||||
// However, the flags supplied with the IRP can make us override this
|
||||
// as well.
|
||||
|
||||
if (FileIndex)
|
||||
{
|
||||
// Caller has told us wherefrom to begin.
|
||||
// You may need to round this to an appropriate directory entry
|
||||
// entry alignment value.
|
||||
StartingIndexForSearch = FileIndex;
|
||||
}
|
||||
else if (RestartScan)
|
||||
{
|
||||
StartingIndexForSearch = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the starting offset from the CCB.
|
||||
StartingIndexForSearch = PtrCCB->CurrentByteOffset.LowPart;
|
||||
}
|
||||
|
||||
// Read in the file inode if it hasn't already been read...
|
||||
Ext2InitializeFCBInodeInfo( PtrFCB );
|
||||
|
||||
if (PtrFileObject->PrivateCacheMap == NULL)
|
||||
{
|
||||
CcInitializeCacheMap(PtrFileObject, (PCC_FILE_SIZES)(&(PtrReqdFCB->CommonFCBHeader.AllocationSize)),
|
||||
TRUE, // We will utilize pin access for directories
|
||||
&(Ext2GlobalData.CacheMgrCallBacks), // callbacks
|
||||
PtrCCB); // The context used in callbacks
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Read in the next Data Block of this directory
|
||||
//
|
||||
LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
|
||||
StartBufferOffset.QuadPart = ( StartingIndexForSearch / LogicalBlockSize );
|
||||
StartBufferOffset.QuadPart *= LogicalBlockSize; // This should be the StartBufferOffset alaigned to LBlock boundary...
|
||||
|
||||
PinBufferLength = PtrReqdFCB->CommonFCBHeader.FileSize.LowPart - StartBufferOffset.LowPart;
|
||||
|
||||
if ( !CcMapData( PtrFileObject,
|
||||
&StartBufferOffset,
|
||||
PinBufferLength,
|
||||
TRUE,
|
||||
&PtrBCB,
|
||||
(PVOID*)&PtrPinnedBlockBuffer ) )
|
||||
{
|
||||
// Read Failure
|
||||
DebugTrace(DEBUG_TRACE_MISC, "Cache read failiure while reading in volume meta data", 0);
|
||||
try_return( STATUS_ACCESS_DENIED );
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MISC, "Cache hit while reading in volume meta data", 0);
|
||||
}
|
||||
|
||||
PtrInode = Ext2AllocatePool( PagedPool, sizeof( EXT2_INODE ) );
|
||||
|
||||
//
|
||||
// Walking through the directory entries...
|
||||
for( BufferUsedup = FALSE, BufferIndex = 0; !BufferUsedup && StartingIndexForSearch < ( PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart - 1) ; )
|
||||
{
|
||||
PtrDirEntry = (PEXT2_DIR_ENTRY) &PtrPinnedBlockBuffer[ StartingIndexForSearch - StartBufferOffset.LowPart ];
|
||||
|
||||
StartingIndexForSearch += PtrDirEntry->rec_len;
|
||||
PtrCCB->CurrentByteOffset.LowPart = StartingIndexForSearch;
|
||||
|
||||
if( PtrDirEntry->inode == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if( PtrDirEntry->name_len == 0 || PtrDirEntry->rec_len == 0 )
|
||||
{
|
||||
//
|
||||
// This should not happen
|
||||
// Hqw can this be so!!!
|
||||
//
|
||||
Ext2BreakPoint();
|
||||
if( BothDirInformation )
|
||||
{
|
||||
BothDirInformation->NextEntryOffset = 0;
|
||||
}
|
||||
if( !BytesReturned )
|
||||
{
|
||||
if( FirstTimeQuery )
|
||||
RC = STATUS_NO_SUCH_FILE;
|
||||
else
|
||||
RC = STATUS_NO_MORE_FILES;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Does this entry match the search criterian?
|
||||
// Checking
|
||||
//
|
||||
{
|
||||
UNICODE_STRING FileName;
|
||||
LONG Matched = 0;
|
||||
// Constructing a counted Unicode string out of PtrDirEntry
|
||||
Ext2CopyCharToUnicodeString( &FileName, PtrDirEntry->name, PtrDirEntry->name_len );
|
||||
|
||||
if ( SearchWithWildCards )
|
||||
{
|
||||
Matched = FsRtlIsNameInExpression ( PtrSearchPattern, &FileName, FALSE, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
Matched = ! RtlCompareUnicodeString( PtrSearchPattern, &FileName, FALSE );
|
||||
}
|
||||
|
||||
Ext2DeallocateUnicodeString( &FileName );
|
||||
if( !Matched )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
switch( FileInformationClass )
|
||||
{
|
||||
case FileBothDirectoryInformation:
|
||||
|
||||
DebugTrace(DEBUG_TRACE_DIRINFO, " === FileBothDirectoryInformation", 0 );
|
||||
ThisBlock = sizeof( FILE_BOTH_DIR_INFORMATION );
|
||||
ThisBlock += PtrDirEntry->name_len*2;
|
||||
ThisBlock = Ext2QuadAlign( ThisBlock );
|
||||
|
||||
if( ( BufferIndex + ThisBlock ) > BufferLength )
|
||||
{
|
||||
//
|
||||
// Next entry won't fit into the buffer...
|
||||
// will have to return...
|
||||
// :(
|
||||
//
|
||||
if( BothDirInformation )
|
||||
BothDirInformation->NextEntryOffset = 0;
|
||||
if( !BytesReturned )
|
||||
RC = STATUS_NO_MORE_FILES;
|
||||
BufferUsedup = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
Ext2ReadInode( PtrVCB, PtrDirEntry->inode, PtrInode );
|
||||
if( !PtrInode )
|
||||
{
|
||||
try_return( RC = STATUS_UNSUCCESSFUL );
|
||||
}
|
||||
|
||||
BothDirInformation = ( PFILE_BOTH_DIR_INFORMATION ) ( Buffer + ( BufferIndex ) );
|
||||
BothDirInformation->EaSize = 0;
|
||||
BothDirInformation->AllocationSize.QuadPart = PtrInode->i_blocks * 512;
|
||||
BothDirInformation->EndOfFile.QuadPart = PtrInode->i_size;
|
||||
BothDirInformation->ChangeTime.QuadPart = 0;
|
||||
|
||||
BothDirInformation->CreationTime.QuadPart = ( __int64 ) PtrInode->i_ctime * 10000000;
|
||||
BothDirInformation->CreationTime.QuadPart += Ext2GlobalData.TimeDiff.QuadPart;
|
||||
|
||||
BothDirInformation->LastAccessTime.QuadPart = Ext2GlobalData.TimeDiff.QuadPart + ( ( __int64 ) PtrInode->i_atime * 10000000 );
|
||||
BothDirInformation->LastWriteTime.QuadPart = Ext2GlobalData.TimeDiff.QuadPart + ( ( __int64 )PtrInode->i_mtime * 10000000 );
|
||||
|
||||
// Getting the file type...
|
||||
BothDirInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||
if( ! Ext2IsModeRegularFile( PtrInode->i_mode ) )
|
||||
{
|
||||
// Not a reqular file...
|
||||
if( Ext2IsModeDirectory( PtrInode->i_mode) )
|
||||
{
|
||||
// Directory...
|
||||
BothDirInformation->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Special File...
|
||||
// Treated with respect... ;)
|
||||
//
|
||||
BothDirInformation->FileAttributes |= ( FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
|
||||
// FILE_ATTRIBUTE_DEVICE
|
||||
}
|
||||
if ( Ext2IsModeHidden( PtrInode->i_mode ) )
|
||||
{
|
||||
BothDirInformation->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
|
||||
}
|
||||
|
||||
if ( Ext2IsModeReadOnly( PtrInode->i_mode ) )
|
||||
{
|
||||
BothDirInformation->FileAttributes |= FILE_ATTRIBUTE_READONLY;
|
||||
}
|
||||
}
|
||||
|
||||
BothDirInformation->FileIndex = StartingIndexForSearch;
|
||||
BothDirInformation->FileNameLength = PtrDirEntry->name_len*2 + 2;
|
||||
BothDirInformation->ShortNameLength = 0;
|
||||
BothDirInformation->ShortName[0] = 0;
|
||||
|
||||
// Copying out the name as WCHAR null terminated strings
|
||||
for( j = 0; j< PtrDirEntry->name_len ; j ++ )
|
||||
{
|
||||
// BothDirInformation->ShortName[ j ] = PtrDirEntry->name[j];
|
||||
BothDirInformation->FileName[ j ] = PtrDirEntry->name[j];
|
||||
// if( j < 11 )
|
||||
// BothDirInformation->ShortName[j] = PtrDirEntry->name[j];;
|
||||
}
|
||||
|
||||
/*
|
||||
if( j < 11 )
|
||||
{
|
||||
BothDirInformation->ShortNameLength = j * 2 + 2;
|
||||
BothDirInformation->ShortName[ j ] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
BothDirInformation->ShortNameLength = 24;
|
||||
BothDirInformation->ShortName[ 11 ] = 0;
|
||||
}*/
|
||||
|
||||
BothDirInformation->FileName[ j ] = 0;
|
||||
BytesReturned += ThisBlock;
|
||||
BufferIndex += ThisBlock;
|
||||
|
||||
if( !ReturnSingleEntry && ( StartingIndexForSearch < ( PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart - 1) ))
|
||||
BothDirInformation->NextEntryOffset = ThisBlock;
|
||||
else
|
||||
BothDirInformation->NextEntryOffset = 0;
|
||||
break;
|
||||
|
||||
case FileDirectoryInformation:
|
||||
// DirectoryInformation
|
||||
DebugTrace(DEBUG_TRACE_DIRINFO, " === FileDirectoryInformation", 0 );
|
||||
ThisBlock = sizeof( FILE_DIRECTORY_INFORMATION );
|
||||
ThisBlock += PtrDirEntry->name_len*2;
|
||||
ThisBlock = Ext2QuadAlign( ThisBlock );
|
||||
|
||||
if( ( BufferIndex + ThisBlock ) > BufferLength )
|
||||
{
|
||||
//
|
||||
// Next entry won't fit into the buffer...
|
||||
// will have to return...
|
||||
// :(
|
||||
//
|
||||
if( DirectoryInformation )
|
||||
DirectoryInformation->NextEntryOffset = 0;
|
||||
if( !BytesReturned )
|
||||
RC = STATUS_NO_MORE_FILES;
|
||||
BufferUsedup = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
Ext2ReadInode( PtrVCB, PtrDirEntry->inode, PtrInode );
|
||||
if( !PtrInode )
|
||||
{
|
||||
try_return( RC = STATUS_UNSUCCESSFUL );
|
||||
}
|
||||
|
||||
DirectoryInformation = ( PFILE_DIRECTORY_INFORMATION ) ( Buffer + ( BufferIndex ) );
|
||||
DirectoryInformation->AllocationSize.QuadPart = PtrInode->i_blocks * 512;
|
||||
DirectoryInformation->EndOfFile.QuadPart = PtrInode->i_size;
|
||||
DirectoryInformation->ChangeTime.QuadPart = 0;
|
||||
|
||||
DirectoryInformation->CreationTime.QuadPart = ( __int64 ) PtrInode->i_ctime * 10000000;
|
||||
DirectoryInformation->CreationTime.QuadPart += Ext2GlobalData.TimeDiff.QuadPart;
|
||||
|
||||
DirectoryInformation->LastAccessTime.QuadPart = Ext2GlobalData.TimeDiff.QuadPart + ( ( __int64 ) PtrInode->i_atime * 10000000 );
|
||||
DirectoryInformation->LastWriteTime.QuadPart = Ext2GlobalData.TimeDiff.QuadPart + ( ( __int64 )PtrInode->i_mtime * 10000000 );
|
||||
|
||||
// Getting the file type...
|
||||
DirectoryInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||
if( ! Ext2IsModeRegularFile( PtrInode->i_mode ) )
|
||||
{
|
||||
// Not a reqular file...
|
||||
if( Ext2IsModeDirectory( PtrInode->i_mode) )
|
||||
{
|
||||
// Directory...
|
||||
DirectoryInformation->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Special File...
|
||||
// Treated with respect... ;)
|
||||
//
|
||||
DirectoryInformation->FileAttributes |= ( FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
|
||||
// FILE_ATTRIBUTE_DEVICE
|
||||
}
|
||||
if ( Ext2IsModeHidden( PtrInode->i_mode ) )
|
||||
{
|
||||
DirectoryInformation->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
|
||||
}
|
||||
|
||||
if ( Ext2IsModeReadOnly( PtrInode->i_mode ) )
|
||||
{
|
||||
DirectoryInformation->FileAttributes |= FILE_ATTRIBUTE_READONLY;
|
||||
}
|
||||
}
|
||||
|
||||
DirectoryInformation->FileIndex = StartingIndexForSearch;
|
||||
DirectoryInformation->FileNameLength = PtrDirEntry->name_len*2 + 2;
|
||||
|
||||
// Copying out the name as WCHAR null terminated strings
|
||||
for( j = 0; j< PtrDirEntry->name_len ; j ++ )
|
||||
{
|
||||
DirectoryInformation->FileName[ j ] = PtrDirEntry->name[j];
|
||||
}
|
||||
|
||||
DirectoryInformation->FileName[ j ] = 0;
|
||||
BytesReturned += ThisBlock;
|
||||
BufferIndex += ThisBlock;
|
||||
|
||||
if( !ReturnSingleEntry && ( StartingIndexForSearch < ( PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart - 1) ))
|
||||
DirectoryInformation->NextEntryOffset = ThisBlock;
|
||||
else
|
||||
DirectoryInformation->NextEntryOffset = 0;
|
||||
break;
|
||||
|
||||
case FileFullDirectoryInformation:
|
||||
// FullDirInformation->
|
||||
DebugTrace(DEBUG_TRACE_DIRINFO, " === FileFullDirectoryInformation - Not handled", 0 );
|
||||
try_return( RC );
|
||||
case FileNamesInformation:
|
||||
// NamesInformation->
|
||||
DebugTrace(DEBUG_TRACE_DIRINFO, " === FileNamesInformation - Not handled", 0 );
|
||||
try_return( RC );
|
||||
default:
|
||||
DebugTrace(DEBUG_TRACE_DIRINFO, " === Invalid Dir Info class - Not handled", 0 );
|
||||
try_return( RC = STATUS_INVALID_INFO_CLASS );
|
||||
}
|
||||
if( ReturnSingleEntry )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}// end of for...
|
||||
|
||||
|
||||
|
||||
if( !BytesReturned && StartingIndexForSearch >= ( PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart) )
|
||||
{
|
||||
Ext2DeallocateUnicodeString( &PtrCCB->DirectorySearchPattern );
|
||||
PtrCCB->CurrentByteOffset.QuadPart = 0;
|
||||
if( FirstTimeQuery )
|
||||
RC = STATUS_NO_SUCH_FILE;
|
||||
else
|
||||
RC = STATUS_NO_MORE_FILES;
|
||||
try_return( RC );
|
||||
}
|
||||
else if( BytesReturned )
|
||||
{
|
||||
BothDirInformation->NextEntryOffset = 0;
|
||||
}
|
||||
|
||||
try_exit: NOTHING;
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
if( PtrInode )
|
||||
{
|
||||
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [DirCtrl]", PtrInode );
|
||||
ExFreePool( PtrInode );
|
||||
}
|
||||
|
||||
if( PtrBCB )
|
||||
{
|
||||
CcUnpinData( PtrBCB );
|
||||
PtrBCB = NULL;
|
||||
}
|
||||
|
||||
if (PostRequest)
|
||||
{
|
||||
if (AcquiredFCB)
|
||||
{
|
||||
Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released in [DirCtrl]", 0);
|
||||
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [DirCtrl]",
|
||||
PtrReqdFCB->MainResource.ActiveCount,
|
||||
PtrReqdFCB->MainResource.NumberOfExclusiveWaiters,
|
||||
PtrReqdFCB->MainResource.NumberOfSharedWaiters );
|
||||
}
|
||||
|
||||
// Map the users buffer and then post the request.
|
||||
RC = Ext2LockCallersBuffer(PtrIrp, TRUE, BufferLength);
|
||||
ASSERT(NT_SUCCESS(RC));
|
||||
|
||||
RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
|
||||
|
||||
}
|
||||
else if (!(PtrIrpContext->IrpContextFlags &
|
||||
EXT2_IRP_CONTEXT_EXCEPTION))
|
||||
{
|
||||
if (AcquiredFCB)
|
||||
{
|
||||
Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [DirCtrl]", 0);
|
||||
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [DirCtrl]",
|
||||
PtrReqdFCB->MainResource.ActiveCount,
|
||||
PtrReqdFCB->MainResource.NumberOfExclusiveWaiters,
|
||||
PtrReqdFCB->MainResource.NumberOfSharedWaiters );
|
||||
}
|
||||
|
||||
// Complete the request.
|
||||
PtrIrp->IoStatus.Status = RC;
|
||||
PtrIrp->IoStatus.Information = BytesReturned;
|
||||
|
||||
// Free up the Irp Context
|
||||
Ext2ReleaseIrpContext(PtrIrpContext);
|
||||
|
||||
// complete the IRP
|
||||
IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT);
|
||||
}
|
||||
|
||||
// Flush the saved BCBs...
|
||||
// Ext2FlushSavedBCBs ( PtrIrpContext );
|
||||
|
||||
}
|
||||
|
||||
return(RC);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2NotifyChangeDirectory()
|
||||
*
|
||||
* Description:
|
||||
* Handle the notify request.
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: STATUS_SUCCESS/Error
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2NotifyChangeDirectory(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp,
|
||||
#ifdef _GNU_NTIFS_
|
||||
PEXTENDED_IO_STACK_LOCATION PtrIoStackLocation,
|
||||
#else
|
||||
PIO_STACK_LOCATION PtrIoStackLocation,
|
||||
#endif
|
||||
PFILE_OBJECT PtrFileObject,
|
||||
PtrExt2FCB PtrFCB,
|
||||
PtrExt2CCB PtrCCB)
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
BOOLEAN CompleteRequest = FALSE;
|
||||
BOOLEAN PostRequest = FALSE;
|
||||
PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
|
||||
BOOLEAN CanWait = FALSE;
|
||||
ULONG CompletionFilter = 0;
|
||||
BOOLEAN WatchTree = FALSE;
|
||||
PtrExt2VCB PtrVCB = NULL;
|
||||
BOOLEAN AcquiredFCB = FALSE;
|
||||
|
||||
try {
|
||||
|
||||
// Validate the sent-in FCB
|
||||
if ((PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) || !(PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY)) {
|
||||
// We will only allow notify requests on directories.
|
||||
RC = STATUS_INVALID_PARAMETER;
|
||||
CompleteRequest = TRUE;
|
||||
}
|
||||
|
||||
PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
|
||||
CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
|
||||
PtrVCB = PtrFCB->PtrVCB;
|
||||
|
||||
// Acquire the FCB resource shared
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire FCB Shared[DirCtrl]", 0);
|
||||
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [DirCtrl]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
|
||||
if (!ExAcquireResourceSharedLite(&(PtrReqdFCB->MainResource), CanWait))
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Acquisition FAILED [DirCtrl]", 0);
|
||||
PostRequest = TRUE;
|
||||
try_return(RC = STATUS_PENDING);
|
||||
}
|
||||
AcquiredFCB = TRUE;
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** FCB acquired [DirCtrl]", 0);
|
||||
|
||||
// Obtain some parameters sent by the caller
|
||||
CompletionFilter = PtrIoStackLocation->Parameters.NotifyDirectory.CompletionFilter;
|
||||
WatchTree = (PtrIoStackLocation->Flags & SL_WATCH_TREE ? TRUE : FALSE);
|
||||
|
||||
// If you wish to capture the subject context, you can do so as
|
||||
// follows:
|
||||
// {
|
||||
// PSECURITY_SUBJECT_CONTEXT SubjectContext;
|
||||
// SubjectContext = Ext2AllocatePool(PagedPool,
|
||||
// sizeof(SECURITY_SUBJECT_CONTEXT) );
|
||||
// SeCaptureSubjectContext(SubjectContext);
|
||||
// }
|
||||
|
||||
FsRtlNotifyFullChangeDirectory((PNOTIFY_SYNC)&(PtrVCB->NotifyIRPMutex), &(PtrVCB->NextNotifyIRP), (void *)PtrCCB,
|
||||
(PSTRING)(PtrFCB->FCBName->ObjectName.Buffer), WatchTree, FALSE, CompletionFilter, PtrIrp,
|
||||
NULL, // Ext2TraverseAccessCheck(...) ?
|
||||
NULL); // SubjectContext ?
|
||||
|
||||
RC = STATUS_PENDING;
|
||||
|
||||
try_exit: NOTHING;
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
if (PostRequest)
|
||||
{
|
||||
// Perform appropriate post related processing here
|
||||
if (AcquiredFCB)
|
||||
{
|
||||
Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released in DirCtrl", 0);
|
||||
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [DirCtrl]",
|
||||
PtrReqdFCB->MainResource.ActiveCount,
|
||||
PtrReqdFCB->MainResource.NumberOfExclusiveWaiters,
|
||||
PtrReqdFCB->MainResource.NumberOfSharedWaiters );
|
||||
|
||||
AcquiredFCB = FALSE;
|
||||
}
|
||||
RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
|
||||
}
|
||||
else if (CompleteRequest)
|
||||
{
|
||||
PtrIrp->IoStatus.Status = RC;
|
||||
PtrIrp->IoStatus.Information = 0;
|
||||
|
||||
// Free up the Irp Context
|
||||
Ext2ReleaseIrpContext(PtrIrpContext);
|
||||
|
||||
// complete the IRP
|
||||
IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT);
|
||||
} else {
|
||||
// Simply free up the IrpContext since the IRP has been queued
|
||||
Ext2ReleaseIrpContext(PtrIrpContext);
|
||||
}
|
||||
|
||||
// Release the FCB resources if acquired.
|
||||
if (AcquiredFCB)
|
||||
{
|
||||
Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** FReleased in [DirCtrl]", 0);
|
||||
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [DirCtrl]",
|
||||
PtrReqdFCB->MainResource.ActiveCount,
|
||||
PtrReqdFCB->MainResource.NumberOfExclusiveWaiters,
|
||||
PtrReqdFCB->MainResource.NumberOfSharedWaiters );
|
||||
|
||||
AcquiredFCB = FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return(RC);
|
||||
}
|
116
reactos/drivers/filesystems/ext2/src/ext2.rc
Normal file
116
reactos/drivers/filesystems/ext2/src/ext2.rc
Normal file
|
@ -0,0 +1,116 @@
|
|||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "../inc/resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#define APSTUDIO_HIDDEN_SYMBOLS
|
||||
#include "windows.h"
|
||||
#undef APSTUDIO_HIDDEN_SYMBOLS
|
||||
/* REACTOS FIXME */
|
||||
/* #include "ntverp.h" */
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"..\\inc\\resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"#include ""windows.h""\r\n"
|
||||
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"#include ""ntverp.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
#ifndef _MAC
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,0,0,3
|
||||
PRODUCTVERSION 0,0,0,3
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x29L
|
||||
#else
|
||||
FILEFLAGS 0x28L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x3L
|
||||
FILESUBTYPE 0x7L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "Ext2 File System Driver\0"
|
||||
VALUE "CompanyName", "Purayidathil\0"
|
||||
VALUE "FileDescription", "Ext2 File System Driver\0"
|
||||
VALUE "FileVersion", "0, 0, 0, 3\0"
|
||||
VALUE "InternalName", "ext2.sys\0"
|
||||
VALUE "LegalCopyright", "Copyright © 2002 Manoj Paul Joseph\0"
|
||||
VALUE "LegalTrademarks", " - \0"
|
||||
VALUE "OriginalFilename", "ext2.sys\0"
|
||||
VALUE "PrivateBuild", " - \0"
|
||||
VALUE "ProductName", "Ext2 File System Driver for Windows NT\0"
|
||||
VALUE "ProductVersion", "0, 0, 0, 3\0"
|
||||
VALUE "SpecialBuild", " - \0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // !_MAC
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
381
reactos/drivers/filesystems/ext2/src/ext2init.c
Normal file
381
reactos/drivers/filesystems/ext2/src/ext2init.c
Normal file
|
@ -0,0 +1,381 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* File: ext2init.c
|
||||
*
|
||||
* Module: Ext2 File System Driver (Kernel mode execution only)
|
||||
*
|
||||
* Description:
|
||||
* This file contains the initialization code for the kernel mode
|
||||
* Ext2 FSD module. The DriverEntry() routine is called by the I/O
|
||||
* sub-system to initialize the FSD.
|
||||
*
|
||||
* Author: Manoj Paul Joseph
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#include "ext2fsd.h"
|
||||
|
||||
// define the file specific bug-check id
|
||||
#define EXT2_BUG_CHECK_ID EXT2_FILE_INIT
|
||||
#define DEBUG_LEVEL (DEBUG_TRACE_INIT)
|
||||
|
||||
#define EXT2_FS_NAME L"\\ext2"
|
||||
|
||||
// global variables are declared here
|
||||
Ext2Data Ext2GlobalData;
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: DriverEntry()
|
||||
*
|
||||
* Description:
|
||||
* This routine is the standard entry point for all kernel mode drivers.
|
||||
* The routine is invoked at IRQL PASSIVE_LEVEL in the context of a
|
||||
* system worker thread.
|
||||
* All FSD specific data structures etc. are initialized here.
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: STATUS_SUCCESS/Error (will cause driver to be unloaded).
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS DriverEntry(
|
||||
PDRIVER_OBJECT DriverObject, // created by the I/O sub-system
|
||||
PUNICODE_STRING RegistryPath) // path to the registry key
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
UNICODE_STRING DriverDeviceName;
|
||||
BOOLEAN RegisteredShutdown = FALSE;
|
||||
|
||||
#if 0
|
||||
Ext2BreakPoint();
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Ext2 File System Driver Entry <<<<<<<", 0);
|
||||
// initialize the global data structure
|
||||
RtlZeroMemory(&Ext2GlobalData, sizeof(Ext2GlobalData));
|
||||
|
||||
// initialize some required fields
|
||||
Ext2GlobalData.NodeIdentifier.NodeType = EXT2_NODE_TYPE_GLOBAL_DATA;
|
||||
Ext2GlobalData.NodeIdentifier.NodeSize = sizeof(Ext2GlobalData);
|
||||
|
||||
// initialize the global data resource and remember the fact that
|
||||
// the resource has been initialized
|
||||
RC = ExInitializeResourceLite(&(Ext2GlobalData.GlobalDataResource));
|
||||
ASSERT(NT_SUCCESS(RC));
|
||||
Ext2SetFlag(Ext2GlobalData.Ext2Flags, EXT2_DATA_FLAGS_RESOURCE_INITIALIZED);
|
||||
|
||||
// keep a ptr to the driver object sent to us by the I/O Mgr
|
||||
Ext2GlobalData.Ext2DriverObject = DriverObject;
|
||||
|
||||
// initialize the mounted logical volume list head
|
||||
InitializeListHead( &( Ext2GlobalData.NextVCB ) );
|
||||
|
||||
// before we proceed with any more initialization, read in
|
||||
// user supplied configurable values ...
|
||||
// if (!NT_SUCCESS(RC = Ext2ObtainRegistryValues(RegistryPath))) {
|
||||
// in your commercial driver implementation, it would be
|
||||
// advisable for your driver to print an appropriate error
|
||||
// message to the system error log before leaving
|
||||
// try_return(RC);
|
||||
// }
|
||||
|
||||
// we should have the registry data (if any), allocate zone memory ...
|
||||
// This is an example of when FSD implementations try to pre-allocate
|
||||
// some fixed amount of memory to avoid internal fragmentation and/or waiting
|
||||
// later during run-time ...
|
||||
|
||||
#ifdef USE_ZONES
|
||||
|
||||
if (!NT_SUCCESS(RC = Ext2InitializeZones()))
|
||||
{
|
||||
// we failed, print a message and leave ...
|
||||
try_return(RC);
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Initialize the Thread queue structure...
|
||||
//
|
||||
KeInitializeEvent(
|
||||
&Ext2GlobalData.ThreadQueue.QueueEvent,
|
||||
SynchronizationEvent,
|
||||
FALSE
|
||||
);
|
||||
KeInitializeSpinLock( &Ext2GlobalData.ThreadQueue.SpinLock );
|
||||
InitializeListHead( &Ext2GlobalData.ThreadQueue.ThreadQueueListHead );
|
||||
|
||||
//
|
||||
// Done Initializing...
|
||||
// Now Creating a worker thread to handle Worker threads...
|
||||
//
|
||||
PsCreateSystemThread(
|
||||
&Ext2GlobalData.ThreadQueue.QueueHandlerThread, (ACCESS_MASK) 0L,
|
||||
NULL, NULL, NULL, Ext2QueueHandlerThread, NULL );
|
||||
|
||||
// initialize the IRP major function table, and the fast I/O table
|
||||
Ext2FsdInitializeFunctionPointers(DriverObject);
|
||||
|
||||
// create a device object representing the driver itself
|
||||
// so that requests can be targeted to the driver ...
|
||||
// e.g. for a disk-based FSD, "mount" requests will be sent to
|
||||
// this device object by the I/O Manager.\
|
||||
// For a redirector/server, you may have applications
|
||||
// send "special" IOCTL's using this device object ...
|
||||
RtlInitUnicodeString(&DriverDeviceName, EXT2_FS_NAME);
|
||||
if (!NT_SUCCESS(RC = IoCreateDevice(
|
||||
DriverObject, // our driver object
|
||||
0, // don't need an extension for this object
|
||||
&DriverDeviceName,// name - can be used to "open" the driver
|
||||
// see the book for alternate choices
|
||||
FILE_DEVICE_DISK_FILE_SYSTEM,
|
||||
0, // no special characteristics
|
||||
// do not want this as an exclusive device, though you might
|
||||
FALSE,
|
||||
&(Ext2GlobalData.Ext2DeviceObject))))
|
||||
{
|
||||
// failed to create a device object, leave ...
|
||||
try_return(RC);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// register the driver with the I/O Manager, pretend as if this is
|
||||
// a physical disk based FSD (or in order words, this FSD manages
|
||||
// logical volumes residing on physical disk drives)
|
||||
IoRegisterFileSystem(Ext2GlobalData.Ext2DeviceObject);
|
||||
|
||||
{
|
||||
TIME_FIELDS TimeFields;
|
||||
|
||||
TimeFields.Day = 1;
|
||||
TimeFields.Hour = 0;
|
||||
TimeFields.Milliseconds = 0;
|
||||
TimeFields.Minute = 0;
|
||||
TimeFields.Month = 1;
|
||||
TimeFields.Second = 0;
|
||||
TimeFields.Weekday = 0;
|
||||
TimeFields.Year = 1970;
|
||||
RtlTimeFieldsToTime( &TimeFields, &Ext2GlobalData.TimeDiff );
|
||||
|
||||
/*
|
||||
Ext2GlobalData.TimeDiff.QuadPart = 0;
|
||||
RtlTimeToTimeFields( &Ext2GlobalData.TimeDiff,&TimeFields );
|
||||
TimeFields.Year = 2002;
|
||||
RtlTimeFieldsToTime( &TimeFields, &Ext2GlobalData.TimeDiff );
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
// we encountered an exception somewhere, eat it up
|
||||
RC = GetExceptionCode();
|
||||
}
|
||||
|
||||
try_exit: NOTHING;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// start unwinding if we were unsuccessful
|
||||
if (!NT_SUCCESS(RC))
|
||||
{
|
||||
|
||||
// Now, delete any device objects, etc. we may have created
|
||||
if (Ext2GlobalData.Ext2DeviceObject)
|
||||
{
|
||||
IoDeleteDevice(Ext2GlobalData.Ext2DeviceObject);
|
||||
Ext2GlobalData.Ext2DeviceObject = NULL;
|
||||
}
|
||||
|
||||
// free up any memory we might have reserved for zones/lookaside
|
||||
// lists
|
||||
if (Ext2GlobalData.Ext2Flags & EXT2_DATA_FLAGS_ZONES_INITIALIZED)
|
||||
{
|
||||
Ext2DestroyZones();
|
||||
}
|
||||
|
||||
// delete the resource we may have initialized
|
||||
if (Ext2GlobalData.Ext2Flags & EXT2_DATA_FLAGS_RESOURCE_INITIALIZED)
|
||||
{
|
||||
// un-initialize this resource
|
||||
ExDeleteResourceLite(&(Ext2GlobalData.GlobalDataResource));
|
||||
Ext2ClearFlag(Ext2GlobalData.Ext2Flags, EXT2_DATA_FLAGS_RESOURCE_INITIALIZED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(RC);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2FsdInitializeFunctionPointers()
|
||||
*
|
||||
* Description:
|
||||
* Initialize the IRP... function pointer array in the driver object
|
||||
* structure. Also initialize the fast-io function ptr array ...
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: None
|
||||
*
|
||||
*************************************************************************/
|
||||
void Ext2FsdInitializeFunctionPointers(
|
||||
PDRIVER_OBJECT DriverObject) // created by the I/O sub-system
|
||||
{
|
||||
PFAST_IO_DISPATCH PtrFastIoDispatch = NULL;
|
||||
|
||||
// initialize the function pointers for the IRP major
|
||||
// functions that this FSD is prepared to handle ...
|
||||
// NT Version 4.0 has 28 possible functions that a
|
||||
// kernel mode driver can handle.
|
||||
// NT Version 3.51 and before has only 22 such functions,
|
||||
// of which 18 are typically interesting to most FSD's.
|
||||
|
||||
// The only interesting new functions that a FSD might
|
||||
// want to respond to beginning with Version 4.0 are the
|
||||
// IRP_MJ_QUERY_QUOTA and the IRP_MJ_SET_QUOTA requests.
|
||||
|
||||
// The code below does not handle quota manipulation, neither
|
||||
// does the NT Version 4.0 operating system (or I/O Manager).
|
||||
// However, you should be on the lookout for any such new
|
||||
// functionality that your FSD might have to implement in
|
||||
// the near future.
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = Ext2Create;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = Ext2Close;
|
||||
DriverObject->MajorFunction[IRP_MJ_READ] = Ext2Read;
|
||||
DriverObject->MajorFunction[IRP_MJ_WRITE] = Ext2Write;
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = Ext2FileInfo;
|
||||
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = Ext2FileInfo;
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = Ext2Flush;
|
||||
// To implement support for querying and modifying volume attributes
|
||||
// (volume information query/set operations), enable initialization
|
||||
// of the following two function pointers and then implement the supporting
|
||||
// functions. Use Chapter 11 in the text to assist you in your efforts.
|
||||
DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = Ext2QueryVolInfo;
|
||||
DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = Ext2SetVolInfo;
|
||||
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = Ext2DirControl;
|
||||
// To implement support for file system IOCTL calls, enable initialization
|
||||
// of the following function pointer and implement appropriate support. Use
|
||||
// Chapter 11 in the text to assist you in your efforts.
|
||||
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = Ext2FileSystemControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Ext2DeviceControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = Ext2Shutdown;
|
||||
// For byte-range lock support, enable initialization of the following
|
||||
// function pointer and implement appropriate support. Use Chapter 10
|
||||
// in the text to assist you in your efforts.
|
||||
// DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = Ext2LockControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = Ext2Cleanup;
|
||||
// If your FSD supports security attributes, you should provide appropriate
|
||||
// dispatch entry points and initialize the function pointers as given below.
|
||||
// DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = Ext2Security;
|
||||
// DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = Ext2Security;
|
||||
// If you support extended attributes, you should provide appropriate
|
||||
// dispatch entry points and initialize the function pointers as given below.
|
||||
// DriverObject->MajorFunction[IRP_MJ_QUERY_EA] = Ext2ExtendedAttr;
|
||||
// DriverObject->MajorFunction[IRP_MJ_SET_EA] = Ext2ExtendedAttr;
|
||||
|
||||
// Now, it is time to initialize the fast-io stuff ...
|
||||
/*
|
||||
DriverObject->FastIoDispatch = NULL;
|
||||
|
||||
*/
|
||||
PtrFastIoDispatch = DriverObject->FastIoDispatch = &(Ext2GlobalData.Ext2FastIoDispatch);
|
||||
|
||||
// initialize the global fast-io structure
|
||||
// NOTE: The fast-io structure has undergone a substantial revision
|
||||
// in Windows NT Version 4.0. The structure has been extensively expanded.
|
||||
// Therefore, if your driver needs to work on both V3.51 and V4.0+,
|
||||
// you will have to be able to distinguish between the two versions at compile time.
|
||||
PtrFastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
|
||||
PtrFastIoDispatch->FastIoCheckIfPossible = Ext2FastIoCheckIfPossible;
|
||||
PtrFastIoDispatch->FastIoRead = Ext2FastIoRead;
|
||||
PtrFastIoDispatch->FastIoWrite = Ext2FastIoWrite;
|
||||
PtrFastIoDispatch->FastIoQueryBasicInfo = Ext2FastIoQueryBasicInfo;
|
||||
PtrFastIoDispatch->FastIoQueryStandardInfo = Ext2FastIoQueryStdInfo;
|
||||
PtrFastIoDispatch->FastIoLock = Ext2FastIoLock;
|
||||
PtrFastIoDispatch->FastIoUnlockSingle = Ext2FastIoUnlockSingle;
|
||||
PtrFastIoDispatch->FastIoUnlockAll = Ext2FastIoUnlockAll;
|
||||
PtrFastIoDispatch->FastIoUnlockAllByKey = Ext2FastIoUnlockAllByKey;
|
||||
PtrFastIoDispatch->AcquireFileForNtCreateSection = Ext2FastIoAcqCreateSec;
|
||||
PtrFastIoDispatch->ReleaseFileForNtCreateSection = Ext2FastIoRelCreateSec;
|
||||
|
||||
// the remaining are only valid under NT Version 4.0 and later
|
||||
#if(_WIN32_WINNT >= 0x0400)
|
||||
PtrFastIoDispatch->FastIoQueryNetworkOpenInfo = Ext2FastIoQueryNetInfo;
|
||||
PtrFastIoDispatch->AcquireForModWrite = Ext2FastIoAcqModWrite;
|
||||
PtrFastIoDispatch->ReleaseForModWrite = Ext2FastIoRelModWrite;
|
||||
PtrFastIoDispatch->AcquireForCcFlush = Ext2FastIoAcqCcFlush;
|
||||
PtrFastIoDispatch->ReleaseForCcFlush = Ext2FastIoRelCcFlush;
|
||||
|
||||
// MDL functionality
|
||||
PtrFastIoDispatch->MdlRead = Ext2FastIoMdlRead;
|
||||
PtrFastIoDispatch->MdlReadComplete = Ext2FastIoMdlReadComplete;
|
||||
PtrFastIoDispatch->PrepareMdlWrite = Ext2FastIoPrepareMdlWrite;
|
||||
PtrFastIoDispatch->MdlWriteComplete = Ext2FastIoMdlWriteComplete;
|
||||
|
||||
// although this FSD does not support compressed read/write functionality,
|
||||
// NTFS does, and if you design a FSD that can provide such functionality,
|
||||
// you should consider initializing the fast io entry points for reading
|
||||
// and/or writing compressed data ...
|
||||
#endif // (_WIN32_WINNT >= 0x0400)
|
||||
|
||||
|
||||
// last but not least, initialize the Cache Manager callback functions
|
||||
// which are used in CcInitializeCacheMap()
|
||||
Ext2GlobalData.CacheMgrCallBacks.AcquireForLazyWrite = Ext2AcqLazyWrite;
|
||||
Ext2GlobalData.CacheMgrCallBacks.ReleaseFromLazyWrite = Ext2RelLazyWrite;
|
||||
Ext2GlobalData.CacheMgrCallBacks.AcquireForReadAhead = Ext2AcqReadAhead;
|
||||
Ext2GlobalData.CacheMgrCallBacks.ReleaseFromReadAhead = Ext2RelReadAhead;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
VOID Ext2QueueHandlerThread(
|
||||
IN PVOID StartContext )
|
||||
{
|
||||
|
||||
DebugTrace(DEBUG_TRACE_MISC, "Ext2QueueHandlerThread!!!", 0);
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
KeWaitForSingleObject( &Ext2GlobalData.ThreadQueue.QueueEvent,
|
||||
Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL );
|
||||
|
||||
DebugTrace(DEBUG_TRACE_MISC, "Ext2QueueHandlerThread Alerted!!!", 0);
|
||||
|
||||
while( !IsListEmpty( &Ext2GlobalData.ThreadQueue.ThreadQueueListHead ) )
|
||||
{
|
||||
HANDLE ThreadHandle;
|
||||
PLIST_ENTRY PtrEntry = NULL;
|
||||
PtrExt2IrpContext PtrIrpContext = NULL;
|
||||
|
||||
|
||||
PtrEntry = ExInterlockedRemoveHeadList(
|
||||
&Ext2GlobalData.ThreadQueue.ThreadQueueListHead,
|
||||
&Ext2GlobalData.ThreadQueue.SpinLock );
|
||||
ASSERT( PtrEntry );
|
||||
PtrIrpContext = CONTAINING_RECORD( PtrEntry, Ext2IrpContext, ThreadQueueListEntry );
|
||||
|
||||
PsCreateSystemThread(
|
||||
&ThreadHandle, (ACCESS_MASK) 0L,
|
||||
NULL, NULL, NULL, Ext2CommonDispatch, PtrIrpContext );
|
||||
}
|
||||
}
|
||||
}
|
1757
reactos/drivers/filesystems/ext2/src/fastio.c
Normal file
1757
reactos/drivers/filesystems/ext2/src/fastio.c
Normal file
File diff suppressed because it is too large
Load diff
1125
reactos/drivers/filesystems/ext2/src/fileinfo.c
Normal file
1125
reactos/drivers/filesystems/ext2/src/fileinfo.c
Normal file
File diff suppressed because it is too large
Load diff
350
reactos/drivers/filesystems/ext2/src/flush.c
Normal file
350
reactos/drivers/filesystems/ext2/src/flush.c
Normal file
|
@ -0,0 +1,350 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* File: flush.c
|
||||
*
|
||||
* Module: Ext2 File System Driver (Kernel mode execution only)
|
||||
*
|
||||
* Description:
|
||||
* Contains code to handle the "Flush Buffers" dispatch entry point.
|
||||
*
|
||||
* Author: Manoj Paul Joseph
|
||||
*
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
#include "ext2fsd.h"
|
||||
|
||||
// define the file specific bug-check id
|
||||
#define EXT2_BUG_CHECK_ID EXT2_FILE_FLUSH
|
||||
|
||||
#define DEBUG_LEVEL (DEBUG_TRACE_FLUSH)
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2Flush()
|
||||
*
|
||||
* Description:
|
||||
* The I/O Manager will invoke this routine to handle a flush buffers
|
||||
* request
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
|
||||
* to be deferred to a worker thread context)
|
||||
*
|
||||
* Return Value: STATUS_SUCCESS/Error
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2Flush(
|
||||
PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
PIRP Irp) // I/O Request Packet
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
PtrExt2IrpContext PtrIrpContext = NULL;
|
||||
BOOLEAN AreWeTopLevel = FALSE;
|
||||
|
||||
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Flush IRP Received...", 0);
|
||||
|
||||
// Ext2BreakPoint();
|
||||
|
||||
FsRtlEnterFileSystem();
|
||||
ASSERT(DeviceObject);
|
||||
ASSERT(Irp);
|
||||
|
||||
// set the top level context
|
||||
AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
// get an IRP context structure and issue the request
|
||||
PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
|
||||
ASSERT(PtrIrpContext);
|
||||
|
||||
RC = Ext2CommonFlush(PtrIrpContext, Irp);
|
||||
|
||||
} except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
|
||||
|
||||
RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
|
||||
|
||||
Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
|
||||
}
|
||||
|
||||
if (AreWeTopLevel) {
|
||||
IoSetTopLevelIrp(NULL);
|
||||
}
|
||||
|
||||
FsRtlExitFileSystem();
|
||||
|
||||
return(RC);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2CommonFlush()
|
||||
*
|
||||
* Description:
|
||||
* The actual work is performed here. This routine may be invoked in one'
|
||||
* of the two possible contexts:
|
||||
* (a) in the context of a system worker thread
|
||||
* (b) in the context of the original caller
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: STATUS_SUCCESS/Error
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2CommonFlush(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp)
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
PIO_STACK_LOCATION PtrIoStackLocation = NULL;
|
||||
PFILE_OBJECT PtrFileObject = NULL;
|
||||
PtrExt2FCB PtrFCB = NULL;
|
||||
PtrExt2CCB PtrCCB = NULL;
|
||||
PtrExt2VCB PtrVCB = NULL;
|
||||
PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
|
||||
BOOLEAN AcquiredFCB = FALSE;
|
||||
BOOLEAN PostRequest = FALSE;
|
||||
BOOLEAN CanWait = TRUE;
|
||||
|
||||
try {
|
||||
// First, get a pointer to the current I/O stack location
|
||||
PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
|
||||
ASSERT(PtrIoStackLocation);
|
||||
|
||||
PtrFileObject = PtrIoStackLocation->FileObject;
|
||||
ASSERT(PtrFileObject);
|
||||
|
||||
// Get the FCB and CCB pointers
|
||||
PtrCCB = (PtrExt2CCB)(PtrFileObject->FsContext2);
|
||||
ASSERT(PtrCCB);
|
||||
PtrFCB = PtrCCB->PtrFCB;
|
||||
AssertFCB( PtrFCB );
|
||||
|
||||
/*ASSERT(PtrFCB);
|
||||
ASSERT(PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB );*/
|
||||
|
||||
PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
|
||||
|
||||
// Get some of the parameters supplied to us
|
||||
CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
|
||||
|
||||
// If we cannot wait, post the request immediately since a flush is inherently blocking/synchronous.
|
||||
if (!CanWait) {
|
||||
PostRequest = TRUE;
|
||||
try_return(RC);
|
||||
}
|
||||
|
||||
// Check the type of object passed-in. That will determine the course of
|
||||
// action we take.
|
||||
if ((PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) || (PtrFCB->FCBFlags & EXT2_FCB_ROOT_DIRECTORY)) {
|
||||
|
||||
if (PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) {
|
||||
PtrVCB = (PtrExt2VCB)(PtrFCB);
|
||||
} else {
|
||||
PtrVCB = PtrFCB->PtrVCB;
|
||||
}
|
||||
|
||||
// The caller wishes to flush all files for the mounted
|
||||
// logical volume. The flush volume routine below should simply
|
||||
// walk through all of the open file streams, acquire the
|
||||
// FCB resource, and request the flush operation from the Cache
|
||||
// Manager. Basically, the sequence of operations listed below
|
||||
// for a single file should be executed on all open files.
|
||||
|
||||
Ext2FlushLogicalVolume(PtrIrpContext, PtrIrp, PtrVCB);
|
||||
|
||||
try_return(RC);
|
||||
}
|
||||
|
||||
if (!(PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY))
|
||||
{
|
||||
// This is a regular file.
|
||||
ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource), TRUE);
|
||||
AcquiredFCB = TRUE;
|
||||
|
||||
// Request the Cache Manager to perform a flush operation.
|
||||
// Further, instruct the Cache Manager that we wish to flush the
|
||||
// entire file stream.
|
||||
Ext2FlushAFile(PtrReqdFCB, &(PtrIrp->IoStatus));
|
||||
RC = PtrIrp->IoStatus.Status;
|
||||
// All done. You may want to also flush the directory entry for the
|
||||
// file stream at this time.
|
||||
|
||||
// Some log-based FSD implementations may wish to flush their
|
||||
// log files at this time. Finally, you should update the time-stamp
|
||||
// values for the file stream appropriately. This would involve
|
||||
// obtaining the current time and modifying the appropriate directory
|
||||
// entry fields.
|
||||
}
|
||||
|
||||
try_exit:
|
||||
|
||||
if (AcquiredFCB)
|
||||
{
|
||||
Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [Flush]", 0);
|
||||
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [Flush]",
|
||||
PtrReqdFCB->MainResource.ActiveCount,
|
||||
PtrReqdFCB->MainResource.NumberOfExclusiveWaiters,
|
||||
PtrReqdFCB->MainResource.NumberOfSharedWaiters );
|
||||
|
||||
AcquiredFCB = FALSE;
|
||||
}
|
||||
|
||||
if (!PostRequest)
|
||||
{
|
||||
PIO_STACK_LOCATION PtrNextIoStackLocation = NULL;
|
||||
NTSTATUS RC1 = STATUS_SUCCESS;
|
||||
|
||||
// Send the request down at this point.
|
||||
// To do this, you must set the next IRP stack location, and
|
||||
// maybe set a completion routine.
|
||||
// Be careful about marking the IRP pending if the lower level
|
||||
// driver returned pending and you do have a completion routine!
|
||||
PtrNextIoStackLocation = IoGetNextIrpStackLocation(PtrIrp);
|
||||
*PtrNextIoStackLocation = *PtrIoStackLocation;
|
||||
|
||||
// Set the completion routine to "eat-up" any
|
||||
// STATUS_INVALID_DEVICE_REQUEST error code returned by the lower
|
||||
// level driver.
|
||||
IoSetCompletionRoutine(PtrIrp, Ext2FlushCompletion, NULL, TRUE, TRUE, TRUE);
|
||||
|
||||
/*
|
||||
* The exception handlers propably masked out the
|
||||
* fact that PtrVCB was never set.
|
||||
* -- Filip Navara, 18/08/2004
|
||||
*/
|
||||
PtrVCB = PtrFCB->PtrVCB;
|
||||
RC1 = IoCallDriver(PtrVCB->TargetDeviceObject, PtrIrp);
|
||||
|
||||
RC = ((RC1 == STATUS_INVALID_DEVICE_REQUEST) ? RC : RC1);
|
||||
}
|
||||
|
||||
} finally {
|
||||
if (PostRequest) {
|
||||
// Nothing to lock now.
|
||||
RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
|
||||
} else {
|
||||
// Release the IRP context at this time.
|
||||
Ext2ReleaseIrpContext(PtrIrpContext);
|
||||
}
|
||||
}
|
||||
|
||||
return(RC);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2FlushAFile()
|
||||
*
|
||||
* Description:
|
||||
* Tell the Cache Manager to perform a flush.
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: None
|
||||
*
|
||||
*************************************************************************/
|
||||
void Ext2FlushAFile(
|
||||
PtrExt2NTRequiredFCB PtrReqdFCB,
|
||||
PIO_STATUS_BLOCK PtrIoStatus)
|
||||
{
|
||||
CcFlushCache(&(PtrReqdFCB->SectionObject), NULL, 0, PtrIoStatus);
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2FlushLogicalVolume()
|
||||
*
|
||||
* Description:
|
||||
* Flush everything beginning at root directory.
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: None
|
||||
*
|
||||
*************************************************************************/
|
||||
void Ext2FlushLogicalVolume(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp,
|
||||
PtrExt2VCB PtrVCB)
|
||||
{
|
||||
BOOLEAN AcquiredVCB = FALSE;
|
||||
PtrExt2FCB PtrFCB = NULL;
|
||||
PLIST_ENTRY PtrNextFCB = NULL;
|
||||
|
||||
try {
|
||||
ExAcquireResourceExclusiveLite(&(PtrVCB->VCBResource), TRUE);
|
||||
|
||||
AcquiredVCB = TRUE;
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** VCB Acquired Ex [Flush] ", 0);
|
||||
|
||||
// Go through the list of FCB's. You would probably
|
||||
// flush all of the files. Then, you could flush the
|
||||
// directories that you may have have pinned into memory.
|
||||
|
||||
// NOTE: This function may also be invoked internally as part of
|
||||
// processing a shutdown request.
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (AcquiredVCB)
|
||||
{
|
||||
Ext2ReleaseResource(&(PtrVCB->VCBResource));
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** VCB Released [Flush]", 0);
|
||||
DebugTraceState( "VCB AC:0x%LX SW:0x%LX EX:0x%LX [Flush]",
|
||||
PtrVCB->VCBResource.ActiveCount,
|
||||
PtrVCB->VCBResource.NumberOfExclusiveWaiters,
|
||||
PtrVCB->VCBResource.NumberOfSharedWaiters );
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2FlushCompletion()
|
||||
*
|
||||
* Description:
|
||||
* Eat up any bad errors.
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: None
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2FlushCompletion(
|
||||
PDEVICE_OBJECT PtrDeviceObject,
|
||||
PIRP PtrIrp,
|
||||
PVOID Context)
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
|
||||
if (PtrIrp->PendingReturned) {
|
||||
IoMarkIrpPending(PtrIrp);
|
||||
}
|
||||
|
||||
if (PtrIrp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST) {
|
||||
// cannot do much here, can we?
|
||||
PtrIrp->IoStatus.Status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
944
reactos/drivers/filesystems/ext2/src/fsctrl.c
Normal file
944
reactos/drivers/filesystems/ext2/src/fsctrl.c
Normal file
|
@ -0,0 +1,944 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* File: fsctrl.c
|
||||
*
|
||||
* Module: Ext2 File System Driver (Kernel mode execution only)
|
||||
*
|
||||
* Description:
|
||||
* Contains code to handle the various File System Control calls.
|
||||
*
|
||||
* Author: Manoj Paul Joseph
|
||||
*
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include "ext2fsd.h"
|
||||
|
||||
|
||||
|
||||
// define the file specific bug-check id
|
||||
#define EXT2_BUG_CHECK_ID EXT2_FILE_FILE_CONTROL
|
||||
#define DEBUG_LEVEL (DEBUG_TRACE_FSCTRL)
|
||||
|
||||
|
||||
NTSTATUS
|
||||
Ext2MountVolume(
|
||||
IN PIRP Irp,
|
||||
IN PIO_STACK_LOCATION IrpSp );
|
||||
|
||||
NTSTATUS
|
||||
Ext2GetPartitionInfo(
|
||||
IN PDEVICE_OBJECT TargetDeviceObject,
|
||||
IN PPARTITION_INFORMATION PartitionInformation
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
Ext2GetDriveLayout(
|
||||
IN PDEVICE_OBJECT TargetDeviceObject,
|
||||
IN PDRIVE_LAYOUT_INFORMATION DriveLayoutInformation,
|
||||
IN int BufferSize
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
Ext2PerformVerifyDiskRead(
|
||||
IN PDEVICE_OBJECT TargetDeviceObject,
|
||||
IN PVOID Buffer,
|
||||
IN LONGLONG Lbo,
|
||||
IN ULONG NumberOfBytesToRead
|
||||
);
|
||||
|
||||
NTSTATUS Ext2UserFileSystemRequest(
|
||||
IN PIRP Irp,
|
||||
IN PIO_STACK_LOCATION IrpSp );
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2FileSystemControl
|
||||
*
|
||||
* Description:
|
||||
* The I/O Manager will invoke this routine to handle a
|
||||
* File System Control IRP
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* ???
|
||||
*
|
||||
* Arguments:
|
||||
*
|
||||
* DeviceObject - Supplies the volume device object where the
|
||||
* file exists
|
||||
*
|
||||
* Irp - Supplies the Irp being processed
|
||||
*
|
||||
*
|
||||
* Return Value:
|
||||
*
|
||||
* NTSTATUS - The FSD status for the IRP
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS
|
||||
Ext2FileSystemControl(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
)
|
||||
{
|
||||
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
|
||||
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "File System Control IRP Received...", 0);
|
||||
|
||||
// Ext2BreakPoint();
|
||||
|
||||
FsRtlEnterFileSystem();
|
||||
|
||||
ASSERT(DeviceObject);
|
||||
ASSERT(Irp);
|
||||
|
||||
//
|
||||
// Get a pointer to the current Irp stack location
|
||||
//
|
||||
IrpSp = IoGetCurrentIrpStackLocation( Irp );
|
||||
|
||||
|
||||
if( IrpSp->MinorFunction == IRP_MN_MOUNT_VOLUME )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MOUNT, "Mount Request Received...", 0);
|
||||
Status = Ext2MountVolume ( Irp, IrpSp );
|
||||
Ext2CompleteRequest( Irp, Status );
|
||||
}
|
||||
else if( IrpSp->MinorFunction == IRP_MN_USER_FS_REQUEST )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, "IRP_MN_USER_FS_REQUEST received...", 0);
|
||||
Status = Ext2UserFileSystemRequest( Irp, IrpSp );
|
||||
Ext2CompleteRequest( Irp, Status );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( IrpSp->MinorFunction == IRP_MN_VERIFY_VOLUME )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, "IRP_MN_VERIFY_VOLUME received...", 0);
|
||||
}
|
||||
else if( IrpSp->MinorFunction == IRP_MN_LOAD_FILE_SYSTEM )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, "IRP_MN_LOAD_FILE_SYSTEM received...", 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, "Unknown Minor IRP code received...", 0);
|
||||
}
|
||||
|
||||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
Ext2CompleteRequest( Irp, Status );
|
||||
}
|
||||
|
||||
FsRtlExitFileSystem();
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2MountVolume()
|
||||
*
|
||||
* Description:
|
||||
* This routine verifies and mounts the volume;
|
||||
* Called by FSCTRL IRP handler to attempt a
|
||||
* volume mount.
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
*
|
||||
* Arguments:
|
||||
*
|
||||
* Irp - Supplies the Irp being processed
|
||||
* IrpSp - Irp Stack Location pointer
|
||||
*
|
||||
* Return Value:
|
||||
*
|
||||
* NTSTATUS - The Mount status
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS
|
||||
Ext2MountVolume (
|
||||
IN PIRP Irp,
|
||||
IN PIO_STACK_LOCATION IrpSp )
|
||||
{
|
||||
|
||||
// Volume Parameter Block
|
||||
PVPB PtrVPB;
|
||||
|
||||
// The target device object
|
||||
PDEVICE_OBJECT TargetDeviceObject = NULL;
|
||||
|
||||
// The new volume device object (to be created if partition is Ext2)
|
||||
PDEVICE_OBJECT PtrVolumeDeviceObject = NULL;
|
||||
|
||||
// Return Status
|
||||
NTSTATUS Status = STATUS_UNRECOGNIZED_VOLUME;
|
||||
|
||||
// Number of bytes to read for Volume verification...
|
||||
unsigned long NumberOfBytesToRead = 0;
|
||||
|
||||
// Starting Offset for 'read'
|
||||
LONGLONG StartingOffset = 0;
|
||||
|
||||
// Boot Sector information...
|
||||
PPACKED_BOOT_SECTOR BootSector = NULL;
|
||||
|
||||
// Ext2 Super Block information...
|
||||
PEXT2_SUPER_BLOCK SuperBlock = NULL;
|
||||
|
||||
// Volume Control Block
|
||||
PtrExt2VCB PtrVCB = NULL;
|
||||
|
||||
// The File Object for the root directory
|
||||
PFILE_OBJECT PtrRootFileObject = NULL;
|
||||
|
||||
// Flag
|
||||
int WeClearedVerifyRequiredBit;
|
||||
|
||||
// Used by a for loop...
|
||||
unsigned int i;
|
||||
|
||||
//
|
||||
LARGE_INTEGER VolumeByteOffset;
|
||||
|
||||
unsigned long LogicalBlockSize = 0;
|
||||
|
||||
// Buffer Control Block
|
||||
PBCB PtrBCB = NULL;
|
||||
|
||||
// Cache Buffer - used for pinned access of volume...
|
||||
PVOID PtrCacheBuffer = NULL;
|
||||
|
||||
PEXT2_GROUP_DESCRIPTOR PtrGroupDescriptor = NULL;
|
||||
|
||||
PEXT2_INODE PtrInode = NULL;
|
||||
|
||||
// Inititalising variables
|
||||
|
||||
PtrVPB = IrpSp->Parameters.MountVolume.Vpb;
|
||||
TargetDeviceObject = IrpSp->Parameters.MountVolume.DeviceObject;
|
||||
|
||||
try
|
||||
{
|
||||
//
|
||||
// 1. Reading in Volume meta data
|
||||
//
|
||||
|
||||
// Temporarily clear the DO_VERIFY_VOLUME Flag
|
||||
WeClearedVerifyRequiredBit = 0;
|
||||
if ( Ext2IsFlagOn( PtrVPB->RealDevice->Flags, DO_VERIFY_VOLUME ) )
|
||||
{
|
||||
Ext2ClearFlag( PtrVPB->RealDevice->Flags, DO_VERIFY_VOLUME );
|
||||
WeClearedVerifyRequiredBit = 1;
|
||||
}
|
||||
|
||||
// Allocating memory for reading in Boot Sector...
|
||||
NumberOfBytesToRead = Ext2Align( sizeof( EXT2_SUPER_BLOCK ), TargetDeviceObject->SectorSize );
|
||||
BootSector = Ext2AllocatePool( PagedPool, NumberOfBytesToRead );
|
||||
RtlZeroMemory( BootSector, NumberOfBytesToRead );
|
||||
|
||||
// Reading in Boot Sector
|
||||
StartingOffset = 0L;
|
||||
Ext2PerformVerifyDiskRead ( TargetDeviceObject,
|
||||
BootSector, StartingOffset, NumberOfBytesToRead );
|
||||
|
||||
// Allocating memory for reading in Super Block...
|
||||
|
||||
SuperBlock = Ext2AllocatePool( PagedPool, NumberOfBytesToRead );
|
||||
RtlZeroMemory( SuperBlock, NumberOfBytesToRead );
|
||||
StartingOffset = 1024;
|
||||
|
||||
// Reading in the Super Block...
|
||||
Ext2PerformVerifyDiskRead ( TargetDeviceObject,
|
||||
SuperBlock, StartingOffset, NumberOfBytesToRead );
|
||||
|
||||
// Resetting the DO_VERIFY_VOLUME Flag
|
||||
if( WeClearedVerifyRequiredBit )
|
||||
{
|
||||
PtrVPB->RealDevice->Flags |= DO_VERIFY_VOLUME;
|
||||
}
|
||||
|
||||
// Verifying the Super Block..
|
||||
if( SuperBlock->s_magic == EXT2_SUPER_MAGIC )
|
||||
{
|
||||
//
|
||||
// Found a valid super block.
|
||||
// No more tests for now.
|
||||
// Assuming that this is an ext2 partition...
|
||||
// Going ahead with mount.
|
||||
//
|
||||
DebugTrace(DEBUG_TRACE_MOUNT, "Valid Ext2 partition detected\nMounting %s...", SuperBlock->s_volume_name);
|
||||
//
|
||||
// 2. Creating a volume device object
|
||||
//
|
||||
if (!NT_SUCCESS( IoCreateDevice(
|
||||
Ext2GlobalData.Ext2DriverObject, // (This) Driver object
|
||||
Ext2QuadAlign( sizeof(Ext2VCB) ), // Device Extension
|
||||
NULL, // Device Name - no name ;)
|
||||
FILE_DEVICE_DISK_FILE_SYSTEM, // Disk File System
|
||||
0, // DeviceCharacteristics
|
||||
FALSE, // Not an exclusive device
|
||||
(PDEVICE_OBJECT *)&PtrVolumeDeviceObject)) // The Volume Device Object
|
||||
)
|
||||
{
|
||||
try_return( Status );
|
||||
}
|
||||
|
||||
//
|
||||
// Our alignment requirement is the larger of the processor alignment requirement
|
||||
// already in the volume device object and that in the TargetDeviceObject
|
||||
//
|
||||
|
||||
if (TargetDeviceObject->AlignmentRequirement > PtrVolumeDeviceObject->AlignmentRequirement)
|
||||
{
|
||||
PtrVolumeDeviceObject->AlignmentRequirement = TargetDeviceObject->AlignmentRequirement;
|
||||
}
|
||||
|
||||
//
|
||||
// Clearing the Device Initialising Flag
|
||||
//
|
||||
Ext2ClearFlag( PtrVolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING);
|
||||
|
||||
|
||||
//
|
||||
// Setting the Stack Size for the newly created Volume Device Object
|
||||
//
|
||||
PtrVolumeDeviceObject->StackSize = (CCHAR)(TargetDeviceObject->StackSize + 1);
|
||||
|
||||
|
||||
//
|
||||
// 3. Creating the link between Target Device Object
|
||||
// and the Volume Device Object via the Volume Parameter Block
|
||||
//
|
||||
PtrVPB->DeviceObject = PtrVolumeDeviceObject;
|
||||
|
||||
// Remembring the Volume parameters in the VPB bock
|
||||
for( i = 0; i < 16 ; i++ )
|
||||
{
|
||||
PtrVPB->VolumeLabel[i] = SuperBlock->s_volume_name[i];
|
||||
if( SuperBlock->s_volume_name[i] == 0 )
|
||||
break;
|
||||
}
|
||||
PtrVPB->VolumeLabelLength = i * 2;
|
||||
PtrVPB->SerialNumber = ((ULONG*)SuperBlock->s_uuid)[0];
|
||||
|
||||
//
|
||||
// 4. Initialise the Volume Comtrol Block
|
||||
//
|
||||
{
|
||||
LARGE_INTEGER AllocationSize;
|
||||
|
||||
AllocationSize .QuadPart =
|
||||
( EXT2_MIN_BLOCK_SIZE << SuperBlock->s_log_block_size ) *
|
||||
SuperBlock->s_blocks_count;
|
||||
|
||||
Ext2InitializeVCB(
|
||||
PtrVolumeDeviceObject,
|
||||
TargetDeviceObject,
|
||||
PtrVPB,
|
||||
&AllocationSize);
|
||||
PtrVCB = (PtrExt2VCB)(PtrVolumeDeviceObject->DeviceExtension);
|
||||
ASSERT( PtrVCB );
|
||||
}
|
||||
|
||||
PtrVCB->InodesCount = SuperBlock->s_inodes_count;
|
||||
PtrVCB->BlocksCount = SuperBlock->s_blocks_count;
|
||||
PtrVCB->ReservedBlocksCount = SuperBlock->s_r_blocks_count;
|
||||
PtrVCB->FreeBlocksCount = SuperBlock->s_free_blocks_count;
|
||||
PtrVCB->FreeInodesCount = SuperBlock->s_free_inodes_count;
|
||||
PtrVCB->LogBlockSize = SuperBlock->s_log_block_size;
|
||||
PtrVCB->InodesPerGroup = SuperBlock->s_inodes_per_group;
|
||||
PtrVCB->BlocksPerGroup = SuperBlock->s_blocks_per_group;
|
||||
PtrVCB->NoOfGroups = ( SuperBlock->s_blocks_count - SuperBlock->s_first_data_block
|
||||
+ SuperBlock->s_blocks_per_group - 1 )
|
||||
/ SuperBlock->s_blocks_per_group;
|
||||
|
||||
PtrVCB->PtrGroupDescriptors = Ext2AllocatePool( NonPagedPool, sizeof( Ext2GroupDescriptors ) * PtrVCB->NoOfGroups );
|
||||
|
||||
RtlZeroMemory( PtrVCB->PtrGroupDescriptors , sizeof( Ext2GroupDescriptors ) * PtrVCB->NoOfGroups );
|
||||
|
||||
//
|
||||
// Attempting to Read in some matadata from the Cache...
|
||||
// using pin access...
|
||||
//
|
||||
LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
|
||||
|
||||
//
|
||||
// Reading Group Descriptors...
|
||||
//
|
||||
if( PtrVCB->LogBlockSize )
|
||||
{
|
||||
// First block contains the descriptors...
|
||||
VolumeByteOffset.QuadPart = LogicalBlockSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Second block contains the descriptors...
|
||||
VolumeByteOffset.QuadPart = LogicalBlockSize * 2;
|
||||
}
|
||||
|
||||
NumberOfBytesToRead = PtrVCB->NoOfGroups * sizeof( struct ext2_group_desc );
|
||||
NumberOfBytesToRead = Ext2Align( NumberOfBytesToRead, LogicalBlockSize );
|
||||
|
||||
if (!CcMapData( PtrVCB->PtrStreamFileObject,
|
||||
&VolumeByteOffset,
|
||||
NumberOfBytesToRead,
|
||||
TRUE,
|
||||
&PtrBCB,
|
||||
&PtrCacheBuffer ))
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0);
|
||||
try_return( Status = STATUS_INSUFFICIENT_RESOURCES );
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Saving up Often Used Group Descriptor Information in the VCB...
|
||||
//
|
||||
unsigned int DescIndex ;
|
||||
|
||||
DebugTrace(DEBUG_TRACE_MISC, "Cache hit while reading in volume meta data", 0);
|
||||
PtrGroupDescriptor = (PEXT2_GROUP_DESCRIPTOR )PtrCacheBuffer;
|
||||
for( DescIndex = 0; DescIndex < PtrVCB->NoOfGroups; DescIndex++ )
|
||||
{
|
||||
PtrVCB->PtrGroupDescriptors[ DescIndex ].InodeTablesBlock
|
||||
= PtrGroupDescriptor[ DescIndex ].bg_inode_table;
|
||||
|
||||
PtrVCB->PtrGroupDescriptors[ DescIndex ].InodeBitmapBlock
|
||||
= PtrGroupDescriptor[ DescIndex ].bg_inode_bitmap
|
||||
;
|
||||
PtrVCB->PtrGroupDescriptors[ DescIndex ].BlockBitmapBlock
|
||||
= PtrGroupDescriptor[ DescIndex ].bg_block_bitmap
|
||||
;
|
||||
PtrVCB->PtrGroupDescriptors[ DescIndex ].FreeBlocksCount
|
||||
= PtrGroupDescriptor[ DescIndex ].bg_free_blocks_count;
|
||||
|
||||
PtrVCB->PtrGroupDescriptors[ DescIndex ].FreeInodesCount
|
||||
= PtrGroupDescriptor[ DescIndex ].bg_free_inodes_count;
|
||||
}
|
||||
CcUnpinData( PtrBCB );
|
||||
PtrBCB = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// 5. Creating a Root Directory FCB
|
||||
//
|
||||
PtrRootFileObject = IoCreateStreamFileObject(NULL, TargetDeviceObject );
|
||||
if( !PtrRootFileObject )
|
||||
{
|
||||
try_return( Status );
|
||||
}
|
||||
//
|
||||
// Associate the file stream with the Volume parameter block...
|
||||
// I do it now
|
||||
//
|
||||
PtrRootFileObject->Vpb = PtrVCB->PtrVPB;
|
||||
|
||||
PtrRootFileObject->ReadAccess = TRUE;
|
||||
PtrRootFileObject->WriteAccess = TRUE;
|
||||
|
||||
{
|
||||
PtrExt2ObjectName PtrObjectName;
|
||||
LARGE_INTEGER ZeroSize;
|
||||
|
||||
PtrObjectName = Ext2AllocateObjectName();
|
||||
RtlInitUnicodeString( &PtrObjectName->ObjectName, L"\\" );
|
||||
Ext2CopyWideCharToUnicodeString( &PtrObjectName->ObjectName, L"\\" );
|
||||
|
||||
|
||||
ZeroSize.QuadPart = 0;
|
||||
if ( !NT_SUCCESS( Ext2CreateNewFCB(
|
||||
&PtrVCB->PtrRootDirectoryFCB, // Root FCB
|
||||
ZeroSize, // AllocationSize,
|
||||
ZeroSize, // EndOfFile,
|
||||
PtrRootFileObject, // The Root Dircetory File Object
|
||||
PtrVCB,
|
||||
PtrObjectName ) ) )
|
||||
{
|
||||
try_return( Status );
|
||||
}
|
||||
|
||||
|
||||
PtrVCB->PtrRootDirectoryFCB->FCBFlags |= EXT2_FCB_DIRECTORY | EXT2_FCB_ROOT_DIRECTORY;
|
||||
|
||||
|
||||
}
|
||||
|
||||
PtrVCB->PtrRootDirectoryFCB->DcbFcb.Dcb.PtrDirFileObject = PtrRootFileObject;
|
||||
PtrVCB->PtrRootDirectoryFCB->INodeNo = EXT2_ROOT_INO;
|
||||
PtrRootFileObject->SectionObjectPointer = &(PtrVCB->PtrRootDirectoryFCB->NTRequiredFCB.SectionObject);
|
||||
RtlInitUnicodeString( &PtrRootFileObject->FileName, L"\\" );
|
||||
|
||||
Ext2InitializeFCBInodeInfo( PtrVCB->PtrRootDirectoryFCB );
|
||||
|
||||
//
|
||||
// Initiating caching for root directory...
|
||||
//
|
||||
|
||||
CcInitializeCacheMap(PtrRootFileObject,
|
||||
(PCC_FILE_SIZES)(&(PtrVCB->PtrRootDirectoryFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize)),
|
||||
TRUE, // We will utilize pin access for directories
|
||||
&(Ext2GlobalData.CacheMgrCallBacks), // callbacks
|
||||
PtrVCB->PtrRootDirectoryFCB ); // The context used in callbacks
|
||||
|
||||
|
||||
//
|
||||
// 6. Update the VCB Flags
|
||||
//
|
||||
PtrVCB->VCBFlags |= EXT2_VCB_FLAGS_VOLUME_MOUNTED ; // | EXT2_VCB_FLAGS_VOLUME_READ_ONLY;
|
||||
|
||||
|
||||
//
|
||||
// 7. Mount Success
|
||||
//
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
{
|
||||
//
|
||||
// This block is for testing....
|
||||
// To be removed...
|
||||
|
||||
/*
|
||||
EXT2_INODE Inode ;
|
||||
Ext2ReadInode( PtrVCB, 100, &Inode );
|
||||
DebugTrace( DEBUG_TRACE_MISC, "Inode size= %lX [FS Ctrl]", Inode.i_size );
|
||||
Ext2DeallocInode( NULL, PtrVCB, 0xfb6 );
|
||||
*/
|
||||
}
|
||||
|
||||
// ObDereferenceObject( TargetDeviceObject );
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MOUNT, "Failing mount. Partition not Ext2...", 0);
|
||||
}
|
||||
|
||||
try_exit: NOTHING;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Freeing Allocated Memory...
|
||||
if( SuperBlock != NULL )
|
||||
{
|
||||
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", SuperBlock );
|
||||
ExFreePool( SuperBlock );
|
||||
}
|
||||
if( BootSector != NULL )
|
||||
{
|
||||
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", BootSector);
|
||||
ExFreePool( BootSector );
|
||||
}
|
||||
|
||||
// start unwinding if we were unsuccessful
|
||||
if (!NT_SUCCESS( Status ))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2MountVolume()
|
||||
*
|
||||
* Description:
|
||||
* This routine is used for querying the partition information.
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Arguments:
|
||||
*
|
||||
* TargetDeviceObject - The target of the query
|
||||
* PartitionInformation - Receives the result of the query
|
||||
*
|
||||
* Return Value:
|
||||
*
|
||||
* NTSTATUS - The return status for the operation
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS
|
||||
Ext2GetPartitionInfo (
|
||||
IN PDEVICE_OBJECT TargetDeviceObject,
|
||||
IN PPARTITION_INFORMATION PartitionInformation
|
||||
)
|
||||
{
|
||||
PIRP Irp;
|
||||
KEVENT *PtrEvent = NULL;
|
||||
NTSTATUS Status;
|
||||
IO_STATUS_BLOCK Iosb;
|
||||
|
||||
//
|
||||
// Query the partition table
|
||||
//
|
||||
PtrEvent = ( KEVENT * )Ext2AllocatePool( NonPagedPool, Ext2QuadAlign( sizeof( KEVENT ) ) );
|
||||
|
||||
|
||||
|
||||
|
||||
KeInitializeEvent( PtrEvent, NotificationEvent, FALSE );
|
||||
|
||||
Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_GET_PARTITION_INFO,
|
||||
TargetDeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
PartitionInformation,
|
||||
sizeof(PARTITION_INFORMATION),
|
||||
FALSE,
|
||||
PtrEvent,
|
||||
&Iosb );
|
||||
|
||||
if ( Irp == NULL )
|
||||
{
|
||||
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", PtrEvent);
|
||||
ExFreePool( PtrEvent );
|
||||
return 0;
|
||||
}
|
||||
|
||||
Status = IoCallDriver( TargetDeviceObject, Irp );
|
||||
|
||||
if ( Status == STATUS_PENDING ) {
|
||||
|
||||
(VOID) KeWaitForSingleObject( PtrEvent,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
(PLARGE_INTEGER)NULL );
|
||||
|
||||
Status = Iosb.Status;
|
||||
}
|
||||
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", PtrEvent);
|
||||
ExFreePool( PtrEvent );
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2MountVolume()
|
||||
*
|
||||
* Description:
|
||||
* This routine is used for querying the Drive Layout Information.
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Arguments:
|
||||
*
|
||||
* TargetDeviceObject - The target of the query
|
||||
* PartitionInformation - Receives the result of the query
|
||||
*
|
||||
* Return Value:
|
||||
*
|
||||
* NTSTATUS - The return status for the operation
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2GetDriveLayout (
|
||||
IN PDEVICE_OBJECT TargetDeviceObject,
|
||||
IN PDRIVE_LAYOUT_INFORMATION DriveLayoutInformation,
|
||||
IN int BufferSize
|
||||
)
|
||||
{
|
||||
PIRP Irp;
|
||||
KEVENT *PtrEvent = NULL;
|
||||
NTSTATUS Status;
|
||||
IO_STATUS_BLOCK Iosb;
|
||||
|
||||
//
|
||||
// Query the partition table
|
||||
//
|
||||
PtrEvent = ( KEVENT * )Ext2AllocatePool( NonPagedPool, Ext2QuadAlign( sizeof( KEVENT ) ) );
|
||||
KeInitializeEvent( PtrEvent, NotificationEvent, FALSE );
|
||||
Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_GET_DRIVE_LAYOUT,
|
||||
TargetDeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
DriveLayoutInformation,
|
||||
BufferSize,
|
||||
FALSE,
|
||||
PtrEvent,
|
||||
&Iosb );
|
||||
|
||||
if ( Irp == NULL )
|
||||
{
|
||||
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", PtrEvent);
|
||||
ExFreePool( PtrEvent );
|
||||
return 0;
|
||||
}
|
||||
|
||||
Status = IoCallDriver( TargetDeviceObject, Irp );
|
||||
|
||||
if ( Status == STATUS_PENDING ) {
|
||||
|
||||
(VOID) KeWaitForSingleObject( PtrEvent,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
(PLARGE_INTEGER)NULL );
|
||||
|
||||
Status = Iosb.Status;
|
||||
}
|
||||
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", PtrEvent);
|
||||
ExFreePool( PtrEvent );
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2MountVolume()
|
||||
*
|
||||
* Description:
|
||||
* This routine is used for performing a verify read...
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Arguments:
|
||||
* TargetDeviceObject - The target of the query
|
||||
* PartitionInformation - Receives the result of the query
|
||||
*
|
||||
* Return Value:
|
||||
* NTSTATUS - The return status for the operation
|
||||
*
|
||||
*************************************************************************/
|
||||
BOOLEAN Ext2PerformVerifyDiskRead(
|
||||
IN PDEVICE_OBJECT TargetDeviceObject,
|
||||
IN PVOID Buffer,
|
||||
IN LONGLONG Lbo,
|
||||
IN ULONG NumberOfBytesToRead )
|
||||
{
|
||||
KEVENT Event;
|
||||
PIRP Irp;
|
||||
LARGE_INTEGER ByteOffset;
|
||||
NTSTATUS Status;
|
||||
IO_STATUS_BLOCK Iosb;
|
||||
|
||||
//
|
||||
// Initialize the event we're going to use
|
||||
//
|
||||
KeInitializeEvent( &Event, NotificationEvent, FALSE );
|
||||
|
||||
//
|
||||
// Build the irp for the operation
|
||||
//
|
||||
ByteOffset.QuadPart = Lbo;
|
||||
Irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ,
|
||||
TargetDeviceObject,
|
||||
Buffer,
|
||||
NumberOfBytesToRead,
|
||||
&ByteOffset,
|
||||
&Event,
|
||||
&Iosb );
|
||||
|
||||
if ( Irp == NULL )
|
||||
{
|
||||
Status = FALSE;
|
||||
}
|
||||
|
||||
Ext2SetFlag( IoGetNextIrpStackLocation( Irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME );
|
||||
|
||||
//
|
||||
// Call the device to do the read and wait for it to finish.
|
||||
//
|
||||
Status = IoCallDriver( TargetDeviceObject, Irp );
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
(VOID)KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL );
|
||||
Status = Iosb.Status;
|
||||
}
|
||||
|
||||
ASSERT(Status != STATUS_VERIFY_REQUIRED);
|
||||
|
||||
//
|
||||
// Special case this error code because this probably means we used
|
||||
// the wrong sector size and we want to reject STATUS_WRONG_VOLUME.
|
||||
//
|
||||
|
||||
if (Status == STATUS_INVALID_PARAMETER)
|
||||
{
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// If it doesn't succeed then either return or raise the error.
|
||||
//
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// And return to our caller
|
||||
//
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2UserFileSystemRequest()
|
||||
*
|
||||
* Description:
|
||||
* This routine handles User File System Requests
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
*
|
||||
* Arguments:
|
||||
*
|
||||
* Irp - Supplies the Irp being processed
|
||||
* IrpSp - Irp Stack Location pointer
|
||||
*
|
||||
* Return Value: NT_STATUS
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2UserFileSystemRequest (
|
||||
IN PIRP Irp,
|
||||
IN PIO_STACK_LOCATION IrpSp )
|
||||
{
|
||||
NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
ULONG FsControlCode;
|
||||
|
||||
IrpSp = IoGetCurrentIrpStackLocation( Irp );
|
||||
|
||||
try
|
||||
{
|
||||
#ifdef _GNU_NTIFS_
|
||||
FsControlCode = ((PEXTENDED_IO_STACK_LOCATION)IrpSp)->Parameters.FileSystemControl.FsControlCode;
|
||||
#else
|
||||
FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
|
||||
#endif
|
||||
|
||||
switch ( FsControlCode )
|
||||
{
|
||||
|
||||
case FSCTL_REQUEST_OPLOCK_LEVEL_1:
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, "FSCTL_REQUEST_OPLOCK_LEVEL_1", 0);
|
||||
break;
|
||||
case FSCTL_REQUEST_OPLOCK_LEVEL_2:
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL ", 0);
|
||||
break;
|
||||
case FSCTL_REQUEST_BATCH_OPLOCK:
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_REQUEST_OPLOCK_LEVEL_2 ", 0);
|
||||
break;
|
||||
case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE:
|
||||
DebugTrace(DEBUG_TRACE_MISC, " FSCTL_OPLOCK_BREAK_ACKNOWLEDGE ", 0);
|
||||
break;
|
||||
case FSCTL_OPBATCH_ACK_CLOSE_PENDING:
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_OPBATCH_ACK_CLOSE_PENDING ", 0);
|
||||
break;
|
||||
case FSCTL_OPLOCK_BREAK_NOTIFY:
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_OPLOCK_BREAK_NOTIFY ", 0);
|
||||
break;
|
||||
case FSCTL_OPLOCK_BREAK_ACK_NO_2:
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_OPLOCK_BREAK_ACK_NO_2 ", 0);
|
||||
break;
|
||||
case FSCTL_LOCK_VOLUME:
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_LOCK_VOLUME ", 0);
|
||||
break;
|
||||
case FSCTL_UNLOCK_VOLUME:
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_UNLOCK_VOLUME ", 0);
|
||||
break;
|
||||
case FSCTL_DISMOUNT_VOLUME:
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_DISMOUNT_VOLUME ", 0);
|
||||
break;
|
||||
case FSCTL_MARK_VOLUME_DIRTY:
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_MARK_VOLUME_DIRTY ", 0);
|
||||
break;
|
||||
case FSCTL_IS_VOLUME_DIRTY:
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_IS_VOLUME_DIRTY ", 0);
|
||||
break;
|
||||
case FSCTL_IS_VOLUME_MOUNTED:
|
||||
Status = Ext2VerifyVolume(Irp, IrpSp );
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_IS_VOLUME_MOUNTED ", 0);
|
||||
break;
|
||||
case FSCTL_IS_PATHNAME_VALID:
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_IS_PATHNAME_VALID ", 0);
|
||||
break;
|
||||
case FSCTL_QUERY_RETRIEVAL_POINTERS:
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_QUERY_RETRIEVAL_POINTERS ", 0);
|
||||
break;
|
||||
case FSCTL_QUERY_FAT_BPB:
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_QUERY_FAT_BPB ", 0);
|
||||
break;
|
||||
case FSCTL_FILESYSTEM_GET_STATISTICS:
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_FILESYSTEM_GET_STATISTICS ", 0);
|
||||
break;
|
||||
case FSCTL_GET_VOLUME_BITMAP:
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_GET_VOLUME_BITMAP ", 0);
|
||||
break;
|
||||
case FSCTL_GET_RETRIEVAL_POINTERS:
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_GET_RETRIEVAL_POINTERS ", 0);
|
||||
break;
|
||||
case FSCTL_MOVE_FILE:
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_MOVE_FILE ", 0);
|
||||
break;
|
||||
case FSCTL_ALLOW_EXTENDED_DASD_IO:
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_ALLOW_EXTENDED_DASD_IO ", 0);
|
||||
break;
|
||||
default :
|
||||
DebugTrace(DEBUG_TRACE_FSCTRL, "Unknown FSCTRL !!!", 0);
|
||||
|
||||
}
|
||||
|
||||
try_exit: NOTHING;
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NTSTATUS Ext2VerifyVolume (
|
||||
IN PIRP Irp,
|
||||
IN PIO_STACK_LOCATION IrpSp )
|
||||
{
|
||||
|
||||
PVPB PtrVPB;
|
||||
|
||||
PtrVPB = IrpSp->Parameters.VerifyVolume.Vpb;
|
||||
if( IrpSp->FileObject )
|
||||
{
|
||||
PtrVPB = IrpSp->FileObject->Vpb;
|
||||
}
|
||||
if( !PtrVPB )
|
||||
{
|
||||
PtrVPB = IrpSp->Parameters.VerifyVolume.Vpb;
|
||||
}
|
||||
|
||||
if( !PtrVPB )
|
||||
{
|
||||
return STATUS_WRONG_VOLUME;
|
||||
}
|
||||
|
||||
|
||||
if ( Ext2IsFlagOn( PtrVPB->RealDevice->Flags, DO_VERIFY_VOLUME ) )
|
||||
{
|
||||
//
|
||||
// Not doing a verify!
|
||||
// Just acting as if everyting is fine!
|
||||
// THis should do for now
|
||||
//
|
||||
Ext2ClearFlag( PtrVPB->RealDevice->Flags, DO_VERIFY_VOLUME );
|
||||
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
543
reactos/drivers/filesystems/ext2/src/io.c
Normal file
543
reactos/drivers/filesystems/ext2/src/io.c
Normal file
|
@ -0,0 +1,543 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* File: io.c
|
||||
*
|
||||
* Module: Ext2 File System Driver (Kernel mode execution only)
|
||||
*
|
||||
* Description:
|
||||
* This file contains low level disk io routines.
|
||||
*
|
||||
* Author: Manoj Paul Joseph
|
||||
*
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
#include "ext2fsd.h"
|
||||
|
||||
// define the file specific bug-check id
|
||||
#define EXT2_BUG_CHECK_ID EXT2_FILE_IO
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2PassDownMultiReadWriteIRP()
|
||||
*
|
||||
* Description:
|
||||
* pass down multiple read IRPs as Associated IRPs
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* ?
|
||||
*
|
||||
* Return Value: STATUS_SUCCESS / STATUS_PENDING / Error
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2PassDownMultiReadWriteIRP(
|
||||
PEXT2_IO_RUN PtrIoRuns,
|
||||
UINT Count,
|
||||
ULONG TotalReadWriteLength,
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PtrExt2FCB PtrFCB,
|
||||
BOOLEAN SynchronousIo)
|
||||
{
|
||||
PIRP PtrMasterIrp;
|
||||
PIRP PtrAssociatedIrp;
|
||||
PIO_STACK_LOCATION PtrIrpSp;
|
||||
PMDL PtrMdl;
|
||||
PtrExt2VCB PtrVCB;
|
||||
UINT i;
|
||||
ULONG BufferOffset;
|
||||
PEXT2_IO_CONTEXT PtrIoContext = NULL;
|
||||
PKEVENT PtrSyncEvent = NULL;
|
||||
ULONG LogicalBlockSize;
|
||||
ULONG ReadWriteLength;
|
||||
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
|
||||
PtrVCB = PtrFCB->PtrVCB;
|
||||
PtrMasterIrp = PtrIrpContext->Irp;
|
||||
LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
|
||||
|
||||
try
|
||||
{
|
||||
if( !SynchronousIo )
|
||||
{
|
||||
IoMarkIrpPending( PtrIrpContext->Irp );
|
||||
// We will be returning STATUS_PENDING...
|
||||
}
|
||||
|
||||
if( !PtrMasterIrp->MdlAddress )
|
||||
{
|
||||
Ext2LockCallersBuffer( PtrMasterIrp, TRUE, TotalReadWriteLength );
|
||||
}
|
||||
|
||||
if( SynchronousIo )
|
||||
{
|
||||
PtrSyncEvent = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( sizeof(KEVENT) ) );
|
||||
if ( !PtrSyncEvent )
|
||||
{
|
||||
RC = STATUS_INSUFFICIENT_RESOURCES;
|
||||
try_return ( RC );
|
||||
}
|
||||
KeInitializeEvent( PtrSyncEvent, SynchronizationEvent, FALSE );
|
||||
}
|
||||
//
|
||||
// Allocate and initialize a completion context
|
||||
//
|
||||
PtrIoContext = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( sizeof(EXT2_IO_CONTEXT) ) );
|
||||
if ( !PtrIoContext )
|
||||
{
|
||||
RC = STATUS_INSUFFICIENT_RESOURCES;
|
||||
try_return ( RC );
|
||||
}
|
||||
|
||||
RtlZeroMemory( PtrIoContext, sizeof(EXT2_IO_CONTEXT) );
|
||||
PtrIoContext->Count = Count;
|
||||
PtrIoContext->NodeIdentifier.NodeType = EXT2_NODE_TYPE_IO_CONTEXT;
|
||||
PtrIoContext->NodeIdentifier.NodeSize = sizeof( EXT2_IO_CONTEXT );
|
||||
PtrIoContext->PtrMasterIrp = PtrMasterIrp;
|
||||
PtrIoContext->PtrSyncEvent = PtrSyncEvent;
|
||||
PtrIoContext->ReadWriteLength = TotalReadWriteLength;
|
||||
|
||||
|
||||
|
||||
for( ReadWriteLength = 0, BufferOffset = 0, i = 0; i < Count; i++, BufferOffset += ReadWriteLength )
|
||||
{
|
||||
|
||||
ReadWriteLength = PtrIoRuns[ i].EndOffset - PtrIoRuns[ i].StartOffset;
|
||||
|
||||
//
|
||||
// Allocating an Associated IRP...
|
||||
//
|
||||
PtrAssociatedIrp = IoMakeAssociatedIrp( PtrMasterIrp,
|
||||
(CCHAR) (PtrVCB->TargetDeviceObject->StackSize + 1 ) );
|
||||
PtrIoRuns[ i].PtrAssociatedIrp = PtrAssociatedIrp;
|
||||
ASSERT ( PtrAssociatedIrp );
|
||||
PtrMasterIrp->AssociatedIrp.IrpCount ++;
|
||||
|
||||
//
|
||||
// Allocating a Memory Descriptor List...
|
||||
//
|
||||
PtrMdl = IoAllocateMdl( (PCHAR) PtrMasterIrp->UserBuffer + BufferOffset, // Virtual Address
|
||||
ReadWriteLength, FALSE, FALSE, PtrAssociatedIrp );
|
||||
|
||||
//
|
||||
// and building a partial MDL...
|
||||
//
|
||||
IoBuildPartialMdl( PtrMasterIrp->MdlAddress,
|
||||
PtrMdl, (PCHAR)PtrMasterIrp->UserBuffer + BufferOffset, ReadWriteLength );
|
||||
|
||||
//
|
||||
// Create an Irp stack location for ourselves...
|
||||
//
|
||||
IoSetNextIrpStackLocation( PtrAssociatedIrp );
|
||||
PtrIrpSp = IoGetCurrentIrpStackLocation( PtrAssociatedIrp );
|
||||
|
||||
//
|
||||
// Setup the Stack location to describe our read.
|
||||
//
|
||||
PtrIrpSp->MajorFunction = PtrIrpContext->MajorFunction;
|
||||
if( PtrIrpContext->MajorFunction == IRP_MJ_READ )
|
||||
{
|
||||
PtrIrpSp->Parameters.Read.Length = ReadWriteLength;
|
||||
PtrIrpSp->Parameters.Read.ByteOffset.QuadPart =
|
||||
PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
|
||||
}
|
||||
else if( PtrIrpContext->MajorFunction == IRP_MJ_WRITE )
|
||||
{
|
||||
PtrIrpSp->Parameters.Write.Length = ReadWriteLength;
|
||||
PtrIrpSp->Parameters.Write.ByteOffset.QuadPart =
|
||||
PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
|
||||
}
|
||||
|
||||
// PtrIrpSp->Parameters.Read.Length = ReadWriteLength;
|
||||
// PtrIrpSp->Parameters.Read.ByteOffset.QuadPart = PtrIoRuns[i].LogicalBlock;
|
||||
|
||||
|
||||
//
|
||||
// Setup a completion routine...
|
||||
//
|
||||
IoSetCompletionRoutine( PtrAssociatedIrp,
|
||||
SynchronousIo ?
|
||||
Ext2MultiSyncCompletionRoutine :
|
||||
Ext2MultiAsyncCompletionRoutine,
|
||||
PtrIoContext, TRUE, TRUE, TRUE );
|
||||
|
||||
//
|
||||
// Initialise the next stack location for the driver below us to use...
|
||||
//
|
||||
PtrIrpSp = IoGetNextIrpStackLocation( PtrAssociatedIrp );
|
||||
PtrIrpSp->MajorFunction = PtrIrpContext->MajorFunction;
|
||||
if( PtrIrpContext->MajorFunction == IRP_MJ_READ )
|
||||
{
|
||||
PtrIrpSp->Parameters.Read.Length = ReadWriteLength;
|
||||
PtrIrpSp->Parameters.Read.ByteOffset.QuadPart = PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
|
||||
}
|
||||
else if( PtrIrpContext->MajorFunction == IRP_MJ_WRITE )
|
||||
{
|
||||
PtrIrpSp->Parameters.Write.Length = ReadWriteLength;
|
||||
PtrIrpSp->Parameters.Write.ByteOffset.QuadPart = PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
|
||||
}
|
||||
|
||||
// PtrIrpSp->Parameters.Read.Length = ReadWriteLength;
|
||||
// PtrIrpSp->Parameters.Read.ByteOffset.QuadPart =
|
||||
// PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
|
||||
}
|
||||
|
||||
for( i = 0; i < Count; i++ ) {
|
||||
DbgPrint("PASSING DOWN IRP %d TO TARGET DEVICE\n", i);
|
||||
IoCallDriver( PtrVCB->TargetDeviceObject, PtrIoRuns[ i].PtrAssociatedIrp );
|
||||
}
|
||||
|
||||
if( SynchronousIo )
|
||||
{
|
||||
//
|
||||
// Synchronous IO
|
||||
// Wait for the IO to complete...
|
||||
//
|
||||
DbgPrint("DEADLY WAIT (%d)\n", KeGetCurrentIrql());
|
||||
KeWaitForSingleObject( PtrSyncEvent,
|
||||
Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL );
|
||||
DbgPrint("DEADLY WAIT DONE\n");
|
||||
try_return ( RC );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Asynchronous IO...
|
||||
RC = STATUS_PENDING;
|
||||
try_return ( RC );
|
||||
}
|
||||
|
||||
try_exit: NOTHING;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if( PtrSyncEvent )
|
||||
{
|
||||
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrSyncEvent );
|
||||
ExFreePool( PtrSyncEvent );
|
||||
}
|
||||
if( PtrIoContext && ! ( RC == STATUS_PENDING || RC == STATUS_SUCCESS ) )
|
||||
{
|
||||
//
|
||||
// This means we are getting out of
|
||||
// this function without doing a read
|
||||
// due to an error, maybe...
|
||||
//
|
||||
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrIoContext);
|
||||
ExFreePool( PtrIoContext );
|
||||
}
|
||||
}
|
||||
return(RC);
|
||||
}
|
||||
|
||||
NTSTATUS Ext2PassDownSingleReadWriteIRP(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp,
|
||||
PtrExt2VCB PtrVCB,
|
||||
LARGE_INTEGER ByteOffset,
|
||||
uint32 ReadWriteLength,
|
||||
BOOLEAN SynchronousIo)
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
|
||||
PEXT2_IO_CONTEXT PtrIoContext = NULL;
|
||||
PKEVENT PtrSyncEvent = NULL;
|
||||
PVOID PtrReadBuffer = NULL;
|
||||
ULONG ReadBufferLength = 0;
|
||||
|
||||
ULONG LogicalBlockNo = 0;
|
||||
ULONG LogicalBlockSize = 0;
|
||||
ULONG PhysicalBlockSize = 0;
|
||||
|
||||
uint32 NumberBytesRead = 0;
|
||||
int i;
|
||||
PIO_STACK_LOCATION PtrIrpNextSp = NULL;
|
||||
|
||||
try
|
||||
{
|
||||
if( !PtrIrp->MdlAddress )
|
||||
{
|
||||
Ext2LockCallersBuffer( PtrIrp, TRUE, ReadWriteLength );
|
||||
}
|
||||
|
||||
|
||||
if( SynchronousIo )
|
||||
{
|
||||
PtrSyncEvent = Ext2AllocatePool( NonPagedPool, Ext2QuadAlign( sizeof(KEVENT) ) );
|
||||
if ( !PtrSyncEvent )
|
||||
{
|
||||
RC = STATUS_INSUFFICIENT_RESOURCES;
|
||||
try_return ( RC );
|
||||
}
|
||||
KeInitializeEvent( PtrSyncEvent, SynchronizationEvent, FALSE );
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate and initialize a completion context
|
||||
//
|
||||
PtrIoContext = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( sizeof(EXT2_IO_CONTEXT) ) );
|
||||
if ( !PtrIoContext )
|
||||
{
|
||||
RC = STATUS_INSUFFICIENT_RESOURCES;
|
||||
try_return ( RC );
|
||||
}
|
||||
|
||||
RtlZeroMemory( PtrIoContext, sizeof(EXT2_IO_CONTEXT) );
|
||||
PtrIoContext->Count = 1;
|
||||
PtrIoContext->NodeIdentifier.NodeType = EXT2_NODE_TYPE_IO_CONTEXT;
|
||||
PtrIoContext->NodeIdentifier.NodeSize = sizeof( EXT2_IO_CONTEXT );
|
||||
PtrIoContext->PtrMasterIrp = NULL;
|
||||
PtrIoContext->PtrSyncEvent = PtrSyncEvent;
|
||||
PtrIoContext->ReadWriteLength = ReadWriteLength;
|
||||
|
||||
IoSetCompletionRoutine( PtrIrp,
|
||||
SynchronousIo ?
|
||||
Ext2SingleSyncCompletionRoutine:
|
||||
Ext2SingleAsyncCompletionRoutine,
|
||||
PtrIoContext, TRUE, TRUE, TRUE );
|
||||
|
||||
//
|
||||
// Setup the next IRP stack location in the associated Irp for the disk
|
||||
// driver beneath us.
|
||||
//
|
||||
PtrIrpNextSp = IoGetNextIrpStackLocation( PtrIrp );
|
||||
|
||||
//
|
||||
// Setup the Stack location to do a read from the disk driver.
|
||||
//
|
||||
PtrIrpNextSp->MajorFunction = PtrIrpContext->MajorFunction;
|
||||
if( PtrIrpContext->MajorFunction == IRP_MJ_READ )
|
||||
{
|
||||
PtrIrpNextSp->Parameters.Read.Length = ReadWriteLength;
|
||||
PtrIrpNextSp->Parameters.Read.ByteOffset = ByteOffset;
|
||||
}
|
||||
else if( PtrIrpContext->MajorFunction == IRP_MJ_WRITE )
|
||||
{
|
||||
PtrIrpNextSp->Parameters.Write.Length = ReadWriteLength;
|
||||
PtrIrpNextSp->Parameters.Write.ByteOffset = ByteOffset;
|
||||
}
|
||||
//
|
||||
// Issue the read / write request
|
||||
//
|
||||
RC = IoCallDriver(PtrVCB->TargetDeviceObject, PtrIrp);
|
||||
|
||||
if( SynchronousIo )
|
||||
{
|
||||
//
|
||||
// Wait for completion...
|
||||
//
|
||||
RC = KeWaitForSingleObject( &PtrIoContext->PtrSyncEvent,
|
||||
Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL );
|
||||
|
||||
RC = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
RC = STATUS_PENDING;
|
||||
}
|
||||
|
||||
try_exit: NOTHING;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if( PtrSyncEvent )
|
||||
{
|
||||
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrSyncEvent );
|
||||
ExFreePool( PtrSyncEvent );
|
||||
}
|
||||
if( PtrIoContext && !( RC == STATUS_PENDING || RC == STATUS_SUCCESS ) )
|
||||
{
|
||||
//
|
||||
// This means we are getting out of
|
||||
// this function without doing a read / write
|
||||
// due to an error, maybe...
|
||||
//
|
||||
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrIoContext );
|
||||
ExFreePool( PtrIoContext );
|
||||
}
|
||||
}
|
||||
return RC;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2SingleSyncCompletionRoutine()
|
||||
*
|
||||
* Description:
|
||||
* Synchronous I/O Completion Routine
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* ?
|
||||
*
|
||||
* Return Value: NTSTATUS - STATUS_SUCCESS(always)
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2SingleSyncCompletionRoutine(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Contxt
|
||||
)
|
||||
{
|
||||
PEXT2_IO_CONTEXT PtrContext = Contxt;
|
||||
|
||||
if( Irp->PendingReturned )
|
||||
IoMarkIrpPending( Irp );
|
||||
|
||||
ASSERT( PtrContext );
|
||||
ASSERT( PtrContext->NodeIdentifier.NodeType == EXT2_NODE_TYPE_IO_CONTEXT );
|
||||
|
||||
KeSetEvent( PtrContext->PtrSyncEvent, 0, FALSE );
|
||||
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrContext );
|
||||
ExFreePool( PtrContext );
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2SingleAsyncCompletionRoutine()
|
||||
*
|
||||
* Description:
|
||||
* Asynchronous I/O Completion Routine
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* ?
|
||||
*
|
||||
* Return Value: NTSTATUS - STATUS_SUCCESS(always)
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2SingleAsyncCompletionRoutine(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Contxt
|
||||
)
|
||||
{
|
||||
PEXT2_IO_CONTEXT PtrContext = Contxt;
|
||||
|
||||
if( Irp->PendingReturned )
|
||||
IoMarkIrpPending( Irp );
|
||||
|
||||
ASSERT( PtrContext );
|
||||
ASSERT( PtrContext->NodeIdentifier.NodeType == EXT2_NODE_TYPE_IO_CONTEXT );
|
||||
|
||||
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrContext );
|
||||
ExFreePool( PtrContext );
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2MultiSyncCompletionRoutine()
|
||||
*
|
||||
* Description:
|
||||
* Synchronous I/O Completion Routine
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* ?
|
||||
*
|
||||
* Return Value: NTSTATUS - STATUS_SUCCESS(always)
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2MultiSyncCompletionRoutine (
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Contxt
|
||||
)
|
||||
{
|
||||
|
||||
PEXT2_IO_CONTEXT PtrContext = Contxt;
|
||||
ASSERT( PtrContext );
|
||||
|
||||
if( Irp->PendingReturned )
|
||||
{
|
||||
IoMarkIrpPending( Irp );
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS( Irp->IoStatus.Status ))
|
||||
{
|
||||
PtrContext->PtrMasterIrp->IoStatus.Status = Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
if (InterlockedDecrement( &PtrContext->Count ) == 0)
|
||||
{
|
||||
if ( NT_SUCCESS( PtrContext->PtrMasterIrp->IoStatus.Status ) )
|
||||
{
|
||||
PtrContext->PtrMasterIrp->IoStatus.Information = PtrContext->ReadWriteLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
PtrContext->PtrMasterIrp->IoStatus.Information = 0;
|
||||
}
|
||||
|
||||
KeSetEvent( PtrContext->PtrSyncEvent, 0, FALSE );
|
||||
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrContext );
|
||||
ExFreePool( PtrContext );
|
||||
}
|
||||
|
||||
//
|
||||
// The master Irp will be automatically completed
|
||||
// when all the associated IRPs are completed
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2MultiAsyncCompletionRoutine()
|
||||
*
|
||||
* Description:
|
||||
* Asynchronous I/O Completion Routine
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* ?
|
||||
*
|
||||
* Return Value: NTSTATUS - STATUS_SUCCESS(always)
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2MultiAsyncCompletionRoutine (
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Contxt
|
||||
)
|
||||
{
|
||||
|
||||
PEXT2_IO_CONTEXT PtrContext = Contxt;
|
||||
ASSERT( PtrContext );
|
||||
|
||||
if( Irp->PendingReturned )
|
||||
{
|
||||
IoMarkIrpPending( Irp );
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS( Irp->IoStatus.Status ))
|
||||
{
|
||||
PtrContext->PtrMasterIrp->IoStatus.Status = Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
if (InterlockedDecrement( &PtrContext->Count ) == 0)
|
||||
{
|
||||
if ( NT_SUCCESS( PtrContext->PtrMasterIrp->IoStatus.Status ) )
|
||||
{
|
||||
PtrContext->PtrMasterIrp->IoStatus.Information = PtrContext->ReadWriteLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
PtrContext->PtrMasterIrp->IoStatus.Information = 0;
|
||||
}
|
||||
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrContext );
|
||||
ExFreePool( PtrContext );
|
||||
}
|
||||
|
||||
//
|
||||
// The master Irp will be automatically completed
|
||||
// when all the associated IRPs are completed
|
||||
// Returning STATUS_SUCCESS to continue postprocessing...
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
2837
reactos/drivers/filesystems/ext2/src/metadata.c
Normal file
2837
reactos/drivers/filesystems/ext2/src/metadata.c
Normal file
File diff suppressed because it is too large
Load diff
2116
reactos/drivers/filesystems/ext2/src/misc.c
Normal file
2116
reactos/drivers/filesystems/ext2/src/misc.c
Normal file
File diff suppressed because it is too large
Load diff
1476
reactos/drivers/filesystems/ext2/src/read.c
Normal file
1476
reactos/drivers/filesystems/ext2/src/read.c
Normal file
File diff suppressed because it is too large
Load diff
211
reactos/drivers/filesystems/ext2/src/shutdown.c
Normal file
211
reactos/drivers/filesystems/ext2/src/shutdown.c
Normal file
|
@ -0,0 +1,211 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* File: shutdown.c
|
||||
*
|
||||
* Module: Ext2 File System Driver (Kernel mode execution only)
|
||||
*
|
||||
* Description:
|
||||
* Contains code to handle the "shutdown notification" dispatch entry point.
|
||||
*
|
||||
* Author: Manoj Paul Joseph
|
||||
*
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
#include "ext2fsd.h"
|
||||
|
||||
// define the file specific bug-check id
|
||||
#define EXT2_BUG_CHECK_ID EXT2_FILE_SHUTDOWN
|
||||
#define DEBUG_LEVEL (DEBUG_TRACE_SHUTDOWN)
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2Shutdown()
|
||||
*
|
||||
* Description:
|
||||
* All disk-based FSDs can expect to receive this shutdown notification
|
||||
* request whenever the system is about to be halted gracefully. If you
|
||||
* design and implement a network redirector, you must register explicitly
|
||||
* for shutdown notification by invoking the IoRegisterShutdownNotification()
|
||||
* routine from your driver entry.
|
||||
*
|
||||
* Note that drivers that register to receive shutdown notification get
|
||||
* invoked BEFORE disk-based FSDs are told about the shutdown notification.
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: Irrelevant.
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2Shutdown(
|
||||
PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
PIRP Irp) // I/O Request Packet
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
PtrExt2IrpContext PtrIrpContext = NULL;
|
||||
BOOLEAN AreWeTopLevel = FALSE;
|
||||
|
||||
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Shutdown IRP received...", 0);
|
||||
|
||||
FsRtlEnterFileSystem();
|
||||
ASSERT(DeviceObject);
|
||||
ASSERT(Irp);
|
||||
|
||||
// set the top level context
|
||||
AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
// get an IRP context structure and issue the request
|
||||
PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
|
||||
ASSERT(PtrIrpContext);
|
||||
|
||||
RC = Ext2CommonShutdown(PtrIrpContext, Irp);
|
||||
|
||||
}
|
||||
except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
|
||||
{
|
||||
|
||||
RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
|
||||
|
||||
Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
|
||||
}
|
||||
|
||||
if (AreWeTopLevel)
|
||||
{
|
||||
IoSetTopLevelIrp(NULL);
|
||||
}
|
||||
|
||||
FsRtlExitFileSystem();
|
||||
|
||||
return(RC);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2CommonShutdown()
|
||||
*
|
||||
* Description:
|
||||
* The actual work is performed here. Basically, all we do here is
|
||||
* internally invoke a flush on all mounted logical volumes. This, in
|
||||
* tuen, will result in all open file streams being flushed to disk.
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: Irrelevant
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2CommonShutdown(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp)
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
PIO_STACK_LOCATION PtrIoStackLocation = NULL;
|
||||
IO_STATUS_BLOCK LocalIoStatus;
|
||||
|
||||
try
|
||||
{
|
||||
// First, get a pointer to the current I/O stack location
|
||||
PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
|
||||
ASSERT(PtrIoStackLocation);
|
||||
|
||||
// (a) Block all new "mount volume" requests by acquiring an appropriate
|
||||
// global resource/lock.
|
||||
// (b) Go through your linked list of mounted logical volumes and for
|
||||
// each such volume, do the following:
|
||||
// (i) acquire the volume resource exclusively
|
||||
// (ii) invoke Ext2FlushLogicalVolume() (internally) to flush the
|
||||
// open data streams belonging to the volume from the system
|
||||
// cache
|
||||
// (iii) Invoke the physical/virtual/logical target device object
|
||||
// on which the volume is mounted and inform this device
|
||||
// about the shutdown request (Use IoBuildSynchronousFsdRequest()
|
||||
// to create an IRP with MajorFunction = IRP_MJ_SHUTDOWN that you
|
||||
// will then issue to the target device object).
|
||||
// (iv) Wait for the completion of the shutdown processing by the target
|
||||
// device object
|
||||
// (v) Release the VCB resource you will have acquired in (i) above.
|
||||
|
||||
// Once you have processed all the mounted logical volumes, you can release
|
||||
// all acquired global resources and leave (in peace :-)
|
||||
|
||||
|
||||
|
||||
/*////////////////////////////////////////////
|
||||
//
|
||||
// Update the Group...
|
||||
//
|
||||
if( PtrVCB->LogBlockSize )
|
||||
{
|
||||
// First block contains the descriptors...
|
||||
VolumeByteOffset.QuadPart = LogicalBlockSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Second block contains the descriptors...
|
||||
VolumeByteOffset.QuadPart = LogicalBlockSize * 2;
|
||||
}
|
||||
|
||||
NumberOfBytesToRead = sizeof( struct ext2_group_desc );
|
||||
NumberOfBytesToRead = Ext2Align( NumberOfBytesToRead, LogicalBlockSize );
|
||||
|
||||
if (!CcMapData( PtrVCB->PtrStreamFileObject,
|
||||
&VolumeByteOffset,
|
||||
NumberOfBytesToRead,
|
||||
TRUE,
|
||||
&PtrBCB,
|
||||
&PtrCacheBuffer ))
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0);
|
||||
try_return( Status = STATUS_INSUFFICIENT_RESOURCES );
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Saving up Often Used Group Descriptor Information in the VCB...
|
||||
//
|
||||
unsigned int DescIndex ;
|
||||
|
||||
DebugTrace(DEBUG_TRACE_MISC, "Cache hit while reading in volume meta data", 0);
|
||||
PtrGroupDescriptor = (PEXT2_GROUP_DESCRIPTOR )PtrCacheBuffer;
|
||||
for( DescIndex = 0; DescIndex < PtrVCB->NoOfGroups; DescIndex++ )
|
||||
{
|
||||
PtrVCB->PtrGroupDescriptors[ DescIndex ].InodeTablesBlock
|
||||
= PtrGroupDescriptor[ DescIndex ].bg_inode_table;
|
||||
|
||||
PtrVCB->PtrGroupDescriptors[ DescIndex ].InodeBitmapBlock
|
||||
= PtrGroupDescriptor[ DescIndex ].bg_inode_bitmap
|
||||
;
|
||||
PtrVCB->PtrGroupDescriptors[ DescIndex ].BlockBitmapBlock
|
||||
= PtrGroupDescriptor[ DescIndex ].bg_block_bitmap
|
||||
;
|
||||
PtrVCB->PtrGroupDescriptors[ DescIndex ].FreeBlocksCount
|
||||
= PtrGroupDescriptor[ DescIndex ].bg_free_blocks_count;
|
||||
|
||||
PtrVCB->PtrGroupDescriptors[ DescIndex ].FreeInodesCount
|
||||
= PtrGroupDescriptor[ DescIndex ].bg_free_inodes_count;
|
||||
}
|
||||
CcUnpinData( PtrBCB );
|
||||
PtrBCB = NULL;
|
||||
}
|
||||
*/////////////////////////////////////////////
|
||||
|
||||
try_exit: NOTHING;
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
// See the read/write examples for how to fill in this portion
|
||||
|
||||
} // end of "finally" processing
|
||||
|
||||
return(RC);
|
||||
}
|
339
reactos/drivers/filesystems/ext2/src/volinfo.c
Normal file
339
reactos/drivers/filesystems/ext2/src/volinfo.c
Normal file
|
@ -0,0 +1,339 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* File: volinfo.c
|
||||
*
|
||||
* Module: Ext2 File System Driver (Kernel mode execution only)
|
||||
*
|
||||
* Description:
|
||||
* Contains code to handle the various Volume Information related calls.
|
||||
*
|
||||
* Author: Manoj Paul Joseph
|
||||
*
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include "ext2fsd.h"
|
||||
|
||||
|
||||
|
||||
|
||||
// define the file specific bug-check id
|
||||
#define EXT2_BUG_CHECK_ID EXT2_FILE_VOL_INFORMATION
|
||||
#define DEBUG_LEVEL (DEBUG_TRACE_VOLINFO)
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2QueryVolInfo()
|
||||
*
|
||||
* Description:
|
||||
* The I/O Manager will invoke this routine to handle a
|
||||
* Query Volume Info IRP
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* ???
|
||||
*
|
||||
* Arguments:
|
||||
*
|
||||
* DeviceObject - Supplies the volume device object where the
|
||||
* file exists
|
||||
*
|
||||
* Irp - Supplies the Irp being processed
|
||||
*
|
||||
*
|
||||
* Return Value:
|
||||
*
|
||||
* NTSTATUS - The FSD status for the IRP
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS Ext2QueryVolInfo (
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
|
||||
// The Return Status
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
// The IRP Stack Location
|
||||
PIO_STACK_LOCATION IrpSp = NULL;
|
||||
|
||||
// Volume Control Block
|
||||
PtrExt2VCB PtrVCB = NULL;
|
||||
|
||||
// The class of the query IRP
|
||||
FS_INFORMATION_CLASS FsInformationClass;
|
||||
|
||||
// The System Buffer Pointer
|
||||
PVOID Buffer = NULL;
|
||||
|
||||
// Parameter Length
|
||||
ULONG Length = 0;
|
||||
|
||||
// Bytes copied...
|
||||
ULONG BytesCopied = 0;
|
||||
|
||||
// Pointers to the Output Information...
|
||||
PFILE_FS_VOLUME_INFORMATION PtrVolumeInformation = NULL;
|
||||
PFILE_FS_SIZE_INFORMATION PtrSizeInformation = NULL;
|
||||
PFILE_FS_ATTRIBUTE_INFORMATION PtrAttributeInformation = NULL;
|
||||
PFILE_FS_DEVICE_INFORMATION PtrDeviceInformation = NULL;
|
||||
PFILE_FS_FULL_SIZE_INFORMATION PtrFullSizeInformation = NULL;
|
||||
|
||||
|
||||
// Now for the handler code...
|
||||
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "QueryVolumeInformation IRP", 0);
|
||||
|
||||
FsRtlEnterFileSystem();
|
||||
|
||||
try
|
||||
{
|
||||
// Getting a pointer to the current I/O stack location
|
||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
ASSERT( IrpSp );
|
||||
|
||||
// Getting the VCB and Verifying it...
|
||||
PtrVCB = ( PtrExt2VCB )( DeviceObject->DeviceExtension );
|
||||
ASSERT(PtrVCB);
|
||||
ASSERT(PtrVCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB);
|
||||
|
||||
// Getting the query parameters...
|
||||
Length = IrpSp->Parameters.QueryVolume.Length;
|
||||
FsInformationClass = IrpSp->Parameters.QueryVolume.FsInformationClass;
|
||||
Buffer = Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
// Now servicing the request depending on the type...
|
||||
switch (FsInformationClass)
|
||||
{
|
||||
case FileFsVolumeInformation:
|
||||
DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsVolumeInformation", 0);
|
||||
PtrVolumeInformation = Buffer;
|
||||
PtrVolumeInformation->SupportsObjects = FALSE;
|
||||
PtrVolumeInformation->VolumeCreationTime.QuadPart = 0;
|
||||
RtlCopyMemory(
|
||||
PtrVolumeInformation->VolumeLabel, // destination
|
||||
PtrVCB->PtrVPB->VolumeLabel, // source
|
||||
PtrVCB->PtrVPB->VolumeLabelLength );
|
||||
PtrVolumeInformation->VolumeLabelLength = PtrVCB->PtrVPB->VolumeLabelLength;
|
||||
PtrVolumeInformation->VolumeSerialNumber = PtrVCB->PtrVPB->SerialNumber;
|
||||
BytesCopied = sizeof( FILE_FS_VOLUME_INFORMATION ) + PtrVolumeInformation->VolumeLabelLength - sizeof( WCHAR);
|
||||
break;
|
||||
|
||||
case FileFsSizeInformation:
|
||||
DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsSizeInformation", 0);
|
||||
PtrSizeInformation = Buffer;
|
||||
PtrSizeInformation->BytesPerSector = DeviceObject->SectorSize;
|
||||
PtrSizeInformation->AvailableAllocationUnits.QuadPart = PtrVCB->FreeBlocksCount;
|
||||
PtrSizeInformation->SectorsPerAllocationUnit = ( EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize) / DeviceObject->SectorSize;
|
||||
PtrSizeInformation->TotalAllocationUnits.QuadPart = PtrVCB->BlocksCount;
|
||||
BytesCopied = sizeof( FILE_FS_SIZE_INFORMATION );
|
||||
break;
|
||||
|
||||
case FileFsDeviceInformation:
|
||||
DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsDeviceInformation", 0);
|
||||
PtrDeviceInformation = Buffer;
|
||||
PtrDeviceInformation->DeviceType = FILE_DEVICE_DISK;
|
||||
PtrDeviceInformation->Characteristics = FILE_DEVICE_IS_MOUNTED;
|
||||
BytesCopied = sizeof( FILE_FS_DEVICE_INFORMATION );
|
||||
break;
|
||||
|
||||
case FileFsAttributeInformation:
|
||||
DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsAttributeInformation", 0);
|
||||
PtrAttributeInformation = Buffer;
|
||||
RtlCopyMemory( PtrAttributeInformation->FileSystemName, L"EXT2", 10 );
|
||||
PtrAttributeInformation->FileSystemNameLength = 8;
|
||||
PtrAttributeInformation->MaximumComponentNameLength = 255;
|
||||
PtrAttributeInformation->FileSystemAttributes =
|
||||
FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
|
||||
BytesCopied = sizeof( FILE_FS_ATTRIBUTE_INFORMATION ) + 8;
|
||||
|
||||
break;
|
||||
|
||||
case FileFsFullSizeInformation:
|
||||
DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsFullSizeInformation", 0);
|
||||
PtrFullSizeInformation = Buffer;
|
||||
PtrFullSizeInformation->BytesPerSector = DeviceObject->SectorSize;
|
||||
PtrFullSizeInformation->ActualAvailableAllocationUnits.QuadPart = PtrVCB->FreeBlocksCount;
|
||||
PtrFullSizeInformation->SectorsPerAllocationUnit = (EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize) / DeviceObject->SectorSize;
|
||||
PtrFullSizeInformation->TotalAllocationUnits.QuadPart = PtrVCB->BlocksCount;
|
||||
PtrFullSizeInformation->CallerAvailableAllocationUnits.QuadPart = PtrVCB->FreeBlocksCount - PtrVCB->ReservedBlocksCount;
|
||||
BytesCopied = sizeof( FILE_FS_FULL_SIZE_INFORMATION );
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
DebugTrace(DEBUG_TRACE_MISC, "Query Volume - STATUS_INVALID_PARAMETER", 0);
|
||||
break;
|
||||
}
|
||||
|
||||
if( IrpSp->Parameters.QueryVolume.Length < BytesCopied )
|
||||
{
|
||||
BytesCopied = IrpSp->Parameters.QueryVolume.Length;
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
DebugTrace(DEBUG_TRACE_MISC, " === Buffer insufficient", 0);
|
||||
}
|
||||
try_exit: NOTHING;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Irp->IoStatus.Information = BytesCopied;
|
||||
Ext2CompleteRequest( Irp, Status );
|
||||
}
|
||||
FsRtlExitFileSystem();
|
||||
|
||||
//
|
||||
// Now return to the caller
|
||||
//
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NTSTATUS Ext2SetVolInfo(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
// The Return Status
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
// The IRP Stack Location
|
||||
PIO_STACK_LOCATION IrpSp = NULL;
|
||||
|
||||
// Volume Control Block
|
||||
PtrExt2VCB PtrVCB = NULL;
|
||||
|
||||
// The class of the query IRP
|
||||
FS_INFORMATION_CLASS FsInformationClass;
|
||||
|
||||
// Pointers to the Output Information...
|
||||
PFILE_FS_LABEL_INFORMATION PtrVolumeLabelInformation = NULL;
|
||||
|
||||
// Now for the handler code...
|
||||
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Set Volume Information IRP", 0);
|
||||
|
||||
FsRtlEnterFileSystem();
|
||||
|
||||
try
|
||||
{
|
||||
// Getting a pointer to the current I/O stack location
|
||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
ASSERT( IrpSp );
|
||||
|
||||
// Getting the VCB and Verifying it...
|
||||
PtrVCB = ( PtrExt2VCB )( DeviceObject->DeviceExtension );
|
||||
AssertVCB(PtrVCB);
|
||||
|
||||
// Getting the query parameters...
|
||||
// Length = IrpSp->Parameters.SetVolume.Length;
|
||||
#ifdef _GNU_NTIFS_
|
||||
FsInformationClass = ((PEXTENDED_IO_STACK_LOCATION)IrpSp)->Parameters.SetVolume.FsInformationClass;
|
||||
#else
|
||||
FsInformationClass = IrpSp->Parameters.SetVolume.FsInformationClass;
|
||||
#endif
|
||||
|
||||
// Now servicing the request depending on the type...
|
||||
switch (FsInformationClass)
|
||||
{
|
||||
case FileFsLabelInformation:
|
||||
PtrVolumeLabelInformation = Irp->AssociatedIrp.SystemBuffer;
|
||||
if( PtrVolumeLabelInformation->VolumeLabelLength > MAXIMUM_VOLUME_LABEL_LENGTH || // This is the maximum that the
|
||||
// VPB can take...
|
||||
PtrVolumeLabelInformation->VolumeLabelLength > 32 ) // this is the maximum that Ext2 FS can support..
|
||||
{
|
||||
try_return( Status = STATUS_INVALID_VOLUME_LABEL );
|
||||
}
|
||||
|
||||
PtrVCB->PtrVPB->VolumeLabelLength = (USHORT)PtrVolumeLabelInformation->VolumeLabelLength ;
|
||||
RtlCopyMemory(
|
||||
PtrVCB->PtrVPB->VolumeLabel, // destination
|
||||
PtrVolumeLabelInformation->VolumeLabel, // source
|
||||
PtrVolumeLabelInformation->VolumeLabelLength );
|
||||
|
||||
{
|
||||
// Now update the volume's super block...
|
||||
|
||||
PEXT2_SUPER_BLOCK PtrSuperBlock = NULL;
|
||||
PBCB PtrSuperBlockBCB = NULL;
|
||||
LARGE_INTEGER VolumeByteOffset;
|
||||
ULONG LogicalBlockSize = 0;
|
||||
ULONG NumberOfBytesToRead = 0;
|
||||
|
||||
|
||||
// Reading in the super block...
|
||||
VolumeByteOffset.QuadPart = 1024;
|
||||
|
||||
LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
|
||||
|
||||
// THis shouldn't be more than a block in size...
|
||||
NumberOfBytesToRead = Ext2Align( sizeof( EXT2_SUPER_BLOCK ), LogicalBlockSize );
|
||||
|
||||
if( !CcPinRead( PtrVCB->PtrStreamFileObject,
|
||||
&VolumeByteOffset,
|
||||
NumberOfBytesToRead,
|
||||
TRUE,
|
||||
&PtrSuperBlockBCB,
|
||||
(PVOID*)&PtrSuperBlock ) )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0);
|
||||
try_return( Status = STATUS_INVALID_VOLUME_LABEL );
|
||||
}
|
||||
else
|
||||
{
|
||||
ULONG i;
|
||||
for( i = 0; i < (PtrVolumeLabelInformation->VolumeLabelLength/2) ; i++ )
|
||||
{
|
||||
PtrSuperBlock->s_volume_name[i] =
|
||||
(char) PtrVolumeLabelInformation->VolumeLabel[i] ;
|
||||
if( PtrSuperBlock->s_volume_name[i] == 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( i < 16 )
|
||||
{
|
||||
PtrSuperBlock->s_volume_name[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
CcSetDirtyPinnedData( PtrSuperBlockBCB, NULL );
|
||||
|
||||
// Not saving and flushing this information synchronously...
|
||||
// This is not a critical information..
|
||||
// Settling for lazy writing of this information
|
||||
|
||||
// Ext2SaveBCB( PtrIrpContext, PtrSuperBlockBCB, PtrVCB->PtrStreamFileObject );
|
||||
|
||||
if( PtrSuperBlockBCB )
|
||||
{
|
||||
CcUnpinData( PtrSuperBlockBCB );
|
||||
PtrSuperBlockBCB = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
DebugTrace(DEBUG_TRACE_MISC, "Query Volume - STATUS_INVALID_PARAMETER", 0);
|
||||
break;
|
||||
}
|
||||
|
||||
try_exit: NOTHING;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Irp->IoStatus.Information = 0;
|
||||
Ext2CompleteRequest( Irp, Status );
|
||||
}
|
||||
FsRtlExitFileSystem();
|
||||
|
||||
//
|
||||
// Now return to the caller
|
||||
//
|
||||
|
||||
return Status;
|
||||
}
|
1483
reactos/drivers/filesystems/ext2/src/write.c
Normal file
1483
reactos/drivers/filesystems/ext2/src/write.c
Normal file
File diff suppressed because it is too large
Load diff
136
reactos/drivers/filesystems/fs_rec/ext2.c
Normal file
136
reactos/drivers/filesystems/fs_rec/ext2.c
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2002,2003 ReactOS Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: fat.c 9284 2004-05-02 20:12:38Z hbirr $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/fs/fs_rec/ext2.c (based on vfat.c)
|
||||
* PURPOSE: Filesystem recognizer driver
|
||||
* PROGRAMMER: Eric Kohl
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <rosrtl/string.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#include "fs_rec.h"
|
||||
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
static NTSTATUS
|
||||
FsRecIsExt2Volume(IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PARTITION_INFORMATION PartitionInfo;
|
||||
DISK_GEOMETRY DiskGeometry;
|
||||
ULONG Size;
|
||||
BOOL RecognizedFS = FALSE;
|
||||
Size = sizeof(DISK_GEOMETRY);
|
||||
|
||||
Status = FsRecDeviceIoControl(DeviceObject,
|
||||
IOCTL_DISK_GET_DRIVE_GEOMETRY,
|
||||
NULL,
|
||||
0,
|
||||
&DiskGeometry,
|
||||
&Size);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("FsRecDeviceIoControl faild (%x)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
if (DiskGeometry.MediaType == FixedMedia || DiskGeometry.MediaType == RemovableMedia)
|
||||
{
|
||||
// We have found a hard disk
|
||||
Size = sizeof(PARTITION_INFORMATION);
|
||||
Status = FsRecDeviceIoControl(DeviceObject,
|
||||
IOCTL_DISK_GET_PARTITION_INFO,
|
||||
NULL,
|
||||
0,
|
||||
&PartitionInfo,
|
||||
&Size);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("FsRecDeviceIoControl faild (%x)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (PartitionInfo.PartitionType)
|
||||
{
|
||||
if (PartitionInfo.PartitionType == PARTITION_EXT2)
|
||||
{
|
||||
RecognizedFS = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return RecognizedFS ? STATUS_SUCCESS : STATUS_UNRECOGNIZED_VOLUME;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
FsRecExt2FsControl(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION Stack;
|
||||
UNICODE_STRING RegistryPath;
|
||||
NTSTATUS Status;
|
||||
|
||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
switch (Stack->MinorFunction)
|
||||
{
|
||||
case IRP_MN_MOUNT_VOLUME:
|
||||
DPRINT("FAT: IRP_MN_MOUNT_VOLUME\n");
|
||||
Status = FsRecIsExt2Volume(Stack->Parameters.MountVolume.DeviceObject);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Identified FAT volume\n");
|
||||
Status = STATUS_FS_DRIVER_REQUIRED;
|
||||
}
|
||||
break;
|
||||
|
||||
case IRP_MN_LOAD_FILE_SYSTEM:
|
||||
DPRINT("FAT: IRP_MN_LOAD_FILE_SYSTEM\n");
|
||||
RtlRosInitUnicodeStringFromLiteral(&RegistryPath,
|
||||
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Ext2");
|
||||
Status = ZwLoadDriver(&RegistryPath);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ZwLoadDriver failed (Status %x)\n", Status);
|
||||
}
|
||||
else
|
||||
{
|
||||
IoUnregisterFileSystem(DeviceObject);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DPRINT("FAT: Unknown minor function %lx\n", Stack->MinorFunction);
|
||||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
break;
|
||||
}
|
||||
return(Status);
|
||||
}
|
||||
|
||||
/* EOF */
|
26
reactos/include/reactos/libs/fslib/ext2lib.h
Normal file
26
reactos/include/reactos/libs/fslib/ext2lib.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS EXT2 filesystem library
|
||||
* FILE: include/fslib/ext2lib.h
|
||||
* PURPOSE: Public definitions for ext2 filesystem library
|
||||
*/
|
||||
#ifndef __EXT2LIB_H
|
||||
#define __EXT2LIB_H
|
||||
|
||||
#include <fmifs.h>
|
||||
|
||||
NTSTATUS
|
||||
Ext2Initialize (VOID);
|
||||
|
||||
NTSTATUS
|
||||
Ext2Cleanup (VOID);
|
||||
|
||||
NTSTATUS
|
||||
Ext2Format (PUNICODE_STRING DriveRoot,
|
||||
ULONG MediaFlag,
|
||||
PUNICODE_STRING Label,
|
||||
BOOLEAN QuickFormat,
|
||||
ULONG ClusterSize,
|
||||
PFMIFSCALLBACK Callback);
|
||||
|
||||
#endif /*__EXT2LIB_H */
|
43
reactos/lib/fslib/ext2lib/Badblock.c
Normal file
43
reactos/lib/fslib/ext2lib/Badblock.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* PROJECT: Mke2fs
|
||||
* FILE: Badblock.c
|
||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||
* HOMEPAGE: http://ext2.yeah.net
|
||||
*/
|
||||
|
||||
/* INCLUDES **************************************************************/
|
||||
|
||||
#include "Mke2fs.h"
|
||||
|
||||
/* DEFINITIONS ***********************************************************/
|
||||
|
||||
/* FUNCTIONS *************************************************************/
|
||||
|
||||
bool create_bad_block_inode( PEXT2_FILESYS Ext2Sys,
|
||||
PEXT2_BADBLK_LIST bb_list)
|
||||
{
|
||||
bool retval;
|
||||
EXT2_INODE inode;
|
||||
LARGE_INTEGER SysTime;
|
||||
|
||||
NtQuerySystemTime(&SysTime);
|
||||
|
||||
ext2_mark_inode_bitmap(Ext2Sys->inode_map, EXT2_BAD_INO);
|
||||
|
||||
Ext2Sys->group_desc[0].bg_free_inodes_count--;
|
||||
Ext2Sys->ext2_sb->s_free_inodes_count--;
|
||||
|
||||
memset(&inode, 0, sizeof(EXT2_INODE));
|
||||
inode.i_mode = (USHORT)((0777 & ~Ext2Sys->umask));
|
||||
inode.i_uid = inode.i_gid = 0;
|
||||
inode.i_blocks = 0;
|
||||
inode.i_block[0] = 0;
|
||||
inode.i_links_count = 2;
|
||||
RtlTimeToSecondsSince1970(&SysTime, &inode.i_mtime);
|
||||
inode.i_ctime = inode.i_atime = inode.i_mtime;
|
||||
inode.i_size = 0;
|
||||
|
||||
retval = ext2_save_inode(Ext2Sys, EXT2_BAD_INO, &inode);
|
||||
|
||||
return retval;
|
||||
}
|
499
reactos/lib/fslib/ext2lib/Bitmap.c
Normal file
499
reactos/lib/fslib/ext2lib/Bitmap.c
Normal file
|
@ -0,0 +1,499 @@
|
|||
/*
|
||||
* PROJECT: Mke2fs
|
||||
* FILE: Bitmap.c
|
||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||
* HOMEPAGE: http://ext2.yeah.net
|
||||
*/
|
||||
|
||||
/* INCLUDES **************************************************************/
|
||||
|
||||
#include "Mke2fs.h"
|
||||
|
||||
/* DEFINITIONS ***********************************************************/
|
||||
|
||||
/* FUNCTIONS *************************************************************/
|
||||
|
||||
|
||||
bool ext2_set_bit(int nr,void * addr)
|
||||
{
|
||||
int mask;
|
||||
unsigned char *ADDR = (unsigned char *) addr;
|
||||
|
||||
ADDR += nr >> 3;
|
||||
mask = 1 << (nr & 0x07);
|
||||
*ADDR |= mask;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ext2_clear_bit(int nr, void * addr)
|
||||
{
|
||||
int mask;
|
||||
unsigned char *ADDR = (unsigned char *) addr;
|
||||
|
||||
ADDR += nr >> 3;
|
||||
mask = 1 << (nr & 0x07);
|
||||
*ADDR &= ~mask;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ext2_test_bit(int nr, void * addr)
|
||||
{
|
||||
int mask;
|
||||
const unsigned char *ADDR = (const unsigned char *) addr;
|
||||
|
||||
ADDR += nr >> 3;
|
||||
mask = 1 << (nr & 0x07);
|
||||
|
||||
return ((mask & *ADDR) != 0);
|
||||
}
|
||||
|
||||
bool ext2_mark_bitmap(PEXT2_BITMAP bitmap, ULONG bitno)
|
||||
{
|
||||
if ((bitno < bitmap->start) || (bitno > bitmap->end))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ext2_set_bit(bitno - bitmap->start, bitmap->bitmap);
|
||||
}
|
||||
|
||||
bool ext2_unmark_bitmap(PEXT2_BITMAP bitmap, ULONG bitno)
|
||||
{
|
||||
if ((bitno < bitmap->start) || (bitno > bitmap->end))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ext2_clear_bit(bitno - bitmap->start, bitmap->bitmap);
|
||||
}
|
||||
|
||||
|
||||
bool ext2_test_block_bitmap(PEXT2_BLOCK_BITMAP bitmap,
|
||||
ULONG block)
|
||||
{
|
||||
return ext2_test_bit(block - bitmap->start, bitmap->bitmap);
|
||||
}
|
||||
|
||||
|
||||
bool ext2_test_block_bitmap_range(PEXT2_BLOCK_BITMAP bitmap,
|
||||
ULONG block, int num)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < num; i++)
|
||||
{
|
||||
if (ext2_test_block_bitmap(bitmap, block+i))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ext2_test_inode_bitmap(PEXT2_BLOCK_BITMAP bitmap,
|
||||
ULONG inode)
|
||||
{
|
||||
return ext2_test_bit(inode - bitmap->start, bitmap->bitmap);
|
||||
}
|
||||
|
||||
|
||||
bool ext2_allocate_block_bitmap(PEXT2_FILESYS Ext2Sys)
|
||||
{
|
||||
ULONG size = 0;
|
||||
|
||||
PEXT2_SUPER_BLOCK pExt2Sb = Ext2Sys->ext2_sb;
|
||||
Ext2Sys->block_map = (PEXT2_BLOCK_BITMAP)
|
||||
RtlAllocateHeap(GetProcessHeap(), 0, sizeof(EXT2_BLOCK_BITMAP));
|
||||
|
||||
if (!Ext2Sys->block_map)
|
||||
{
|
||||
KdPrint(("Mke2fs: error allocating block bitmap...\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(Ext2Sys->block_map, 0, sizeof(EXT2_BLOCK_BITMAP));
|
||||
|
||||
Ext2Sys->block_map->start = pExt2Sb->s_first_data_block;
|
||||
Ext2Sys->block_map->end = pExt2Sb->s_blocks_count-1;
|
||||
Ext2Sys->block_map->real_end = (EXT2_BLOCKS_PER_GROUP(pExt2Sb)
|
||||
* Ext2Sys->group_desc_count) -1 + Ext2Sys->block_map->start;
|
||||
|
||||
size = (((Ext2Sys->block_map->real_end - Ext2Sys->block_map->start) / 8) + 1);
|
||||
|
||||
Ext2Sys->block_map->bitmap =
|
||||
(char *)RtlAllocateHeap(GetProcessHeap(), 0, size);
|
||||
|
||||
if (!Ext2Sys->block_map->bitmap)
|
||||
{
|
||||
RtlFreeHeap(GetProcessHeap(), 0, Ext2Sys->block_map);
|
||||
Ext2Sys->block_map = NULL;
|
||||
KdPrint(("Mke2fs: error allocating block bitmap...\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(Ext2Sys->block_map->bitmap, 0, size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ext2_allocate_inode_bitmap(PEXT2_FILESYS Ext2Sys)
|
||||
{
|
||||
ULONG size = 0;
|
||||
|
||||
PEXT2_SUPER_BLOCK pExt2Sb = Ext2Sys->ext2_sb;
|
||||
|
||||
Ext2Sys->inode_map = (PEXT2_INODE_BITMAP)
|
||||
RtlAllocateHeap(GetProcessHeap(), 0, sizeof(EXT2_INODE_BITMAP));
|
||||
|
||||
if (!Ext2Sys->inode_map)
|
||||
{
|
||||
KdPrint(("Mke2fs: error allocating inode bitmap...\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(Ext2Sys->inode_map, 0, sizeof(EXT2_INODE_BITMAP));
|
||||
|
||||
Ext2Sys->inode_map->start = 1;
|
||||
Ext2Sys->inode_map->end = pExt2Sb->s_inodes_count;
|
||||
Ext2Sys->inode_map->real_end = (EXT2_INODES_PER_GROUP(pExt2Sb)
|
||||
* Ext2Sys->group_desc_count);
|
||||
|
||||
size = (((Ext2Sys->inode_map->real_end - Ext2Sys->inode_map->start) / 8) + 1);
|
||||
|
||||
Ext2Sys->inode_map->bitmap =
|
||||
(char *)RtlAllocateHeap(GetProcessHeap(), 0, size);
|
||||
|
||||
if (!Ext2Sys->inode_map->bitmap)
|
||||
{
|
||||
RtlFreeHeap(GetProcessHeap(), 0, Ext2Sys->inode_map);
|
||||
Ext2Sys->inode_map = NULL;
|
||||
KdPrint(("Mke2fs: error allocating block bitmap...\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(Ext2Sys->inode_map->bitmap, 0, size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ext2_free_generic_bitmap(PEXT2_GENERIC_BITMAP bitmap)
|
||||
{
|
||||
if (!bitmap)
|
||||
return;
|
||||
|
||||
if (bitmap->bitmap)
|
||||
{
|
||||
RtlFreeHeap(GetProcessHeap(), 0, bitmap->bitmap);
|
||||
bitmap->bitmap = 0;
|
||||
}
|
||||
|
||||
RtlFreeHeap(GetProcessHeap(), 0, bitmap);
|
||||
}
|
||||
|
||||
void ext2_free_inode_bitmap(PEXT2_FILESYS Ext2Sys)
|
||||
{
|
||||
PEXT2_INODE_BITMAP bitmap = Ext2Sys->inode_map;
|
||||
if (!bitmap)
|
||||
return;
|
||||
|
||||
ext2_free_generic_bitmap(bitmap);
|
||||
|
||||
Ext2Sys->inode_map = NULL;
|
||||
}
|
||||
|
||||
void ext2_free_block_bitmap(PEXT2_FILESYS Ext2Sys)
|
||||
{
|
||||
PEXT2_BLOCK_BITMAP bitmap = Ext2Sys->block_map;
|
||||
if (!bitmap)
|
||||
return;
|
||||
|
||||
ext2_free_generic_bitmap(bitmap);
|
||||
|
||||
Ext2Sys->block_map = NULL;
|
||||
}
|
||||
|
||||
bool ext2_write_inode_bitmap(PEXT2_FILESYS fs)
|
||||
{
|
||||
ULONG i;
|
||||
ULONG nbytes;
|
||||
bool retval;
|
||||
char *inode_bitmap = fs->inode_map->bitmap;
|
||||
char *bitmap_block = NULL;
|
||||
ULONG blk;
|
||||
|
||||
if (!inode_bitmap)
|
||||
return false;
|
||||
|
||||
nbytes = (size_t) ((EXT2_INODES_PER_GROUP(fs->ext2_sb)+7) / 8);
|
||||
|
||||
bitmap_block = (char *)RtlAllocateHeap(GetProcessHeap(), 0, fs->blocksize);
|
||||
if (!bitmap_block) return false;
|
||||
|
||||
memset(bitmap_block, 0xff, fs->blocksize);
|
||||
|
||||
for (i = 0; i < fs->group_desc_count; i++)
|
||||
{
|
||||
memcpy(bitmap_block, inode_bitmap, nbytes);
|
||||
blk = fs->group_desc[i].bg_inode_bitmap;
|
||||
|
||||
if (blk)
|
||||
{
|
||||
/*
|
||||
#ifdef EXT2_BIG_ENDIAN_BITMAPS
|
||||
if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
|
||||
(fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
|
||||
ext2_swap_bitmap(fs, bitmap_block, nbytes);
|
||||
#endif
|
||||
*/
|
||||
retval = NT_SUCCESS(Ext2WriteDisk(
|
||||
fs,
|
||||
((ULONGLONG)blk * fs->blocksize),
|
||||
fs->blocksize,
|
||||
(unsigned char *)bitmap_block));
|
||||
|
||||
if (!retval)
|
||||
{
|
||||
RtlFreeHeap(GetProcessHeap(), 0, bitmap_block);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inode_bitmap += nbytes;
|
||||
}
|
||||
|
||||
RtlFreeHeap(GetProcessHeap(), 0, bitmap_block);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ext2_write_block_bitmap (PEXT2_FILESYS fs)
|
||||
{
|
||||
ULONG i;
|
||||
int j;
|
||||
int nbytes;
|
||||
int nbits;
|
||||
bool retval;
|
||||
char *block_bitmap = fs->block_map->bitmap;
|
||||
char *bitmap_block = NULL;
|
||||
ULONG blk;
|
||||
|
||||
if (!block_bitmap)
|
||||
return false;
|
||||
|
||||
nbytes = EXT2_BLOCKS_PER_GROUP(fs->ext2_sb) / 8;
|
||||
|
||||
bitmap_block = (char *)RtlAllocateHeap(GetProcessHeap(), 0, fs->blocksize);
|
||||
if (!bitmap_block)
|
||||
return false;
|
||||
|
||||
memset(bitmap_block, 0xff, fs->blocksize);
|
||||
|
||||
for (i = 0; i < fs->group_desc_count; i++)
|
||||
{
|
||||
memcpy(bitmap_block, block_bitmap, nbytes);
|
||||
|
||||
if (i == fs->group_desc_count - 1)
|
||||
{
|
||||
/* Force bitmap padding for the last group */
|
||||
nbits = (int) ((fs->ext2_sb->s_blocks_count
|
||||
- fs->ext2_sb->s_first_data_block)
|
||||
% EXT2_BLOCKS_PER_GROUP(fs->ext2_sb));
|
||||
|
||||
if (nbits)
|
||||
{
|
||||
for (j = nbits; j < fs->blocksize * 8; j++)
|
||||
{
|
||||
ext2_set_bit(j, bitmap_block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blk = fs->group_desc[i].bg_block_bitmap;
|
||||
|
||||
if (blk)
|
||||
{
|
||||
#ifdef EXT2_BIG_ENDIAN_BITMAPS
|
||||
if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
|
||||
(fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
|
||||
ext2_swap_bitmap(fs, bitmap_block, nbytes);
|
||||
#endif
|
||||
retval = NT_SUCCESS(Ext2WriteDisk(
|
||||
fs,
|
||||
((ULONGLONG)blk * fs->blocksize),
|
||||
fs->blocksize,
|
||||
(unsigned char *)bitmap_block));
|
||||
|
||||
if (!retval)
|
||||
{
|
||||
RtlFreeHeap(GetProcessHeap(), 0, bitmap_block);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
block_bitmap += nbytes;
|
||||
}
|
||||
|
||||
RtlFreeHeap(GetProcessHeap(), 0, bitmap_block);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ext2_write_bitmaps(PEXT2_FILESYS fs)
|
||||
{
|
||||
bool retval;
|
||||
|
||||
if (fs->block_map) // && ext2fs_test_bb_dirty(fs))
|
||||
{
|
||||
retval = ext2_write_block_bitmap(fs);
|
||||
if (!retval)
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (fs->inode_map) // && ext2fs_test_ib_dirty(fs))
|
||||
{
|
||||
retval = ext2_write_inode_bitmap(fs);
|
||||
if (!retval)
|
||||
return retval;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool read_bitmaps(PEXT2_FILESYS fs, int do_inode, int do_block)
|
||||
{
|
||||
ULONG i;
|
||||
char *block_bitmap = 0, *inode_bitmap = 0;
|
||||
bool retval = false;
|
||||
ULONG block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->ext2_sb) / 8;
|
||||
ULONG inode_nbytes = EXT2_INODES_PER_GROUP(fs->ext2_sb) / 8;
|
||||
ULONG blk;
|
||||
|
||||
// fs->write_bitmaps = ext2_write_bitmaps;
|
||||
|
||||
if (do_block)
|
||||
{
|
||||
if (fs->block_map)
|
||||
ext2_free_block_bitmap(fs);
|
||||
|
||||
retval = ext2_allocate_block_bitmap(fs);
|
||||
|
||||
if (!retval)
|
||||
goto cleanup;
|
||||
|
||||
block_bitmap = fs->block_map->bitmap;
|
||||
}
|
||||
|
||||
if (do_inode)
|
||||
{
|
||||
if (fs->inode_map)
|
||||
ext2_free_inode_bitmap(fs);
|
||||
|
||||
retval = ext2_allocate_inode_bitmap(fs);
|
||||
if (!retval)
|
||||
goto cleanup;
|
||||
|
||||
inode_bitmap = fs->inode_map->bitmap;
|
||||
}
|
||||
|
||||
for (i = 0; i < fs->group_desc_count; i++)
|
||||
{
|
||||
if (block_bitmap)
|
||||
{
|
||||
blk = fs->group_desc[i].bg_block_bitmap;
|
||||
|
||||
if (blk)
|
||||
{
|
||||
retval = NT_SUCCESS(Ext2ReadDisk(
|
||||
fs,
|
||||
((ULONGLONG)blk * fs->blocksize),
|
||||
block_nbytes,
|
||||
(unsigned char *) block_bitmap));
|
||||
|
||||
if (!retval)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
#ifdef EXT2_BIG_ENDIAN_BITMAPS
|
||||
if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
|
||||
(fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
|
||||
ext2_swap_bitmap(fs, block_bitmap, block_nbytes);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(block_bitmap, 0, block_nbytes);
|
||||
}
|
||||
|
||||
block_bitmap += block_nbytes;
|
||||
}
|
||||
|
||||
if (inode_bitmap)
|
||||
{
|
||||
blk = fs->group_desc[i].bg_inode_bitmap;
|
||||
if (blk)
|
||||
{
|
||||
retval = NT_SUCCESS(Ext2ReadDisk(
|
||||
fs, ((LONGLONG)blk * fs->blocksize),
|
||||
inode_nbytes,
|
||||
(unsigned char *)inode_bitmap));
|
||||
|
||||
if (!retval)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
#ifdef EXT2_BIG_ENDIAN_BITMAPS
|
||||
if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
|
||||
(fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
|
||||
ext2_swap_bitmap(fs, inode_bitmap, inode_nbytes);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(inode_bitmap, 0, inode_nbytes);
|
||||
}
|
||||
|
||||
inode_bitmap += inode_nbytes;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
cleanup:
|
||||
|
||||
if (do_block)
|
||||
{
|
||||
RtlFreeHeap(GetProcessHeap(), 0, fs->block_map);
|
||||
fs->block_map = NULL;
|
||||
}
|
||||
|
||||
if (do_inode)
|
||||
{
|
||||
RtlFreeHeap(GetProcessHeap(), 0, fs->inode_map);
|
||||
fs->inode_map = 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ext2_read_inode_bitmap (PEXT2_FILESYS fs)
|
||||
{
|
||||
return read_bitmaps(fs, 1, 0);
|
||||
}
|
||||
|
||||
bool ext2_read_block_bitmap(PEXT2_FILESYS fs)
|
||||
{
|
||||
return read_bitmaps(fs, 0, 1);
|
||||
}
|
||||
|
||||
bool ext2_read_bitmaps(PEXT2_FILESYS fs)
|
||||
{
|
||||
|
||||
if (fs->inode_map && fs->block_map)
|
||||
return 0;
|
||||
|
||||
return read_bitmaps(fs, !fs->inode_map, !fs->block_map);
|
||||
}
|
||||
|
12
reactos/lib/fslib/ext2lib/Bitmap.h
Normal file
12
reactos/lib/fslib/ext2lib/Bitmap.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef _BITMAP_H
|
||||
|
||||
#include "time.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "windows.h"
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // _BITMAP_H
|
1352
reactos/lib/fslib/ext2lib/Disk.c
Normal file
1352
reactos/lib/fslib/ext2lib/Disk.c
Normal file
File diff suppressed because it is too large
Load diff
19
reactos/lib/fslib/ext2lib/Disk.h
Normal file
19
reactos/lib/fslib/ext2lib/Disk.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* PROJECT: Mke2fs
|
||||
* FILE: Disk.h
|
||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||
* HOMEPAGE: http://ext2.yeah.net
|
||||
*/
|
||||
|
||||
#ifndef _DISK_H_
|
||||
#define _DISK_H_
|
||||
|
||||
/* INCLUDES **************************************************************/
|
||||
|
||||
#include "Stdafx.h"
|
||||
|
||||
/* DEFINITIONS ***********************************************************/
|
||||
|
||||
|
||||
|
||||
#endif /* _DISK_H_ */
|
68
reactos/lib/fslib/ext2lib/Group.c
Normal file
68
reactos/lib/fslib/ext2lib/Group.c
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* PROJECT: Mke2fs
|
||||
* FILE: Group.c
|
||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||
* HOMEPAGE: http://ext2.yeah.net
|
||||
*/
|
||||
|
||||
/* INCLUDES **************************************************************/
|
||||
|
||||
#include "Mke2fs.h"
|
||||
|
||||
/* DEFINITIONS ***********************************************************/
|
||||
|
||||
/* FUNCTIONS *************************************************************/
|
||||
|
||||
int test_root(int a, int b)
|
||||
{
|
||||
if (a == 0)
|
||||
return 1;
|
||||
while (1)
|
||||
{
|
||||
if (a == 1)
|
||||
return 1;
|
||||
if (a % b)
|
||||
return 0;
|
||||
a = a / b;
|
||||
}
|
||||
}
|
||||
|
||||
bool ext2_bg_has_super(PEXT2_SUPER_BLOCK pExt2Sb, int group_block)
|
||||
{
|
||||
if (!(pExt2Sb->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
|
||||
return true;
|
||||
|
||||
if (test_root(group_block, 3) || (test_root(group_block, 5)) ||
|
||||
test_root(group_block, 7))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool ext2_allocate_group_desc(PEXT2_FILESYS Ext2Sys)
|
||||
{
|
||||
ULONG size;
|
||||
|
||||
size = Ext2Sys->desc_blocks * Ext2Sys->blocksize;
|
||||
|
||||
Ext2Sys->group_desc =
|
||||
(PEXT2_GROUP_DESC)RtlAllocateHeap(GetProcessHeap(), 0, size);
|
||||
|
||||
if (Ext2Sys->group_desc)
|
||||
{
|
||||
memset(Ext2Sys->group_desc, 0, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ext2_free_group_desc(PEXT2_FILESYS Ext2Sys)
|
||||
{
|
||||
if (Ext2Sys->group_desc)
|
||||
{
|
||||
RtlFreeHeap(GetProcessHeap(), 0, Ext2Sys->group_desc);
|
||||
Ext2Sys->group_desc = NULL;
|
||||
}
|
||||
}
|
697
reactos/lib/fslib/ext2lib/Inode.c
Normal file
697
reactos/lib/fslib/ext2lib/Inode.c
Normal file
|
@ -0,0 +1,697 @@
|
|||
/*
|
||||
* PROJECT: Mke2fs
|
||||
* FILE: Inode.c
|
||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||
* HOMEPAGE: http://ext2.yeah.net
|
||||
*/
|
||||
|
||||
/* INCLUDES **************************************************************/
|
||||
|
||||
#include "Mke2fs.h"
|
||||
|
||||
/* DEFINITIONS ***********************************************************/
|
||||
|
||||
extern char *device_name;
|
||||
|
||||
/* FUNCTIONS *************************************************************/
|
||||
|
||||
|
||||
bool ext2_get_inode_lba(PEXT2_FILESYS Ext2Sys, ULONG no, LONGLONG *offset)
|
||||
{
|
||||
LONGLONG loc = 0;
|
||||
PEXT2_SUPER_BLOCK pExt2Sb = Ext2Sys->ext2_sb;
|
||||
|
||||
if (no < 1 || no > pExt2Sb->s_inodes_count)
|
||||
{
|
||||
KdPrint(("Mke2fs: Inode value %lu was out of range in load_inode.(1-%ld)\n",
|
||||
no, pExt2Sb->s_inodes_count));
|
||||
*offset = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
loc = (LONGLONG)(Ext2Sys->blocksize) * Ext2Sys->group_desc[(no - 1) / pExt2Sb->s_inodes_per_group].bg_inode_table +
|
||||
((no - 1) % pExt2Sb->s_inodes_per_group) * sizeof(EXT2_INODE);
|
||||
|
||||
*offset = loc;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ext2_load_inode(PEXT2_FILESYS Ext2Sys, ULONG no, PEXT2_INODE pInode)
|
||||
{
|
||||
LONGLONG Offset;
|
||||
bool bRet = false;
|
||||
|
||||
if (ext2_get_inode_lba(Ext2Sys, no, &Offset))
|
||||
{
|
||||
bRet = NT_SUCCESS(Ext2ReadDisk(
|
||||
Ext2Sys,
|
||||
Offset,
|
||||
sizeof(EXT2_INODE),
|
||||
(unsigned char *)pInode));
|
||||
}
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
||||
bool ext2_save_inode(PEXT2_FILESYS Ext2Sys, ULONG no, PEXT2_INODE pInode)
|
||||
{
|
||||
LONGLONG offset;
|
||||
bool bRet = false;
|
||||
|
||||
if (ext2_get_inode_lba(Ext2Sys, no, &offset))
|
||||
{
|
||||
bRet = NT_SUCCESS(Ext2WriteDisk(
|
||||
Ext2Sys,
|
||||
offset,
|
||||
sizeof(EXT2_INODE),
|
||||
(unsigned char *)pInode));
|
||||
}
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Right now, just search forward from the parent directory's block
|
||||
* group to find the next free inode.
|
||||
*
|
||||
* Should have a special policy for directories.
|
||||
*/
|
||||
|
||||
bool ext2_new_inode(PEXT2_FILESYS fs, ULONG dir, int mode,
|
||||
PEXT2_INODE_BITMAP map, ULONG *ret)
|
||||
{
|
||||
ULONG dir_group = 0;
|
||||
ULONG i;
|
||||
ULONG start_inode;
|
||||
|
||||
if (!map)
|
||||
map = fs->inode_map;
|
||||
|
||||
if (!map)
|
||||
return false;
|
||||
|
||||
if (dir > 0)
|
||||
dir_group = (dir - 1) / EXT2_INODES_PER_GROUP(fs->ext2_sb);
|
||||
|
||||
start_inode = (dir_group * EXT2_INODES_PER_GROUP(fs->ext2_sb)) + 1;
|
||||
|
||||
if (start_inode < EXT2_FIRST_INODE(fs->ext2_sb))
|
||||
start_inode = EXT2_FIRST_INODE(fs->ext2_sb);
|
||||
|
||||
i = start_inode;
|
||||
|
||||
do
|
||||
{
|
||||
if (!ext2_test_inode_bitmap(map, i))
|
||||
break;
|
||||
|
||||
i++;
|
||||
|
||||
if (i > fs->ext2_sb->s_inodes_count)
|
||||
i = EXT2_FIRST_INODE(fs->ext2_sb);
|
||||
|
||||
} while (i != start_inode);
|
||||
|
||||
if (ext2_test_inode_bitmap(map, i))
|
||||
return false;
|
||||
|
||||
*ret = i;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ext2_expand_block( PEXT2_FILESYS Ext2Sys, PEXT2_INODE Inode,
|
||||
ULONG dwContent, ULONG Index, int layer,
|
||||
ULONG newBlk, ULONG *dwRet, ULONG *off )
|
||||
{
|
||||
ULONG *pData = NULL;
|
||||
ULONG i = 0, j = 0, temp = 1;
|
||||
ULONG dwBlk;
|
||||
ULONG dwNewBlk = newBlk;
|
||||
bool bDirty = false;
|
||||
bool bRet = true;
|
||||
ULONG Offset = 0;
|
||||
|
||||
PEXT2_SUPER_BLOCK pExt2Sb = Ext2Sys->ext2_sb;
|
||||
|
||||
pData = (ULONG *)RtlAllocateHeap(GetProcessHeap(), 0, Ext2Sys->blocksize);
|
||||
|
||||
if (!pData)
|
||||
{
|
||||
bRet = false;
|
||||
goto errorout;
|
||||
}
|
||||
|
||||
if (!ext2_read_block(Ext2Sys, dwContent, (void *)pData))
|
||||
{
|
||||
bRet = false;
|
||||
goto errorout;
|
||||
}
|
||||
|
||||
if (layer == 1)
|
||||
{
|
||||
*dwRet = dwContent;
|
||||
*off = Index;
|
||||
pData[Index] = newBlk;
|
||||
|
||||
bDirty = TRUE;
|
||||
}
|
||||
else if (layer <= 3)
|
||||
{
|
||||
temp = 1 << ((10 + pExt2Sb->s_log_block_size - 2) * (layer - 1));
|
||||
|
||||
i = Index / temp;
|
||||
j = Index % temp;
|
||||
|
||||
dwBlk = pData[i];
|
||||
|
||||
if (dwBlk == 0)
|
||||
{
|
||||
if (ext2_alloc_block(Ext2Sys, 0, &dwBlk) )
|
||||
{
|
||||
pData[i] = dwBlk;
|
||||
bDirty = true;
|
||||
|
||||
Inode->i_blocks += (Ext2Sys->blocksize / SECTOR_SIZE);
|
||||
}
|
||||
|
||||
if (!bDirty)
|
||||
goto errorout;
|
||||
}
|
||||
|
||||
if (!ext2_expand_block(Ext2Sys, Inode, dwBlk, j, layer - 1, bDirty, &dwNewBlk, &Offset))
|
||||
{
|
||||
bRet = false;
|
||||
KdPrint(("Mke2fs: ext2_expand_block: ... error recuise...\n"));
|
||||
goto errorout;
|
||||
}
|
||||
}
|
||||
|
||||
if (bDirty)
|
||||
{
|
||||
bRet = ext2_write_block(Ext2Sys, dwContent, (void *)pData);
|
||||
}
|
||||
|
||||
|
||||
errorout:
|
||||
|
||||
if (pData)
|
||||
RtlFreeHeap(GetProcessHeap(), 0, pData);
|
||||
|
||||
if (bRet && dwRet)
|
||||
*dwRet = dwNewBlk;
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
bool ext2_expand_inode( PEXT2_FILESYS Ext2Sys,
|
||||
PEXT2_INODE Inode,
|
||||
ULONG newBlk )
|
||||
{
|
||||
ULONG dwSizes[4] = {12, 1, 1, 1};
|
||||
ULONG Index = 0;
|
||||
ULONG dwTotal = 0;
|
||||
ULONG dwBlk = 0, dwNewBlk = 0, Offset = 0;
|
||||
PEXT2_SUPER_BLOCK pExt2Sb = Ext2Sys->ext2_sb;
|
||||
int i = 0;
|
||||
bool bRet = true;
|
||||
bool bDirty = false;
|
||||
ULONG TotalBlocks;
|
||||
|
||||
TotalBlocks = Inode->i_blocks / (Ext2Sys->blocksize / SECTOR_SIZE);
|
||||
Index = Ext2DataBlocks(Ext2Sys, TotalBlocks);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
dwSizes[i] = dwSizes[i] << ((10 + pExt2Sb->s_log_block_size - 2) * i);
|
||||
dwTotal += dwSizes[i];
|
||||
}
|
||||
|
||||
if (Index >= dwTotal)
|
||||
{
|
||||
KdPrint(("Mke2fs: ext2_expand_inode: beyond the maxinum size of an inode.\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (Index < dwSizes[i])
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
Inode->i_block[Index] = newBlk;
|
||||
bDirty = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
dwBlk = Inode->i_block[(i + 12 - 1)];
|
||||
|
||||
if (dwBlk == 0)
|
||||
{
|
||||
if (ext2_alloc_block(Ext2Sys, 0, &dwBlk))
|
||||
{
|
||||
Inode->i_block[(i + 12 - 1)] = dwBlk;
|
||||
bDirty = true;
|
||||
|
||||
Inode->i_blocks += (Ext2Sys->blocksize / SECTOR_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dwNewBlk = 0;
|
||||
bRet = ext2_expand_block(
|
||||
Ext2Sys,
|
||||
Inode,
|
||||
dwBlk,
|
||||
Index,
|
||||
i,
|
||||
newBlk,
|
||||
&dwNewBlk,
|
||||
&Offset );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Index -= dwSizes[i];
|
||||
}
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
||||
bool ext2_get_block(PEXT2_FILESYS Ext2Sys, ULONG dwContent, ULONG Index, int layer, ULONG *dwRet)
|
||||
{
|
||||
ULONG *pData = NULL;
|
||||
LONGLONG Offset = 0;
|
||||
ULONG i = 0, j = 0, temp = 1;
|
||||
ULONG dwBlk = 0;
|
||||
bool bRet = true;
|
||||
|
||||
PEXT2_SUPER_BLOCK pExt2Sb = Ext2Sys->ext2_sb;
|
||||
|
||||
Offset = (LONGLONG) dwContent;
|
||||
Offset = Offset * Ext2Sys->blocksize;
|
||||
|
||||
pData = (ULONG *)RtlAllocateHeap(GetProcessHeap(), 0, Ext2Sys->blocksize);
|
||||
|
||||
if (!pData)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
memset(pData, 0, Ext2Sys->blocksize);
|
||||
|
||||
if (layer == 0)
|
||||
{
|
||||
dwBlk = dwContent;
|
||||
}
|
||||
else if (layer <= 3)
|
||||
{
|
||||
|
||||
if (!ext2_read_block(Ext2Sys, dwContent, (void *)pData))
|
||||
{
|
||||
bRet = false;
|
||||
goto errorout;
|
||||
}
|
||||
|
||||
temp = 1 << ((10 + pExt2Sb->s_log_block_size - 2) * (layer - 1));
|
||||
|
||||
i = Index / temp;
|
||||
j = Index % temp;
|
||||
|
||||
if (!ext2_get_block(Ext2Sys, pData[i], j, layer - 1, &dwBlk))
|
||||
{
|
||||
bRet = false;
|
||||
KdPrint(("Mke2fs: ext2_get_block: ... error recuise...\n"));
|
||||
goto errorout;
|
||||
}
|
||||
}
|
||||
|
||||
errorout:
|
||||
|
||||
if (pData)
|
||||
RtlFreeHeap(GetProcessHeap(), 0, pData);
|
||||
|
||||
if (bRet && dwRet)
|
||||
*dwRet = dwBlk;
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
bool ext2_block_map(PEXT2_FILESYS Ext2Sys, PEXT2_INODE inode, ULONG block, ULONG *dwRet)
|
||||
{
|
||||
ULONG dwSizes[4] = {12, 1, 1, 1};
|
||||
ULONG Index = 0;
|
||||
ULONG dwBlk = 0;
|
||||
PEXT2_SUPER_BLOCK pExt2Sb = Ext2Sys->ext2_sb;
|
||||
int i;
|
||||
bool bRet = false;
|
||||
|
||||
Index = block;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
dwSizes[i] = dwSizes[i] << ((10 + pExt2Sb->s_log_block_size - 2) * i);
|
||||
}
|
||||
|
||||
if (Index >= inode->i_blocks / (Ext2Sys->blocksize / SECTOR_SIZE))
|
||||
{
|
||||
KdPrint(("Mke2fs: ext2_block_map: beyond the size of the inode.\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (Index < dwSizes[i])
|
||||
{
|
||||
dwBlk = inode->i_block[i==0 ? (Index):(i + 12 - 1)];
|
||||
|
||||
bRet = ext2_get_block(Ext2Sys, dwBlk, Index , i, &dwBlk);
|
||||
|
||||
break;
|
||||
}
|
||||
Index -= dwSizes[i];
|
||||
}
|
||||
|
||||
if (bRet && dwBlk)
|
||||
{
|
||||
if (dwRet)
|
||||
*dwRet = dwBlk;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
ULONG ext2_build_bdl(PEXT2_FILESYS Ext2Sys,
|
||||
PEXT2_INODE ext2_inode,
|
||||
IN ULONG offset,
|
||||
IN ULONG size,
|
||||
OUT PEXT2_BDL *ext2_bdl )
|
||||
{
|
||||
ULONG nBeg, nEnd, nBlocks;
|
||||
ULONG dwBlk;
|
||||
ULONG i;
|
||||
ULONG dwBytes = 0;
|
||||
LONGLONG lba;
|
||||
|
||||
PEXT2_BDL ext2bdl = NULL;
|
||||
|
||||
*ext2_bdl = NULL;
|
||||
|
||||
if (offset >= ext2_inode->i_size)
|
||||
{
|
||||
KdPrint(("Mke2fs: ext2_build_bdl: beyond the file range.\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
if (offset + size > ext2_inode->i_size)
|
||||
{
|
||||
size = ext2_inode->i_size - offset;
|
||||
}
|
||||
*/
|
||||
|
||||
nBeg = offset / Ext2Sys->blocksize;
|
||||
nEnd = (size + offset + Ext2Sys->blocksize - 1) / Ext2Sys->blocksize;
|
||||
|
||||
nBlocks = nEnd - nBeg;
|
||||
|
||||
if (nBlocks > 0)
|
||||
{
|
||||
ext2bdl = (PEXT2_BDL)
|
||||
RtlAllocateHeap(GetProcessHeap(), 0, sizeof(EXT2_BDL) * nBlocks);
|
||||
|
||||
if (ext2bdl)
|
||||
{
|
||||
|
||||
memset(ext2bdl, 0, sizeof(EXT2_BDL) * nBlocks);
|
||||
|
||||
for (i = nBeg; i < nEnd; i++)
|
||||
{
|
||||
if (!ext2_block_map(Ext2Sys, ext2_inode, i, &dwBlk))
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
lba = (LONGLONG) dwBlk;
|
||||
lba = lba * Ext2Sys->blocksize;
|
||||
|
||||
if (nBlocks == 1) // ie. (nBeg == nEnd - 1)
|
||||
{
|
||||
dwBytes = size;
|
||||
ext2bdl[i - nBeg].Lba = lba + (LONGLONG)(offset % (Ext2Sys->blocksize));
|
||||
ext2bdl[i - nBeg].Length = dwBytes;
|
||||
ext2bdl[i - nBeg].Offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i == nBeg)
|
||||
{
|
||||
dwBytes = Ext2Sys->blocksize - (offset % (Ext2Sys->blocksize));
|
||||
ext2bdl[i - nBeg].Lba = lba + (LONGLONG)(offset % (Ext2Sys->blocksize));
|
||||
ext2bdl[i - nBeg].Length = dwBytes;
|
||||
ext2bdl[i - nBeg].Offset = 0;
|
||||
}
|
||||
else if (i == nEnd - 1)
|
||||
{
|
||||
ext2bdl[i - nBeg].Lba = lba;
|
||||
ext2bdl[i - nBeg].Length = size - dwBytes;
|
||||
ext2bdl[i - nBeg].Offset = dwBytes;
|
||||
dwBytes = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
ext2bdl[i - nBeg].Lba = lba;
|
||||
ext2bdl[i - nBeg].Length = Ext2Sys->blocksize;
|
||||
ext2bdl[i - nBeg].Offset = dwBytes;
|
||||
dwBytes += Ext2Sys->blocksize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*ext2_bdl = ext2bdl;
|
||||
return nBlocks;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
|
||||
if (ext2bdl)
|
||||
RtlFreeHeap(GetProcessHeap(), 0, ext2bdl);
|
||||
|
||||
// Error
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool ext2_read_inode(PEXT2_FILESYS Ext2Sys,
|
||||
ULONG ino,
|
||||
ULONG offset,
|
||||
PVOID Buffer,
|
||||
ULONG size,
|
||||
PULONG dwReturn)
|
||||
{
|
||||
PEXT2_BDL ext2_bdl = NULL;
|
||||
ULONG blocks, i;
|
||||
bool bRet = true;
|
||||
EXT2_INODE ext2_inode;
|
||||
ULONG dwTotal = 0;
|
||||
|
||||
if (!ext2_load_inode(Ext2Sys, ino, &ext2_inode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
blocks = ext2_build_bdl(Ext2Sys, &ext2_inode, offset, size, &ext2_bdl);
|
||||
|
||||
if (blocks <= 0)
|
||||
return false;
|
||||
|
||||
|
||||
for(i = 0; i < blocks; i++)
|
||||
{
|
||||
bRet = NT_SUCCESS(Ext2ReadDisk(
|
||||
Ext2Sys,
|
||||
ext2_bdl[i].Lba,
|
||||
ext2_bdl[i].Length,
|
||||
(PUCHAR)Buffer + ext2_bdl[i].Offset
|
||||
));
|
||||
|
||||
if (!bRet)
|
||||
break;
|
||||
dwTotal += ext2_bdl[i].Length;
|
||||
}
|
||||
|
||||
*dwReturn = dwTotal;
|
||||
|
||||
if (ext2_bdl)
|
||||
RtlFreeHeap(GetProcessHeap(), 0, ext2_bdl);
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
||||
bool ext2_write_inode (PEXT2_FILESYS Ext2Sys,
|
||||
ULONG ino,
|
||||
ULONG offset,
|
||||
PVOID Buffer,
|
||||
ULONG size,
|
||||
PULONG dwReturn )
|
||||
{
|
||||
PEXT2_BDL ext2_bdl = NULL;
|
||||
ULONG blocks, i;
|
||||
bool bRet = true;
|
||||
EXT2_INODE inode;
|
||||
ULONG dwTotal = 0;
|
||||
ULONG dwBlk = 0;
|
||||
ULONG TotalBlks;
|
||||
|
||||
blocks = (size + offset + Ext2Sys->blocksize - 1) / Ext2Sys->blocksize;
|
||||
|
||||
if (!ext2_load_inode(Ext2Sys, ino, &inode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TotalBlks = inode.i_blocks / (Ext2Sys->blocksize / SECTOR_SIZE);
|
||||
TotalBlks = Ext2DataBlocks(Ext2Sys, TotalBlks);
|
||||
|
||||
if (blocks > TotalBlks)
|
||||
{
|
||||
for (i=0; i < (blocks - TotalBlks); i++)
|
||||
{
|
||||
if (ext2_alloc_block(Ext2Sys, 0, &dwBlk) )
|
||||
{
|
||||
ext2_expand_inode(Ext2Sys, &inode, dwBlk);
|
||||
inode.i_blocks += (Ext2Sys->blocksize/SECTOR_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blocks = ext2_build_bdl(Ext2Sys, &inode, offset, size, &ext2_bdl);
|
||||
|
||||
if (blocks <= 0)
|
||||
return false;
|
||||
|
||||
for(i = 0; i < blocks; i++)
|
||||
{
|
||||
bRet = NT_SUCCESS(Ext2WriteDisk(
|
||||
Ext2Sys,
|
||||
ext2_bdl[i].Lba,
|
||||
ext2_bdl[i].Length,
|
||||
(PUCHAR)Buffer + ext2_bdl[i].Offset
|
||||
));
|
||||
|
||||
if (!bRet)
|
||||
{
|
||||
goto errorout;
|
||||
}
|
||||
|
||||
dwTotal += ext2_bdl[i].Length;
|
||||
}
|
||||
|
||||
*dwReturn = dwTotal;
|
||||
|
||||
if (size + offset > inode.i_size)
|
||||
{
|
||||
inode.i_size = size + offset;
|
||||
}
|
||||
|
||||
ext2_save_inode(Ext2Sys, ino, &inode);
|
||||
|
||||
|
||||
errorout:
|
||||
|
||||
if (ext2_bdl)
|
||||
RtlFreeHeap(GetProcessHeap(), 0, ext2_bdl);
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
bool
|
||||
ext2_add_entry( PEXT2_FILESYS Ext2Sys,
|
||||
ULONG parent, ULONG inode,
|
||||
int filetype, char *name )
|
||||
{
|
||||
PEXT2_DIR_ENTRY2 dir = NULL, newdir = NULL;
|
||||
EXT2_INODE parent_inode;
|
||||
ULONG dwRet;
|
||||
char *buf;
|
||||
int rec_len;
|
||||
bool bRet = false;
|
||||
|
||||
rec_len = EXT2_DIR_REC_LEN(strlen(name));
|
||||
|
||||
if (!ext2_load_inode(Ext2Sys, parent, &parent_inode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
buf = (char *)RtlAllocateHeap(GetProcessHeap(), 0, parent_inode.i_size);
|
||||
|
||||
if (!ext2_read_inode(Ext2Sys, parent, 0, buf, parent_inode.i_size, &dwRet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
dir = (PEXT2_DIR_ENTRY2) buf;
|
||||
|
||||
while ((char *)dir < buf + parent_inode.i_size)
|
||||
{
|
||||
if ((dir->inode == 0 && dir->rec_len >= rec_len) ||
|
||||
(dir->rec_len >= dir->name_len + rec_len) )
|
||||
{
|
||||
if (dir->inode)
|
||||
{
|
||||
newdir = (PEXT2_DIR_ENTRY2) ((PUCHAR)dir + EXT2_DIR_REC_LEN(dir->name_len));
|
||||
newdir->rec_len = dir->rec_len - EXT2_DIR_REC_LEN(dir->name_len);
|
||||
|
||||
dir->rec_len = EXT2_DIR_REC_LEN(dir->name_len);
|
||||
|
||||
dir = newdir;
|
||||
}
|
||||
|
||||
dir->file_type = filetype;
|
||||
dir->inode = inode;
|
||||
dir->name_len = strlen(name);
|
||||
memcpy(dir->name, name, strlen(name));
|
||||
|
||||
bRet = true;
|
||||
break;
|
||||
}
|
||||
|
||||
dir = (PEXT2_DIR_ENTRY2) (dir->rec_len + (PUCHAR) dir);
|
||||
}
|
||||
|
||||
|
||||
if (bRet)
|
||||
return ext2_write_inode(Ext2Sys, parent, 0, buf, parent_inode.i_size, &dwRet);
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
||||
bool ext2_reserve_inodes(PEXT2_FILESYS fs)
|
||||
{
|
||||
ULONG i;
|
||||
int group;
|
||||
|
||||
for (i = EXT2_ROOT_INO + 1; i < EXT2_FIRST_INODE(fs->ext2_sb); i++)
|
||||
{
|
||||
ext2_mark_inode_bitmap(fs->inode_map, i);
|
||||
group = ext2_group_of_ino(fs, i);
|
||||
fs->group_desc[group].bg_free_inodes_count--;
|
||||
fs->ext2_sb->s_free_inodes_count--;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
416
reactos/lib/fslib/ext2lib/Memory.c
Normal file
416
reactos/lib/fslib/ext2lib/Memory.c
Normal file
|
@ -0,0 +1,416 @@
|
|||
/*
|
||||
* PROJECT: Mke2fs
|
||||
* FILE: Memory.c
|
||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||
* HOMEPAGE: http://ext2.yeah.net
|
||||
*/
|
||||
|
||||
/* INCLUDES **************************************************************/
|
||||
|
||||
#include "Mke2fs.h"
|
||||
|
||||
/* DEFINITIONS ***********************************************************/
|
||||
|
||||
extern char *device_name;
|
||||
|
||||
/* FUNCTIONS *************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* Return the group # of an inode number
|
||||
*/
|
||||
int ext2_group_of_ino(PEXT2_FILESYS fs, ULONG ino)
|
||||
{
|
||||
return (ino - 1) / fs->ext2_sb->s_inodes_per_group;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the group # of a block
|
||||
*/
|
||||
int ext2_group_of_blk(PEXT2_FILESYS fs, ULONG blk)
|
||||
{
|
||||
return (blk - fs->ext2_sb->s_first_data_block) /
|
||||
fs->ext2_sb->s_blocks_per_group;
|
||||
}
|
||||
|
||||
void ext2_inode_alloc_stats2(PEXT2_FILESYS fs, ULONG ino,
|
||||
int inuse, int isdir)
|
||||
{
|
||||
int group = ext2_group_of_ino(fs, ino);
|
||||
|
||||
if (inuse > 0)
|
||||
ext2_mark_inode_bitmap(fs->inode_map, ino);
|
||||
else
|
||||
ext2_unmark_inode_bitmap(fs->inode_map, ino);
|
||||
|
||||
fs->group_desc[group].bg_free_inodes_count -= inuse;
|
||||
|
||||
if (isdir)
|
||||
fs->group_desc[group].bg_used_dirs_count += inuse;
|
||||
|
||||
fs->ext2_sb->s_free_inodes_count -= inuse;
|
||||
}
|
||||
|
||||
|
||||
void ext2_inode_alloc_stats(PEXT2_FILESYS fs, ULONG ino, int inuse)
|
||||
{
|
||||
ext2_inode_alloc_stats2(fs, ino, inuse, 0);
|
||||
}
|
||||
|
||||
void ext2_block_alloc_stats(PEXT2_FILESYS fs, ULONG blk, int inuse)
|
||||
{
|
||||
int group = ext2_group_of_blk(fs, blk);
|
||||
|
||||
if (inuse > 0)
|
||||
ext2_mark_block_bitmap(fs->block_map, blk);
|
||||
else
|
||||
ext2_unmark_block_bitmap(fs->block_map, blk);
|
||||
|
||||
fs->group_desc[group].bg_free_blocks_count -= inuse;
|
||||
fs->ext2_sb->s_free_blocks_count -= inuse;
|
||||
}
|
||||
|
||||
|
||||
bool ext2_allocate_tables(PEXT2_FILESYS Ext2Sys)
|
||||
{
|
||||
bool retval;
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < Ext2Sys->group_desc_count; i++)
|
||||
{
|
||||
retval = ext2_allocate_group_table(Ext2Sys, i, Ext2Sys->block_map);
|
||||
|
||||
if (!retval)
|
||||
return retval;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ext2_allocate_group_table(PEXT2_FILESYS fs, ULONG group,
|
||||
PEXT2_BLOCK_BITMAP bmap)
|
||||
{
|
||||
bool retval;
|
||||
ULONG group_blk, start_blk, last_blk, new_blk, blk;
|
||||
int j;
|
||||
|
||||
group_blk = fs->ext2_sb->s_first_data_block +
|
||||
(group * fs->ext2_sb->s_blocks_per_group);
|
||||
|
||||
last_blk = group_blk + fs->ext2_sb->s_blocks_per_group;
|
||||
if (last_blk >= fs->ext2_sb->s_blocks_count)
|
||||
last_blk = fs->ext2_sb->s_blocks_count - 1;
|
||||
|
||||
start_blk = group_blk + 3 + fs->desc_blocks;
|
||||
if (start_blk > last_blk)
|
||||
start_blk = group_blk;
|
||||
|
||||
if (!bmap)
|
||||
bmap = fs->block_map;
|
||||
|
||||
/*
|
||||
* Allocate the inode table
|
||||
*/
|
||||
if (!fs->group_desc[group].bg_inode_table)
|
||||
{
|
||||
retval = ext2_get_free_blocks(fs, start_blk, last_blk,
|
||||
fs->inode_blocks_per_group,
|
||||
bmap, &new_blk);
|
||||
if (!retval)
|
||||
return retval;
|
||||
|
||||
for (j=0, blk = new_blk;
|
||||
j < fs->inode_blocks_per_group;
|
||||
j++, blk++)
|
||||
ext2_mark_block_bitmap(bmap, blk);
|
||||
|
||||
fs->group_desc[group].bg_inode_table = new_blk;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate the block and inode bitmaps, if necessary
|
||||
*/
|
||||
if (fs->stride)
|
||||
{
|
||||
start_blk += fs->inode_blocks_per_group;
|
||||
start_blk += ((fs->stride * group) %
|
||||
(last_blk - start_blk));
|
||||
if (start_blk > last_blk)
|
||||
/* should never happen */
|
||||
start_blk = group_blk;
|
||||
}
|
||||
else
|
||||
{
|
||||
start_blk = group_blk;
|
||||
}
|
||||
|
||||
if (!fs->group_desc[group].bg_block_bitmap)
|
||||
{
|
||||
retval = ext2_get_free_blocks(fs, start_blk, last_blk,
|
||||
1, bmap, &new_blk);
|
||||
|
||||
if (!retval)
|
||||
retval = ext2_get_free_blocks(fs, group_blk,
|
||||
last_blk, 1, bmap, &new_blk);
|
||||
|
||||
if (!retval)
|
||||
return retval;
|
||||
|
||||
ext2_mark_block_bitmap(bmap, new_blk);
|
||||
fs->group_desc[group].bg_block_bitmap = new_blk;
|
||||
}
|
||||
|
||||
if (!fs->group_desc[group].bg_inode_bitmap)
|
||||
{
|
||||
retval = ext2_get_free_blocks(fs, start_blk, last_blk,
|
||||
1, bmap, &new_blk);
|
||||
if (!retval)
|
||||
retval = ext2_get_free_blocks(fs, group_blk,
|
||||
last_blk, 1, bmap, &new_blk);
|
||||
if (!retval)
|
||||
return retval;
|
||||
|
||||
ext2_mark_block_bitmap(bmap, new_blk);
|
||||
fs->group_desc[group].bg_inode_bitmap = new_blk;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ext2_get_free_blocks(PEXT2_FILESYS fs, ULONG start, ULONG finish,
|
||||
int num, PEXT2_BLOCK_BITMAP map, ULONG *ret)
|
||||
{
|
||||
ULONG b = start;
|
||||
|
||||
if (!map)
|
||||
map = fs->block_map;
|
||||
|
||||
if (!map)
|
||||
return false;
|
||||
|
||||
if (!b)
|
||||
b = fs->ext2_sb->s_first_data_block;
|
||||
|
||||
if (!finish)
|
||||
finish = start;
|
||||
|
||||
if (!num)
|
||||
num = 1;
|
||||
|
||||
do
|
||||
{
|
||||
if (b+num-1 > fs->ext2_sb->s_blocks_count)
|
||||
b = fs->ext2_sb->s_first_data_block;
|
||||
|
||||
if (ext2_test_block_bitmap_range(map, b, num))
|
||||
{
|
||||
*ret = b;
|
||||
return true;
|
||||
}
|
||||
|
||||
b++;
|
||||
|
||||
} while (b != finish);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool write_inode_tables(PEXT2_FILESYS fs)
|
||||
{
|
||||
bool retval;
|
||||
ULONG blk, num;
|
||||
int i;
|
||||
|
||||
for (i = 0; (ULONG)i < fs->group_desc_count; i++)
|
||||
{
|
||||
blk = fs->group_desc[i].bg_inode_table;
|
||||
num = fs->inode_blocks_per_group;
|
||||
|
||||
retval = zero_blocks(fs, blk, num, &blk, &num);
|
||||
if (!retval)
|
||||
{
|
||||
KdPrint(("\nMke2fs: Could not write %lu blocks "
|
||||
"in inode table starting at %lu.\n",
|
||||
num, blk));
|
||||
|
||||
zero_blocks(0, 0, 0, 0, 0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
zero_blocks(0, 0, 0, 0, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Stupid algorithm --- we now just search forward starting from the
|
||||
* goal. Should put in a smarter one someday....
|
||||
*/
|
||||
bool ext2_new_block(PEXT2_FILESYS fs, ULONG goal,
|
||||
PEXT2_BLOCK_BITMAP map, ULONG *ret)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
if (!map)
|
||||
map = fs->block_map;
|
||||
|
||||
if (!map)
|
||||
return false;
|
||||
|
||||
if (!goal || (goal >= fs->ext2_sb->s_blocks_count))
|
||||
goal = fs->ext2_sb->s_first_data_block;
|
||||
|
||||
i = goal;
|
||||
|
||||
do
|
||||
{
|
||||
if (!ext2_test_block_bitmap(map, i))
|
||||
{
|
||||
*ret = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
if (i >= fs->ext2_sb->s_blocks_count)
|
||||
i = fs->ext2_sb->s_first_data_block;
|
||||
|
||||
} while (i != goal);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function zeros out the allocated block, and updates all of the
|
||||
* appropriate filesystem records.
|
||||
*/
|
||||
bool ext2_alloc_block(PEXT2_FILESYS fs, ULONG goal, ULONG *ret)
|
||||
{
|
||||
bool retval;
|
||||
ULONG block;
|
||||
char *buf = NULL;
|
||||
|
||||
buf = (char *)RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, fs->blocksize);
|
||||
if (!buf)
|
||||
return false;
|
||||
|
||||
if (!fs->block_map)
|
||||
{
|
||||
retval = ext2_read_block_bitmap(fs);
|
||||
if (!retval)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
retval = ext2_new_block(fs, goal, 0, &block);
|
||||
|
||||
if (!retval)
|
||||
goto fail;
|
||||
|
||||
retval = NT_SUCCESS(Ext2WriteDisk(
|
||||
fs,
|
||||
((LONGLONG)block * fs->blocksize),
|
||||
fs->blocksize, (unsigned char *)buf));
|
||||
|
||||
if (!retval)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ext2_block_alloc_stats(fs, block, +1);
|
||||
*ret = block;
|
||||
|
||||
if (buf)
|
||||
{
|
||||
RtlFreeHeap(GetProcessHeap(), 0, buf);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
|
||||
if (buf)
|
||||
{
|
||||
RtlFreeHeap(GetProcessHeap(), 0, buf);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create new directory block
|
||||
*/
|
||||
bool ext2_new_dir_block(PEXT2_FILESYS fs, ULONG dir_ino,
|
||||
ULONG parent_ino, char **block)
|
||||
{
|
||||
PEXT2_DIR_ENTRY dir = NULL;
|
||||
char *buf;
|
||||
int rec_len;
|
||||
int filetype = 0;
|
||||
|
||||
buf = (char *)RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, fs->blocksize);
|
||||
if (!buf)
|
||||
return false;
|
||||
|
||||
dir = (PEXT2_DIR_ENTRY) buf;
|
||||
dir->rec_len = fs->blocksize;
|
||||
|
||||
if (dir_ino)
|
||||
{
|
||||
if (fs->ext2_sb->s_feature_incompat &
|
||||
EXT2_FEATURE_INCOMPAT_FILETYPE)
|
||||
filetype = EXT2_FT_DIR << 8;
|
||||
/*
|
||||
* Set up entry for '.'
|
||||
*/
|
||||
dir->inode = dir_ino;
|
||||
dir->name_len = 1 | filetype;
|
||||
dir->name[0] = '.';
|
||||
rec_len = dir->rec_len - EXT2_DIR_REC_LEN(1);
|
||||
dir->rec_len = EXT2_DIR_REC_LEN(1);
|
||||
|
||||
/*
|
||||
* Set up entry for '..'
|
||||
*/
|
||||
dir = (struct ext2_dir_entry *) (buf + dir->rec_len);
|
||||
dir->rec_len = rec_len;
|
||||
dir->inode = parent_ino;
|
||||
dir->name_len = 2 | filetype;
|
||||
dir->name[0] = '.';
|
||||
dir->name[1] = '.';
|
||||
}
|
||||
|
||||
*block = buf;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ext2_write_block(PEXT2_FILESYS fs, ULONG block, void *inbuf)
|
||||
{
|
||||
bool retval = false;
|
||||
|
||||
retval = NT_SUCCESS(Ext2WriteDisk(
|
||||
fs,
|
||||
((ULONGLONG)block * fs->blocksize),
|
||||
fs->blocksize, (unsigned char *)inbuf));
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool ext2_read_block(PEXT2_FILESYS fs, ULONG block, void *inbuf)
|
||||
{
|
||||
bool retval = false;
|
||||
|
||||
retval = NT_SUCCESS(Ext2ReadDisk(
|
||||
fs,
|
||||
((ULONGLONG)block * fs->blocksize),
|
||||
fs->blocksize, (unsigned char *)inbuf));
|
||||
|
||||
return retval;
|
||||
}
|
1010
reactos/lib/fslib/ext2lib/Mke2fs.c
Normal file
1010
reactos/lib/fslib/ext2lib/Mke2fs.c
Normal file
File diff suppressed because it is too large
Load diff
876
reactos/lib/fslib/ext2lib/Mke2fs.h
Normal file
876
reactos/lib/fslib/ext2lib/Mke2fs.h
Normal file
|
@ -0,0 +1,876 @@
|
|||
/*
|
||||
* PROJECT: Mke2fs
|
||||
* FILE: Mke2fs.h
|
||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||
* HOMEPAGE: http://ext2.yeah.net
|
||||
*/
|
||||
|
||||
#ifndef __MKE2FS__INCLUDE__
|
||||
#define __MKE2FS__INCLUDE__
|
||||
|
||||
|
||||
/* INCLUDES **************************************************************/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ntddk.h>
|
||||
#include <ntdddisk.h>
|
||||
|
||||
#include <napi/teb.h>
|
||||
|
||||
#include "time.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "ctype.h"
|
||||
|
||||
#include "types.h"
|
||||
#include "ext2_fs.h"
|
||||
|
||||
#include "getopt.h"
|
||||
|
||||
#define NTSYSAPI
|
||||
|
||||
/* DEFINITIONS ***********************************************************/
|
||||
|
||||
#define SECTOR_SIZE (Ext2Sys->DiskGeometry.BytesPerSector)
|
||||
|
||||
#ifndef GUID_DEFINED
|
||||
#define GUID_DEFINED
|
||||
typedef struct _GUID
|
||||
{
|
||||
unsigned long Data1;
|
||||
unsigned short Data2;
|
||||
unsigned short Data3;
|
||||
unsigned char Data4[8];
|
||||
} GUID;
|
||||
#endif /* GUID_DEFINED */
|
||||
|
||||
#ifndef UUID_DEFINED
|
||||
#define UUID_DEFINED
|
||||
typedef GUID UUID;
|
||||
#ifndef uuid_t
|
||||
#define uuid_t UUID
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef bool
|
||||
#define bool BOOLEAN
|
||||
#endif
|
||||
|
||||
#ifndef true
|
||||
#define true TRUE
|
||||
#endif
|
||||
|
||||
#ifndef false
|
||||
#define false FALSE
|
||||
#endif
|
||||
|
||||
|
||||
#define EXT2_CHECK_MAGIC(struct, code) \
|
||||
if ((struct)->magic != (code)) return (code)
|
||||
|
||||
/*
|
||||
* ext2fs_scan flags
|
||||
*/
|
||||
#define EXT2_SF_CHK_BADBLOCKS 0x0001
|
||||
#define EXT2_SF_BAD_INODE_BLK 0x0002
|
||||
#define EXT2_SF_BAD_EXTRA_BYTES 0x0004
|
||||
#define EXT2_SF_SKIP_MISSING_ITABLE 0x0008
|
||||
|
||||
/*
|
||||
* ext2fs_check_if_mounted flags
|
||||
*/
|
||||
#define EXT2_MF_MOUNTED 1
|
||||
#define EXT2_MF_ISROOT 2
|
||||
#define EXT2_MF_READONLY 4
|
||||
#define EXT2_MF_SWAP 8
|
||||
|
||||
/*
|
||||
* Ext2/linux mode flags. We define them here so that we don't need
|
||||
* to depend on the OS's sys/stat.h, since we may be compiling on a
|
||||
* non-Linux system.
|
||||
*/
|
||||
|
||||
#define LINUX_S_IFMT 00170000
|
||||
#define LINUX_S_IFSOCK 0140000
|
||||
#define LINUX_S_IFLNK 0120000
|
||||
#define LINUX_S_IFREG 0100000
|
||||
#define LINUX_S_IFBLK 0060000
|
||||
#define LINUX_S_IFDIR 0040000
|
||||
#define LINUX_S_IFCHR 0020000
|
||||
#define LINUX_S_IFIFO 0010000
|
||||
#define LINUX_S_ISUID 0004000
|
||||
#define LINUX_S_ISGID 0002000
|
||||
#define LINUX_S_ISVTX 0001000
|
||||
|
||||
#define LINUX_S_IRWXU 00700
|
||||
#define LINUX_S_IRUSR 00400
|
||||
#define LINUX_S_IWUSR 00200
|
||||
#define LINUX_S_IXUSR 00100
|
||||
|
||||
#define LINUX_S_IRWXG 00070
|
||||
#define LINUX_S_IRGRP 00040
|
||||
#define LINUX_S_IWGRP 00020
|
||||
#define LINUX_S_IXGRP 00010
|
||||
|
||||
#define LINUX_S_IRWXO 00007
|
||||
#define LINUX_S_IROTH 00004
|
||||
#define LINUX_S_IWOTH 00002
|
||||
#define LINUX_S_IXOTH 00001
|
||||
|
||||
#define LINUX_S_ISLNK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFLNK)
|
||||
#define LINUX_S_ISREG(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFREG)
|
||||
#define LINUX_S_ISDIR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFDIR)
|
||||
#define LINUX_S_ISCHR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFCHR)
|
||||
#define LINUX_S_ISBLK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFBLK)
|
||||
#define LINUX_S_ISFIFO(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFIFO)
|
||||
#define LINUX_S_ISSOCK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFSOCK)
|
||||
|
||||
|
||||
#define EXT2_FIRST_INODE(s) EXT2_FIRST_INO(s)
|
||||
|
||||
typedef struct _ext2fs_bitmap {
|
||||
__u32 start, end;
|
||||
__u32 real_end;
|
||||
char* bitmap;
|
||||
} EXT2_BITMAP, *PEXT2_BITMAP;
|
||||
|
||||
typedef EXT2_BITMAP EXT2_GENERIC_BITMAP, *PEXT2_GENERIC_BITMAP;
|
||||
typedef EXT2_BITMAP EXT2_INODE_BITMAP, *PEXT2_INODE_BITMAP;
|
||||
typedef EXT2_BITMAP EXT2_BLOCK_BITMAP, *PEXT2_BLOCK_BITMAP;
|
||||
|
||||
typedef struct ext2_acl_entry EXT2_ACL_ENTRY, *PEXT2_ACL_ENTRY;
|
||||
typedef struct ext2_acl_header EXT2_ACL_HEADER, *PEXT2_ACL_HEADER;
|
||||
typedef struct ext2_dir_entry EXT2_DIR_ENTRY, *PEXT2_DIR_ENTRY;
|
||||
typedef struct ext2_dir_entry_2 EXT2_DIR_ENTRY2, *PEXT2_DIR_ENTRY2;
|
||||
typedef struct ext2_dx_countlimit EXT2_DX_CL, *PEXT2_DX_CL;
|
||||
typedef struct ext2_dx_entry EXT2_DX_ENTRY, *PEXT2_DX_ENTRY;
|
||||
typedef struct ext2_dx_root_info EXT2_DX_RI, *PEXT2_DX_RI;
|
||||
typedef struct ext2_inode EXT2_INODE, *PEXT2_INODE;
|
||||
typedef struct ext2_group_desc EXT2_GROUP_DESC, *PEXT2_GROUP_DESC;
|
||||
typedef struct ext2_super_block EXT2_SUPER_BLOCK, *PEXT2_SUPER_BLOCK;
|
||||
|
||||
/*
|
||||
* Badblocks list
|
||||
*/
|
||||
struct ext2_struct_badblocks_list {
|
||||
int num;
|
||||
int size;
|
||||
ULONG *list;
|
||||
int badblocks_flags;
|
||||
};
|
||||
|
||||
typedef struct ext2_struct_badblocks_list EXT2_BADBLK_LIST, *PEXT2_BADBLK_LIST;
|
||||
|
||||
typedef struct _ext2_filesys
|
||||
{
|
||||
int flags;
|
||||
int blocksize;
|
||||
int fragsize;
|
||||
ULONG group_desc_count;
|
||||
unsigned long desc_blocks;
|
||||
PEXT2_GROUP_DESC group_desc;
|
||||
PEXT2_SUPER_BLOCK ext2_sb;
|
||||
unsigned long inode_blocks_per_group;
|
||||
PEXT2_INODE_BITMAP inode_map;
|
||||
PEXT2_BLOCK_BITMAP block_map;
|
||||
|
||||
EXT2_BADBLK_LIST badblocks;
|
||||
/*
|
||||
ext2_dblist dblist;
|
||||
*/
|
||||
__u32 stride; /* for mke2fs */
|
||||
|
||||
__u32 umask;
|
||||
|
||||
/*
|
||||
* Reserved for future expansion
|
||||
*/
|
||||
__u32 reserved[8];
|
||||
|
||||
/*
|
||||
* Reserved for the use of the calling application.
|
||||
*/
|
||||
void * priv_data;
|
||||
|
||||
HANDLE MediaHandle;
|
||||
|
||||
DISK_GEOMETRY DiskGeometry;
|
||||
|
||||
PARTITION_INFORMATION PartInfo;
|
||||
|
||||
} EXT2_FILESYS, *PEXT2_FILESYS;
|
||||
|
||||
// Block Description List
|
||||
typedef struct _EXT2_BDL {
|
||||
LONGLONG Lba;
|
||||
ULONG Offset;
|
||||
ULONG Length;
|
||||
} EXT2_BDL, *PEXT2_BDL;
|
||||
|
||||
/*
|
||||
* Where the master copy of the superblock is located, and how big
|
||||
* superblocks are supposed to be. We define SUPERBLOCK_SIZE because
|
||||
* the size of the superblock structure is not necessarily trustworthy
|
||||
* (some versions have the padding set up so that the superblock is
|
||||
* 1032 bytes long).
|
||||
*/
|
||||
#define SUPERBLOCK_OFFSET 1024
|
||||
#define SUPERBLOCK_SIZE 1024
|
||||
|
||||
|
||||
bool create_bad_block_inode(PEXT2_FILESYS fs, PEXT2_BADBLK_LIST bb_list);
|
||||
|
||||
|
||||
//
|
||||
// Definitions
|
||||
//
|
||||
|
||||
#define FSCTL_REQUEST_OPLOCK_LEVEL_1 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSCTL_REQUEST_OPLOCK_LEVEL_2 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSCTL_REQUEST_BATCH_OPLOCK CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSCTL_OPLOCK_BREAK_ACKNOWLEDGE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 3, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSCTL_OPBATCH_ACK_CLOSE_PENDING CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 4, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSCTL_OPLOCK_BREAK_NOTIFY CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 5, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSCTL_LOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 6, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSCTL_UNLOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 7, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSCTL_DISMOUNT_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 8, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
// decommissioned fsctl value 9
|
||||
#define FSCTL_IS_VOLUME_MOUNTED CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 10, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSCTL_IS_PATHNAME_VALID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 11, METHOD_BUFFERED, FILE_ANY_ACCESS) // PATHNAME_BUFFER,
|
||||
#define FSCTL_MARK_VOLUME_DIRTY CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 12, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
// decommissioned fsctl value 13
|
||||
#define FSCTL_QUERY_RETRIEVAL_POINTERS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 14, METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
#define FSCTL_GET_COMPRESSION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 15, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSCTL_SET_COMPRESSION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 16, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
|
||||
// decommissioned fsctl value 17
|
||||
// decommissioned fsctl value 18
|
||||
#define FSCTL_MARK_AS_SYSTEM_HIVE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 19, METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
#define FSCTL_OPLOCK_BREAK_ACK_NO_2 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 20, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSCTL_INVALIDATE_VOLUMES CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 21, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSCTL_QUERY_FAT_BPB CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 22, METHOD_BUFFERED, FILE_ANY_ACCESS) // , FSCTL_QUERY_FAT_BPB_BUFFER
|
||||
#define FSCTL_REQUEST_FILTER_OPLOCK CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 23, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSCTL_FILESYSTEM_GET_STATISTICS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 24, METHOD_BUFFERED, FILE_ANY_ACCESS) // , FILESYSTEM_STATISTICS
|
||||
|
||||
|
||||
//
|
||||
// Disk I/O Routines
|
||||
//
|
||||
|
||||
NTSYSAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtReadFile(HANDLE FileHandle,
|
||||
HANDLE Event OPTIONAL,
|
||||
PIO_APC_ROUTINE ApcRoutine OPTIONAL,
|
||||
PVOID ApcContext OPTIONAL,
|
||||
PIO_STATUS_BLOCK IoStatusBlock,
|
||||
PVOID Buffer,
|
||||
ULONG Length,
|
||||
PLARGE_INTEGER ByteOffset OPTIONAL,
|
||||
PULONG Key OPTIONAL);
|
||||
|
||||
NTSYSAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtWriteFile(HANDLE FileHandle,
|
||||
HANDLE Event OPTIONAL,
|
||||
PIO_APC_ROUTINE ApcRoutine OPTIONAL,
|
||||
PVOID ApcContext OPTIONAL,
|
||||
PIO_STATUS_BLOCK IoStatusBlock,
|
||||
PVOID Buffer,
|
||||
ULONG Length,
|
||||
PLARGE_INTEGER ByteOffset OPTIONAL,
|
||||
PULONG Key OPTIONAL);
|
||||
|
||||
NTSYSAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtClose(HANDLE Handle);
|
||||
|
||||
NTSYSAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtCreateFile(PHANDLE FileHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
PIO_STATUS_BLOCK IoStatusBlock,
|
||||
PLARGE_INTEGER AllocationSize OPTIONAL,
|
||||
ULONG FileAttributes,
|
||||
ULONG ShareAccess,
|
||||
ULONG CreateDisposition,
|
||||
ULONG CreateOptions,
|
||||
PVOID EaBuffer OPTIONAL,
|
||||
ULONG EaLength);
|
||||
|
||||
|
||||
NTSYSAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtDeviceIoControlFile(
|
||||
IN HANDLE FileHandle,
|
||||
IN HANDLE Event,
|
||||
IN PIO_APC_ROUTINE ApcRoutine,
|
||||
IN PVOID ApcContext,
|
||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
||||
IN ULONG IoControlCode,
|
||||
IN PVOID InputBuffer,
|
||||
IN ULONG InputBufferLength,
|
||||
OUT PVOID OutputBuffer,
|
||||
OUT ULONG OutputBufferLength
|
||||
);
|
||||
|
||||
NTSYSAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtFsControlFile(
|
||||
IN HANDLE FileHandle,
|
||||
IN HANDLE Event OPTIONAL,
|
||||
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
|
||||
IN PVOID ApcContext OPTIONAL,
|
||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
||||
IN ULONG FsControlCode,
|
||||
IN PVOID InputBuffer OPTIONAL,
|
||||
IN ULONG InputBufferLength,
|
||||
OUT PVOID OutputBuffer OPTIONAL,
|
||||
IN ULONG OutputBufferLength
|
||||
);
|
||||
|
||||
|
||||
NTSYSAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtQueryInformationFile(
|
||||
IN HANDLE FileHandle,
|
||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
||||
OUT PVOID FileInformation,
|
||||
IN ULONG Length,
|
||||
IN FILE_INFORMATION_CLASS FileInformationClass
|
||||
);
|
||||
|
||||
//
|
||||
// Bitmap Routines
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// BitMap routines. The following structure, routines, and macros are
|
||||
// for manipulating bitmaps. The user is responsible for allocating a bitmap
|
||||
// structure (which is really a header) and a buffer (which must be longword
|
||||
// aligned and multiple longwords in size).
|
||||
//
|
||||
|
||||
//
|
||||
// The following routine initializes a new bitmap. It does not alter the
|
||||
// data currently in the bitmap. This routine must be called before
|
||||
// any other bitmap routine/macro.
|
||||
//
|
||||
|
||||
NTSYSAPI
|
||||
VOID
|
||||
NTAPI
|
||||
RtlInitializeBitMap (
|
||||
PRTL_BITMAP BitMapHeader,
|
||||
PULONG BitMapBuffer,
|
||||
ULONG SizeOfBitMap
|
||||
);
|
||||
|
||||
//
|
||||
// The following two routines either clear or set all of the bits
|
||||
// in a bitmap.
|
||||
//
|
||||
|
||||
NTSYSAPI
|
||||
VOID
|
||||
NTAPI
|
||||
RtlClearAllBits (
|
||||
PRTL_BITMAP BitMapHeader
|
||||
);
|
||||
|
||||
NTSYSAPI
|
||||
VOID
|
||||
NTAPI
|
||||
RtlSetAllBits (
|
||||
PRTL_BITMAP BitMapHeader
|
||||
);
|
||||
|
||||
//
|
||||
// The following two routines locate a contiguous region of either
|
||||
// clear or set bits within the bitmap. The region will be at least
|
||||
// as large as the number specified, and the search of the bitmap will
|
||||
// begin at the specified hint index (which is a bit index within the
|
||||
// bitmap, zero based). The return value is the bit index of the located
|
||||
// region (zero based) or -1 (i.e., 0xffffffff) if such a region cannot
|
||||
// be located
|
||||
//
|
||||
|
||||
NTSYSAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
RtlFindClearBits (
|
||||
PRTL_BITMAP BitMapHeader,
|
||||
ULONG NumberToFind,
|
||||
ULONG HintIndex
|
||||
);
|
||||
|
||||
NTSYSAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
RtlFindSetBits (
|
||||
PRTL_BITMAP BitMapHeader,
|
||||
ULONG NumberToFind,
|
||||
ULONG HintIndex
|
||||
);
|
||||
|
||||
//
|
||||
// The following two routines locate a contiguous region of either
|
||||
// clear or set bits within the bitmap and either set or clear the bits
|
||||
// within the located region. The region will be as large as the number
|
||||
// specified, and the search for the region will begin at the specified
|
||||
// hint index (which is a bit index within the bitmap, zero based). The
|
||||
// return value is the bit index of the located region (zero based) or
|
||||
// -1 (i.e., 0xffffffff) if such a region cannot be located. If a region
|
||||
// cannot be located then the setting/clearing of the bitmap is not performed.
|
||||
//
|
||||
|
||||
NTSYSAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
RtlFindClearBitsAndSet (
|
||||
PRTL_BITMAP BitMapHeader,
|
||||
ULONG NumberToFind,
|
||||
ULONG HintIndex
|
||||
);
|
||||
|
||||
NTSYSAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
RtlFindSetBitsAndClear (
|
||||
PRTL_BITMAP BitMapHeader,
|
||||
ULONG NumberToFind,
|
||||
ULONG HintIndex
|
||||
);
|
||||
|
||||
//
|
||||
// The following two routines clear or set bits within a specified region
|
||||
// of the bitmap. The starting index is zero based.
|
||||
//
|
||||
|
||||
NTSYSAPI
|
||||
VOID
|
||||
NTAPI
|
||||
RtlClearBits (
|
||||
PRTL_BITMAP BitMapHeader,
|
||||
ULONG StartingIndex,
|
||||
ULONG NumberToClear
|
||||
);
|
||||
|
||||
NTSYSAPI
|
||||
VOID
|
||||
NTAPI
|
||||
RtlSetBits (
|
||||
PRTL_BITMAP BitMapHeader,
|
||||
ULONG StartingIndex,
|
||||
ULONG NumberToSet
|
||||
);
|
||||
|
||||
//
|
||||
// The following routine locates a set of contiguous regions of clear
|
||||
// bits within the bitmap. The caller specifies whether to return the
|
||||
// longest runs or just the first found lcoated. The following structure is
|
||||
// used to denote a contiguous run of bits. The two routines return an array
|
||||
// of this structure, one for each run located.
|
||||
//
|
||||
|
||||
NTSYSAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
RtlFindClearRuns (
|
||||
PRTL_BITMAP BitMapHeader,
|
||||
PRTL_BITMAP_RUN RunArray,
|
||||
ULONG SizeOfRunArray,
|
||||
BOOLEAN LocateLongestRuns
|
||||
);
|
||||
//
|
||||
// The following routine locates the longest contiguous region of
|
||||
// clear bits within the bitmap. The returned starting index value
|
||||
// denotes the first contiguous region located satisfying our requirements
|
||||
// The return value is the length (in bits) of the longest region found.
|
||||
//
|
||||
|
||||
NTSYSAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
RtlFindLongestRunClear (
|
||||
PRTL_BITMAP BitMapHeader,
|
||||
PULONG StartingIndex
|
||||
);
|
||||
|
||||
//
|
||||
// The following routine locates the first contiguous region of
|
||||
// clear bits within the bitmap. The returned starting index value
|
||||
// denotes the first contiguous region located satisfying our requirements
|
||||
// The return value is the length (in bits) of the region found.
|
||||
//
|
||||
|
||||
NTSYSAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
RtlFindFirstRunClear (
|
||||
PRTL_BITMAP BitMapHeader,
|
||||
PULONG StartingIndex
|
||||
);
|
||||
|
||||
//
|
||||
// The following macro returns the value of the bit stored within the
|
||||
// bitmap at the specified location. If the bit is set a value of 1 is
|
||||
// returned otherwise a value of 0 is returned.
|
||||
//
|
||||
// ULONG
|
||||
// RtlCheckBit (
|
||||
// PRTL_BITMAP BitMapHeader,
|
||||
// ULONG BitPosition
|
||||
// );
|
||||
//
|
||||
//
|
||||
// To implement CheckBit the macro retrieves the longword containing the
|
||||
// bit in question, shifts the longword to get the bit in question into the
|
||||
// low order bit position and masks out all other bits.
|
||||
//
|
||||
|
||||
#define RtlCheckBit(BMH,BP) ((((BMH)->Buffer[(BP) / 32]) >> ((BP) % 32)) & 0x1)
|
||||
|
||||
//
|
||||
// The following two procedures return to the caller the total number of
|
||||
// clear or set bits within the specified bitmap.
|
||||
//
|
||||
|
||||
NTSYSAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
RtlNumberOfClearBits (
|
||||
PRTL_BITMAP BitMapHeader
|
||||
);
|
||||
|
||||
NTSYSAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
RtlNumberOfSetBits (
|
||||
PRTL_BITMAP BitMapHeader
|
||||
);
|
||||
|
||||
//
|
||||
// The following two procedures return to the caller a boolean value
|
||||
// indicating if the specified range of bits are all clear or set.
|
||||
//
|
||||
|
||||
NTSYSAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
RtlAreBitsClear (
|
||||
PRTL_BITMAP BitMapHeader,
|
||||
ULONG StartingIndex,
|
||||
ULONG Length
|
||||
);
|
||||
|
||||
NTSYSAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
RtlAreBitsSet (
|
||||
PRTL_BITMAP BitMapHeader,
|
||||
ULONG StartingIndex,
|
||||
ULONG Length
|
||||
);
|
||||
|
||||
NTSYSAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
RtlFindNextForwardRunClear (
|
||||
IN PRTL_BITMAP BitMapHeader,
|
||||
IN ULONG FromIndex,
|
||||
IN PULONG StartingRunIndex
|
||||
);
|
||||
|
||||
NTSYSAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
RtlFindLastBackwardRunClear (
|
||||
IN PRTL_BITMAP BitMapHeader,
|
||||
IN ULONG FromIndex,
|
||||
IN PULONG StartingRunIndex
|
||||
);
|
||||
|
||||
//
|
||||
// The following two procedures return to the caller a value indicating
|
||||
// the position within a ULONGLONG of the most or least significant non-zero
|
||||
// bit. A value of zero results in a return value of -1.
|
||||
//
|
||||
|
||||
NTSYSAPI
|
||||
CCHAR
|
||||
NTAPI
|
||||
RtlFindLeastSignificantBit (
|
||||
IN ULONGLONG Set
|
||||
);
|
||||
|
||||
NTSYSAPI
|
||||
CCHAR
|
||||
NTAPI
|
||||
RtlFindMostSignificantBit (
|
||||
IN ULONGLONG Set
|
||||
);
|
||||
|
||||
|
||||
//
|
||||
// Random routines ...
|
||||
//
|
||||
|
||||
NTSYSAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
RtlRandom(
|
||||
IN OUT PULONG Seed
|
||||
);
|
||||
|
||||
//
|
||||
// Time routines ...
|
||||
//
|
||||
|
||||
NTSYSAPI
|
||||
CCHAR
|
||||
NTAPI
|
||||
NtQuerySystemTime(
|
||||
OUT PLARGE_INTEGER CurrentTime
|
||||
);
|
||||
|
||||
|
||||
NTSYSAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
RtlTimeToSecondsSince1970(
|
||||
IN PLARGE_INTEGER Time,
|
||||
OUT PULONG ElapsedSeconds
|
||||
);
|
||||
|
||||
|
||||
NTSYSAPI
|
||||
VOID
|
||||
NTAPI
|
||||
RtlSecondsSince1970ToTime(
|
||||
IN ULONG ElapsedSeconds,
|
||||
OUT PLARGE_INTEGER Time
|
||||
);
|
||||
|
||||
//
|
||||
// Heap routines...
|
||||
//
|
||||
|
||||
#define GetProcessHeap() (NtCurrentTeb()->Peb->ProcessHeap)
|
||||
|
||||
PVOID STDCALL
|
||||
RtlAllocateHeap (
|
||||
HANDLE Heap,
|
||||
ULONG Flags,
|
||||
ULONG Size
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
RtlFreeHeap (
|
||||
HANDLE Heap,
|
||||
ULONG Flags,
|
||||
PVOID Address
|
||||
);
|
||||
|
||||
/*
|
||||
* Bitmap.c
|
||||
*/
|
||||
|
||||
#define ext2_mark_block_bitmap ext2_mark_bitmap
|
||||
#define ext2_mark_inode_bitmap ext2_mark_bitmap
|
||||
#define ext2_unmark_block_bitmap ext2_unmark_bitmap
|
||||
#define ext2_unmark_inode_bitmap ext2_unmark_bitmap
|
||||
|
||||
bool ext2_set_bit(int nr, void * addr);
|
||||
bool ext2_clear_bit(int nr, void * addr);
|
||||
bool ext2_test_bit(int nr, void * addr);
|
||||
|
||||
bool ext2_mark_bitmap(PEXT2_BITMAP bitmap, ULONG bitno);
|
||||
bool ext2_unmark_bitmap(PEXT2_BITMAP bitmap, ULONG bitno);
|
||||
|
||||
bool ext2_test_block_bitmap(PEXT2_BLOCK_BITMAP bitmap,
|
||||
ULONG block);
|
||||
|
||||
bool ext2_test_block_bitmap_range(PEXT2_BLOCK_BITMAP bitmap,
|
||||
ULONG block, int num);
|
||||
|
||||
bool ext2_test_inode_bitmap(PEXT2_BLOCK_BITMAP bitmap,
|
||||
ULONG inode);
|
||||
|
||||
|
||||
bool ext2_allocate_block_bitmap(PEXT2_FILESYS pExt2Sys);
|
||||
bool ext2_allocate_inode_bitmap(PEXT2_FILESYS pExt2Sys);
|
||||
void ext2_free_inode_bitmap(PEXT2_FILESYS pExt2Sys);
|
||||
void ext2_free_block_bitmap(PEXT2_FILESYS pExt2Sys);
|
||||
|
||||
bool ext2_write_block_bitmap (PEXT2_FILESYS fs);
|
||||
bool ext2_write_inode_bitmap (PEXT2_FILESYS fs);
|
||||
|
||||
bool ext2_write_bitmaps(PEXT2_FILESYS fs);
|
||||
|
||||
//bool read_bitmaps(PEXT2_FILESYS fs, int do_inode, int do_block);
|
||||
bool ext2_read_inode_bitmap (PEXT2_FILESYS fs);
|
||||
bool ext2_read_block_bitmap(PEXT2_FILESYS fs);
|
||||
bool ext2_read_bitmaps(PEXT2_FILESYS fs);
|
||||
|
||||
|
||||
/*
|
||||
* Disk.c
|
||||
*/
|
||||
|
||||
NTSTATUS
|
||||
Ext2OpenDevice( PEXT2_FILESYS Ext2Sys,
|
||||
PUNICODE_STRING DeviceName );
|
||||
|
||||
NTSTATUS
|
||||
Ext2CloseDevice( PEXT2_FILESYS Ext2Sys);
|
||||
|
||||
NTSTATUS
|
||||
Ext2ReadDisk( PEXT2_FILESYS Ext2Sys,
|
||||
ULONGLONG Offset,
|
||||
ULONG Length,
|
||||
PVOID Buffer );
|
||||
|
||||
NTSTATUS
|
||||
Ext2WriteDisk( PEXT2_FILESYS Ext2Sys,
|
||||
ULONGLONG Offset,
|
||||
ULONG Length,
|
||||
PVOID Buffer );
|
||||
|
||||
NTSTATUS
|
||||
Ext2GetMediaInfo( PEXT2_FILESYS Ext2Sys );
|
||||
|
||||
|
||||
NTSTATUS
|
||||
Ext2LockVolume( PEXT2_FILESYS Ext2Sys );
|
||||
|
||||
NTSTATUS
|
||||
Ext2UnLockVolume( PEXT2_FILESYS Ext2Sys );
|
||||
|
||||
NTSTATUS
|
||||
Ext2DisMountVolume( PEXT2_FILESYS Ext2Sys );
|
||||
|
||||
|
||||
/*
|
||||
* Group.c
|
||||
*/
|
||||
|
||||
bool ext2_allocate_group_desc(PEXT2_FILESYS pExt2Sys);
|
||||
void ext2_free_group_desc(PEXT2_FILESYS pExt2Sys);
|
||||
bool ext2_bg_has_super(PEXT2_SUPER_BLOCK pExt2Sb, int group_block);
|
||||
|
||||
/*
|
||||
* Inode.c
|
||||
*/
|
||||
|
||||
bool ext2_get_inode_lba(PEXT2_FILESYS pExt2Sys, ULONG no, LONGLONG *offset);
|
||||
bool ext2_load_inode(PEXT2_FILESYS pExt2Sys, ULONG no, PEXT2_INODE pInode);
|
||||
bool ext2_save_inode(PEXT2_FILESYS pExt2Sys, ULONG no, PEXT2_INODE pInode);
|
||||
bool ext2_new_inode(PEXT2_FILESYS fs, ULONG dir, int mode,
|
||||
PEXT2_INODE_BITMAP map, ULONG *ret);
|
||||
bool ext2_expand_inode(PEXT2_FILESYS pExt2Sys, PEXT2_INODE, ULONG newBlk);
|
||||
|
||||
bool ext2_read_inode (PEXT2_FILESYS pExt2Sys,
|
||||
ULONG ino,
|
||||
ULONG offset,
|
||||
PVOID Buffer,
|
||||
ULONG size,
|
||||
PULONG dwReturn );
|
||||
bool ext2_write_inode (PEXT2_FILESYS pExt2Sys,
|
||||
ULONG ino,
|
||||
ULONG offset,
|
||||
PVOID Buffer,
|
||||
ULONG size,
|
||||
PULONG dwReturn );
|
||||
|
||||
bool ext2_add_entry(PEXT2_FILESYS pExt2Sys, ULONG parent, ULONG inode, int filetype, char *name);
|
||||
bool ext2_reserve_inodes(PEXT2_FILESYS fs);
|
||||
/*
|
||||
* Memory.c
|
||||
*/
|
||||
|
||||
//
|
||||
// Return the group # of an inode number
|
||||
//
|
||||
int ext2_group_of_ino(PEXT2_FILESYS fs, ULONG ino);
|
||||
|
||||
//
|
||||
// Return the group # of a block
|
||||
//
|
||||
int ext2_group_of_blk(PEXT2_FILESYS fs, ULONG blk);
|
||||
|
||||
/*
|
||||
* Badblock.c
|
||||
*/
|
||||
|
||||
|
||||
void ext2_inode_alloc_stats2(PEXT2_FILESYS fs, ULONG ino, int inuse, int isdir);
|
||||
void ext2_inode_alloc_stats(PEXT2_FILESYS fs, ULONG ino, int inuse);
|
||||
void ext2_block_alloc_stats(PEXT2_FILESYS fs, ULONG blk, int inuse);
|
||||
|
||||
bool ext2_allocate_tables(PEXT2_FILESYS pExt2Sys);
|
||||
bool ext2_allocate_group_table(PEXT2_FILESYS fs, ULONG group,
|
||||
PEXT2_BLOCK_BITMAP bmap);
|
||||
bool ext2_get_free_blocks(PEXT2_FILESYS fs, ULONG start, ULONG finish,
|
||||
int num, PEXT2_BLOCK_BITMAP map, ULONG *ret);
|
||||
bool write_inode_tables(PEXT2_FILESYS fs);
|
||||
|
||||
bool ext2_new_block(PEXT2_FILESYS fs, ULONG goal,
|
||||
PEXT2_BLOCK_BITMAP map, ULONG *ret);
|
||||
bool ext2_alloc_block(PEXT2_FILESYS fs, ULONG goal, ULONG *ret);
|
||||
bool ext2_new_dir_block(PEXT2_FILESYS fs, ULONG dir_ino,
|
||||
ULONG parent_ino, char **block);
|
||||
bool ext2_write_block(PEXT2_FILESYS fs, ULONG block, void *inbuf);
|
||||
bool ext2_read_block(PEXT2_FILESYS fs, ULONG block, void *inbuf);
|
||||
|
||||
/*
|
||||
* Mke2fs.c
|
||||
*/
|
||||
|
||||
bool parase_cmd(int argc, char *argv[], PEXT2_FILESYS pExt2Sys);
|
||||
|
||||
bool zero_blocks(PEXT2_FILESYS fs, ULONG blk, ULONG num,
|
||||
ULONG *ret_blk, ULONG *ret_count);
|
||||
|
||||
ULONG
|
||||
Ext2DataBlocks(PEXT2_FILESYS Ext2Sys, ULONG TotalBlocks);
|
||||
|
||||
ULONG
|
||||
Ext2TotalBlocks(PEXT2_FILESYS Ext2Sys, ULONG DataBlocks);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Super.c
|
||||
*/
|
||||
|
||||
void ext2_print_super(PEXT2_SUPER_BLOCK pExt2Sb);
|
||||
bool ext2_initialize_sb(PEXT2_FILESYS pExt2Sys);
|
||||
|
||||
|
||||
/*
|
||||
* Super.c
|
||||
*/
|
||||
|
||||
LONGLONG ext2_nt_time (ULONG i_time);
|
||||
ULONG ext2_unix_time (LONGLONG n_time);
|
||||
|
||||
/*
|
||||
* Uuid.c
|
||||
*/
|
||||
|
||||
void uuid_generate(__u8 * uuid);
|
||||
|
||||
#endif //__MKE2FS__INCLUDE__
|
302
reactos/lib/fslib/ext2lib/Super.c
Normal file
302
reactos/lib/fslib/ext2lib/Super.c
Normal file
|
@ -0,0 +1,302 @@
|
|||
/*
|
||||
* PROJECT: Mke2fs
|
||||
* FILE: Super.c
|
||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||
* HOMEPAGE: http://ext2.yeah.net
|
||||
*/
|
||||
|
||||
/* INCLUDES **************************************************************/
|
||||
|
||||
#include "Mke2fs.h"
|
||||
|
||||
/* DEFINITIONS ***********************************************************/
|
||||
|
||||
extern int inode_ratio;
|
||||
|
||||
|
||||
/* FUNCTIONS *************************************************************/
|
||||
|
||||
void ext2_print_super(PEXT2_SUPER_BLOCK pExt2Sb)
|
||||
{
|
||||
int i;
|
||||
|
||||
KdPrint(("\nExt2 Super Block Details ...\n\n"));
|
||||
KdPrint((" Inode Count: %lu\n", pExt2Sb->s_inodes_count));
|
||||
KdPrint((" Block Count: %lu\n", pExt2Sb->s_blocks_count));
|
||||
KdPrint((" Reserved Block Count: %lu\n", pExt2Sb->s_r_blocks_count));
|
||||
KdPrint((" Free Blocks: %lu\n", pExt2Sb->s_free_blocks_count));
|
||||
KdPrint((" Free Inodes: %lu\n", pExt2Sb->s_free_inodes_count));
|
||||
KdPrint((" First Data Block: %lu\n", pExt2Sb->s_first_data_block));
|
||||
KdPrint((" Log Block Size: %lu\n", pExt2Sb->s_log_block_size));
|
||||
KdPrint((" Log Frag Size: %ld\n", pExt2Sb->s_log_frag_size));
|
||||
KdPrint((" Blocks per Group: %lu\n", pExt2Sb->s_blocks_per_group));
|
||||
KdPrint((" Fragments per Group: %lu\n", pExt2Sb->s_frags_per_group));
|
||||
KdPrint((" Inodes per Group: %lu\n", pExt2Sb->s_inodes_per_group));
|
||||
// KdPrint((" Mount Time: %s", ctime((time_t *) & (pExt2Sb->s_mtime))));
|
||||
// KdPrint((" Write Time: %s", ctime((time_t *) & (pExt2Sb->s_wtime))));
|
||||
KdPrint((" Mount Count: %u\n", pExt2Sb->s_mnt_count));
|
||||
KdPrint((" Max Mount Count: %d\n", pExt2Sb->s_max_mnt_count));
|
||||
KdPrint((" Magic Number: %X (%s)\n", pExt2Sb->s_magic,
|
||||
pExt2Sb->s_magic == EXT2_SUPER_MAGIC ? "OK" : "BAD"));
|
||||
KdPrint((" File System State: %X\n", pExt2Sb->s_state));
|
||||
KdPrint((" Error Behaviour: %X\n", pExt2Sb->s_errors));
|
||||
KdPrint((" Minor rev: %u\n", pExt2Sb->s_minor_rev_level));
|
||||
// KdPrint((" Last Check: %s", ctime((time_t *) & (pExt2Sb->s_lastcheck))));
|
||||
KdPrint((" Check Interval: %lu\n", pExt2Sb->s_checkinterval));
|
||||
KdPrint((" Creator OS: %lu\n", pExt2Sb->s_creator_os));
|
||||
KdPrint((" Revision Level: %lu\n", pExt2Sb->s_rev_level));
|
||||
KdPrint((" Reserved Block Default UID: %u\n", pExt2Sb->s_def_resuid));
|
||||
KdPrint((" Reserved Block Default GID: %u\n", pExt2Sb->s_def_resgid));
|
||||
KdPrint((" uuid = "));
|
||||
for (i=0; i < 16; i++)
|
||||
KdPrint(("%x ", pExt2Sb->s_uuid[i]));
|
||||
KdPrint(("\n"));
|
||||
|
||||
KdPrint((" volume label name: "));
|
||||
for (i=0; i < 16; i++)
|
||||
{
|
||||
if (pExt2Sb->s_volume_name[i] == 0)
|
||||
break;
|
||||
KdPrint(("%c", pExt2Sb->s_volume_name[i]));
|
||||
}
|
||||
KdPrint(("\n"));
|
||||
|
||||
KdPrint(("\n\n"));
|
||||
}
|
||||
|
||||
|
||||
#define set_field(field, default) if (!pExt2Sb->field) pExt2Sb->field = (default);
|
||||
|
||||
/*
|
||||
* Initialize super block ...
|
||||
*/
|
||||
|
||||
bool ext2_initialize_sb(PEXT2_FILESYS Ext2Sys)
|
||||
{
|
||||
int frags_per_block = 0;
|
||||
ULONG overhead = 0;
|
||||
int rem = 0;
|
||||
ULONG i = 0;
|
||||
ULONG group_block = 0;
|
||||
ULONG numblocks = 0;
|
||||
PEXT2_SUPER_BLOCK pExt2Sb = Ext2Sys->ext2_sb;
|
||||
LARGE_INTEGER SysTime;
|
||||
|
||||
NtQuerySystemTime(&SysTime);
|
||||
|
||||
Ext2Sys->blocksize = EXT2_BLOCK_SIZE(pExt2Sb);
|
||||
Ext2Sys->fragsize = EXT2_FRAG_SIZE(pExt2Sb);
|
||||
frags_per_block = Ext2Sys->blocksize / Ext2Sys->fragsize;
|
||||
|
||||
pExt2Sb->s_magic = EXT2_SUPER_MAGIC;
|
||||
pExt2Sb->s_state = EXT2_VALID_FS;
|
||||
|
||||
pExt2Sb->s_first_data_block = (pExt2Sb->s_log_block_size) ? 0 : 1;
|
||||
pExt2Sb->s_max_mnt_count = EXT2_DFL_MAX_MNT_COUNT;
|
||||
|
||||
pExt2Sb->s_errors = EXT2_ERRORS_DEFAULT;
|
||||
|
||||
pExt2Sb->s_checkinterval = EXT2_DFL_CHECKINTERVAL;
|
||||
|
||||
if (!pExt2Sb->s_rev_level)
|
||||
pExt2Sb->s_rev_level = EXT2_GOOD_OLD_REV;
|
||||
|
||||
if (pExt2Sb->s_rev_level >= EXT2_DYNAMIC_REV)
|
||||
{
|
||||
set_field(s_first_ino, EXT2_GOOD_OLD_FIRST_INO);
|
||||
set_field(s_inode_size, EXT2_GOOD_OLD_INODE_SIZE);
|
||||
}
|
||||
|
||||
RtlTimeToSecondsSince1970(&SysTime, &pExt2Sb->s_wtime);
|
||||
pExt2Sb->s_lastcheck = pExt2Sb->s_mtime = pExt2Sb->s_wtime;
|
||||
|
||||
if (!pExt2Sb->s_blocks_per_group)
|
||||
pExt2Sb->s_blocks_per_group = Ext2Sys->blocksize * 8;
|
||||
|
||||
pExt2Sb->s_frags_per_group = pExt2Sb->s_blocks_per_group * frags_per_block;
|
||||
pExt2Sb->s_creator_os = EXT2_OS_WINNT;
|
||||
|
||||
if (pExt2Sb->s_r_blocks_count >= pExt2Sb->s_blocks_count)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're creating an external journal device, we don't need
|
||||
* to bother with the rest.
|
||||
*/
|
||||
if (pExt2Sb->s_feature_incompat &
|
||||
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
|
||||
{
|
||||
Ext2Sys->group_desc_count = 0;
|
||||
// ext2fs_mark_super_dirty(fs);
|
||||
return true;
|
||||
}
|
||||
|
||||
retry:
|
||||
|
||||
Ext2Sys->group_desc_count = (pExt2Sb->s_blocks_count - pExt2Sb->s_first_data_block
|
||||
+ EXT2_BLOCKS_PER_GROUP(pExt2Sb) - 1) / EXT2_BLOCKS_PER_GROUP(pExt2Sb);
|
||||
|
||||
if (Ext2Sys->group_desc_count == 0)
|
||||
return false;
|
||||
|
||||
Ext2Sys->desc_blocks = (Ext2Sys->group_desc_count + EXT2_DESC_PER_BLOCK(pExt2Sb)
|
||||
- 1) / EXT2_DESC_PER_BLOCK(pExt2Sb);
|
||||
|
||||
if (!pExt2Sb->s_inodes_count)
|
||||
pExt2Sb->s_inodes_count = pExt2Sb->s_blocks_count / ( inode_ratio /Ext2Sys->blocksize);
|
||||
|
||||
/*
|
||||
* Make sure we have at least EXT2_FIRST_INO + 1 inodes, so
|
||||
* that we have enough inodes for the filesystem(!)
|
||||
*/
|
||||
if (pExt2Sb->s_inodes_count < EXT2_FIRST_INODE(pExt2Sb)+1)
|
||||
pExt2Sb->s_inodes_count = EXT2_FIRST_INODE(pExt2Sb)+1;
|
||||
|
||||
/*
|
||||
* There should be at least as many inodes as the user
|
||||
* requested. Figure out how many inodes per group that
|
||||
* should be. But make sure that we don't allocate more than
|
||||
* one bitmap's worth of inodes
|
||||
*/
|
||||
pExt2Sb->s_inodes_per_group = (pExt2Sb->s_inodes_count + Ext2Sys->group_desc_count - 1)
|
||||
/Ext2Sys->group_desc_count;
|
||||
|
||||
if (pExt2Sb->s_inodes_per_group > (ULONG)(Ext2Sys->blocksize*8))
|
||||
pExt2Sb->s_inodes_per_group = Ext2Sys->blocksize*8;
|
||||
|
||||
/*
|
||||
* Make sure the number of inodes per group completely fills
|
||||
* the inode table blocks in the descriptor. If not, add some
|
||||
* additional inodes/group. Waste not, want not...
|
||||
*/
|
||||
Ext2Sys->inode_blocks_per_group = (((pExt2Sb->s_inodes_per_group * EXT2_INODE_SIZE(pExt2Sb))
|
||||
+ EXT2_BLOCK_SIZE(pExt2Sb) - 1) / EXT2_BLOCK_SIZE(pExt2Sb));
|
||||
|
||||
pExt2Sb->s_inodes_per_group = ((Ext2Sys->inode_blocks_per_group * EXT2_BLOCK_SIZE(pExt2Sb))
|
||||
/ EXT2_INODE_SIZE(pExt2Sb));
|
||||
|
||||
/*
|
||||
* Finally, make sure the number of inodes per group is a
|
||||
* multiple of 8. This is needed to simplify the bitmap
|
||||
* splicing code.
|
||||
*/
|
||||
pExt2Sb->s_inodes_per_group &= ~7;
|
||||
Ext2Sys->inode_blocks_per_group = (((pExt2Sb->s_inodes_per_group * EXT2_INODE_SIZE(pExt2Sb))
|
||||
+ EXT2_BLOCK_SIZE(pExt2Sb) - 1) / EXT2_BLOCK_SIZE(pExt2Sb));
|
||||
|
||||
/*
|
||||
* adjust inode count to reflect the adjusted inodes_per_group
|
||||
*/
|
||||
pExt2Sb->s_inodes_count = pExt2Sb->s_inodes_per_group * Ext2Sys->group_desc_count;
|
||||
pExt2Sb->s_free_inodes_count = pExt2Sb->s_inodes_count;
|
||||
|
||||
/*
|
||||
* Overhead is the number of bookkeeping blocks per group. It
|
||||
* includes the superblock backup, the group descriptor
|
||||
* backups, the inode bitmap, the block bitmap, and the inode
|
||||
* table.
|
||||
*
|
||||
* XXX Not all block groups need the descriptor blocks, but
|
||||
* being clever is tricky...
|
||||
*/
|
||||
overhead = (int) (3 + Ext2Sys->desc_blocks + Ext2Sys->inode_blocks_per_group);
|
||||
|
||||
/*
|
||||
* See if the last group is big enough to support the
|
||||
* necessary data structures. If not, we need to get rid of
|
||||
* it.
|
||||
*/
|
||||
rem = (int) ((pExt2Sb->s_blocks_count - pExt2Sb->s_first_data_block) %
|
||||
pExt2Sb->s_blocks_per_group);
|
||||
|
||||
if ((Ext2Sys->group_desc_count == 1) && rem && (rem < overhead))
|
||||
return false;
|
||||
|
||||
if (rem && (rem < overhead+50))
|
||||
{
|
||||
pExt2Sb->s_blocks_count -= rem;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point we know how big the filesystem will be. So we can do
|
||||
* any and all allocations that depend on the block count.
|
||||
*/
|
||||
|
||||
// Allocate block bitmap
|
||||
if(!ext2_allocate_block_bitmap(Ext2Sys))
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Allocate inode bitmap
|
||||
if(!ext2_allocate_inode_bitmap(Ext2Sys))
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Allocate gourp desc
|
||||
if(!ext2_allocate_group_desc(Ext2Sys))
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reserve the superblock and group descriptors for each
|
||||
* group, and fill in the correct group statistics for group.
|
||||
* Note that although the block bitmap, inode bitmap, and
|
||||
* inode table have not been allocated (and in fact won't be
|
||||
* by this routine), they are accounted for nevertheless.
|
||||
*/
|
||||
group_block = pExt2Sb->s_first_data_block;
|
||||
numblocks = 0;
|
||||
|
||||
pExt2Sb->s_free_blocks_count = 0;
|
||||
|
||||
for (i = 0; i < Ext2Sys->group_desc_count; i++)
|
||||
{
|
||||
if (i == Ext2Sys->group_desc_count-1)
|
||||
{
|
||||
numblocks = (pExt2Sb->s_blocks_count - pExt2Sb->s_first_data_block)
|
||||
% pExt2Sb->s_blocks_per_group;
|
||||
|
||||
if (!numblocks)
|
||||
numblocks = pExt2Sb->s_blocks_per_group;
|
||||
}
|
||||
else
|
||||
{
|
||||
numblocks = pExt2Sb->s_blocks_per_group;
|
||||
}
|
||||
|
||||
if (ext2_bg_has_super(pExt2Sb, i))
|
||||
{
|
||||
ULONG j;
|
||||
|
||||
for (j=0; j < Ext2Sys->desc_blocks+1; j++)
|
||||
ext2_mark_bitmap(Ext2Sys->block_map, group_block + j);
|
||||
|
||||
numblocks -= 1 + Ext2Sys->desc_blocks;
|
||||
}
|
||||
|
||||
numblocks -= 2 + Ext2Sys->inode_blocks_per_group;
|
||||
|
||||
pExt2Sb->s_free_blocks_count += numblocks;
|
||||
Ext2Sys->group_desc[i].bg_free_blocks_count = (__u16)numblocks;
|
||||
Ext2Sys->group_desc[i].bg_free_inodes_count = (__u16)pExt2Sb->s_inodes_per_group;
|
||||
Ext2Sys->group_desc[i].bg_used_dirs_count = 0;
|
||||
|
||||
group_block += pExt2Sb->s_blocks_per_group;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
cleanup:
|
||||
|
||||
ext2_free_group_desc(Ext2Sys);
|
||||
ext2_free_block_bitmap(Ext2Sys);
|
||||
ext2_free_inode_bitmap(Ext2Sys);
|
||||
|
||||
return false;
|
||||
}
|
25
reactos/lib/fslib/ext2lib/Uuid.c
Normal file
25
reactos/lib/fslib/ext2lib/Uuid.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* PROJECT: Mke2fs
|
||||
* FILE: Timer.c
|
||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||
* HOMEPAGE: http://ext2.yeah.net
|
||||
*/
|
||||
|
||||
/* INCLUDES **************************************************************/
|
||||
|
||||
#include "windows.h"
|
||||
#include "types.h"
|
||||
|
||||
/* DEFINITIONS ***********************************************************/
|
||||
|
||||
|
||||
/* FUNCTIONS *************************************************************/
|
||||
|
||||
void uuid_generate(__u8 * uuid)
|
||||
{
|
||||
#if 0
|
||||
UuidCreate((UUID *) uuid);
|
||||
#else
|
||||
RtlZeroMemory(uuid, 16);
|
||||
#endif
|
||||
}
|
657
reactos/lib/fslib/ext2lib/ext2_fs.h
Normal file
657
reactos/lib/fslib/ext2lib/ext2_fs.h
Normal file
|
@ -0,0 +1,657 @@
|
|||
/*
|
||||
* linux/include/linux/ext2_fs.h
|
||||
*
|
||||
* Copyright (C) 1992, 1993, 1994, 1995
|
||||
* Remy Card (card@masi.ibp.fr)
|
||||
* Laboratoire MASI - Institut Blaise Pascal
|
||||
* Universite Pierre et Marie Curie (Paris VI)
|
||||
*
|
||||
* from
|
||||
*
|
||||
* linux/include/linux/minix_fs.h
|
||||
*
|
||||
* Copyright f(C) 1991, 1992 Linus Torvalds
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_EXT2_FS_H
|
||||
#define _LINUX_EXT2_FS_H
|
||||
|
||||
#include "types.h" /* Changed from linux/types.h */
|
||||
|
||||
/*
|
||||
* The second extended filesystem constants/structures
|
||||
*/
|
||||
|
||||
/*
|
||||
* Define EXT2FS_DEBUG to produce debug messages
|
||||
*/
|
||||
#undef EXT2FS_DEBUG
|
||||
|
||||
/*
|
||||
* Define EXT2_PREALLOCATE to preallocate data blocks for expanding files
|
||||
*/
|
||||
#define EXT2_PREALLOCATE
|
||||
#define EXT2_DEFAULT_PREALLOC_BLOCKS 8
|
||||
|
||||
/*
|
||||
* The second extended file system version
|
||||
*/
|
||||
#define EXT2FS_DATE "95/08/09"
|
||||
#define EXT2FS_VERSION "0.5b"
|
||||
|
||||
/*
|
||||
* Special inodes numbers
|
||||
*/
|
||||
#define EXT2_BAD_INO 1 /* Bad blocks inode */
|
||||
#define EXT2_ROOT_INO 2 /* Root inode */
|
||||
#define EXT2_ACL_IDX_INO 3 /* ACL inode */
|
||||
#define EXT2_ACL_DATA_INO 4 /* ACL inode */
|
||||
#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
|
||||
#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
|
||||
#define EXT2_RESIZE_INO 7 /* Reserved group descriptors inode */
|
||||
#define EXT2_JOURNAL_INO 8 /* Journal inode */
|
||||
|
||||
/* First non-reserved inode for old ext2 filesystems */
|
||||
#define EXT2_GOOD_OLD_FIRST_INO 11
|
||||
|
||||
/*
|
||||
* The second extended file system magic number
|
||||
*/
|
||||
#define EXT2_SUPER_MAGIC 0xEF53
|
||||
|
||||
/*
|
||||
* Maximal count of links to a file
|
||||
*/
|
||||
#define EXT2_LINK_MAX 32000
|
||||
|
||||
/*
|
||||
* Macro-instructions used to manage several block sizes
|
||||
*/
|
||||
#define EXT2_MIN_BLOCK_SIZE 1024
|
||||
#define EXT2_MAX_BLOCK_SIZE 4096
|
||||
#define EXT2_MIN_BLOCK_LOG_SIZE 10
|
||||
#ifdef __KERNEL__
|
||||
# define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize)
|
||||
#else
|
||||
# define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
|
||||
#endif
|
||||
#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
|
||||
#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
|
||||
#ifdef __KERNEL__
|
||||
# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
|
||||
#else
|
||||
# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
|
||||
#endif
|
||||
#ifdef __KERNEL__
|
||||
#define EXT2_ADDR_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_addr_per_block_bits)
|
||||
#define EXT2_INODE_SIZE(s) ((s)->u.ext2_sb.s_inode_size)
|
||||
#define EXT2_FIRST_INO(s) ((s)->u.ext2_sb.s_first_ino)
|
||||
#else
|
||||
#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
|
||||
EXT2_GOOD_OLD_INODE_SIZE : \
|
||||
(s)->s_inode_size)
|
||||
#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
|
||||
EXT2_GOOD_OLD_FIRST_INO : \
|
||||
(s)->s_first_ino)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macro-instructions used to manage fragments
|
||||
*/
|
||||
#define EXT2_MIN_FRAG_SIZE 1024
|
||||
#define EXT2_MAX_FRAG_SIZE 4096
|
||||
#define EXT2_MIN_FRAG_LOG_SIZE 10
|
||||
#ifdef __KERNEL__
|
||||
# define EXT2_FRAG_SIZE(s) ((s)->u.ext2_sb.s_frag_size)
|
||||
# define EXT2_FRAGS_PER_BLOCK(s) ((s)->u.ext2_sb.s_frags_per_block)
|
||||
#else
|
||||
# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
|
||||
# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ACL structures
|
||||
*/
|
||||
struct ext2_acl_header /* Header of Access Control Lists */
|
||||
{
|
||||
__u32 aclh_size;
|
||||
__u32 aclh_file_count;
|
||||
__u32 aclh_acle_count;
|
||||
__u32 aclh_first_acle;
|
||||
};
|
||||
|
||||
struct ext2_acl_entry /* Access Control List Entry */
|
||||
{
|
||||
__u32 acle_size;
|
||||
__u16 acle_perms; /* Access permissions */
|
||||
__u16 acle_type; /* Type of entry */
|
||||
__u16 acle_tag; /* User or group identity */
|
||||
__u16 acle_pad1;
|
||||
__u32 acle_next; /* Pointer on next entry for the */
|
||||
/* same inode or on next free entry */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure of a blocks group descriptor
|
||||
*/
|
||||
struct ext2_group_desc
|
||||
{
|
||||
__u32 bg_block_bitmap; /* Blocks bitmap block */
|
||||
__u32 bg_inode_bitmap; /* Inodes bitmap block */
|
||||
__u32 bg_inode_table; /* Inodes table block */
|
||||
__u16 bg_free_blocks_count; /* Free blocks count */
|
||||
__u16 bg_free_inodes_count; /* Free inodes count */
|
||||
__u16 bg_used_dirs_count; /* Directories count */
|
||||
__u16 bg_pad;
|
||||
__u32 bg_reserved[3];
|
||||
};
|
||||
|
||||
/*
|
||||
* Data structures used by the directory indexing feature
|
||||
*
|
||||
* Note: all of the multibyte integer fields are little endian.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note: dx_root_info is laid out so that if it should somehow get
|
||||
* overlaid by a dirent the two low bits of the hash version will be
|
||||
* zero. Therefore, the hash version mod 4 should never be 0.
|
||||
* Sincerely, the paranoia department.
|
||||
*/
|
||||
struct ext2_dx_root_info {
|
||||
__u32 reserved_zero;
|
||||
__u8 hash_version; /* 0 now, 1 at release */
|
||||
__u8 info_length; /* 8 */
|
||||
__u8 indirect_levels;
|
||||
__u8 unused_flags;
|
||||
};
|
||||
|
||||
struct ext2_dx_entry {
|
||||
__u32 hash;
|
||||
__u32 block;
|
||||
};
|
||||
|
||||
struct ext2_dx_countlimit {
|
||||
__u16 limit;
|
||||
__u16 count;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Macro-instructions used to manage group descriptors
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
# define EXT2_BLOCKS_PER_GROUP(s) ((s)->u.ext2_sb.s_blocks_per_group)
|
||||
# define EXT2_DESC_PER_BLOCK(s) ((s)->u.ext2_sb.s_desc_per_block)
|
||||
# define EXT2_INODES_PER_GROUP(s) ((s)->u.ext2_sb.s_inodes_per_group)
|
||||
# define EXT2_DESC_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_desc_per_block_bits)
|
||||
#else
|
||||
# define EXT2_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group)
|
||||
# define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
|
||||
# define EXT2_INODES_PER_GROUP(s) ((s)->s_inodes_per_group)
|
||||
#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_NOATIME_FL 0x00000080 /* do not update atime */
|
||||
/* Reserved for compression usage... */
|
||||
#define EXT2_DIRTY_FL 0x00000100
|
||||
#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
|
||||
#define EXT2_NOCOMPR_FL 0x00000400 /* Access raw compressed data */
|
||||
#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */
|
||||
/* End compression flags --- maybe not all used */
|
||||
#define EXT2_BTREE_FL 0x00001000 /* btree format dir */
|
||||
#define EXT2_INDEX_FL 0x00001000 /* hash-indexed directory */
|
||||
#define EXT2_IMAGIC_FL 0x00002000
|
||||
#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
|
||||
#define EXT2_NOTAIL_FL 0x00008000 /* file tail should not be merged */
|
||||
#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
|
||||
|
||||
#define EXT2_FL_USER_VISIBLE 0x0000DFFF /* User visible flags */
|
||||
#define EXT2_FL_USER_MODIFIABLE 0x000080FF /* User modifiable flags */
|
||||
|
||||
/*
|
||||
* ioctl commands
|
||||
*/
|
||||
#define EXT2_IOC_GETFLAGS _IOR('f', 1, long)
|
||||
#define EXT2_IOC_SETFLAGS _IOW('f', 2, long)
|
||||
#define EXT2_IOC_GETVERSION _IOR('v', 1, long)
|
||||
#define EXT2_IOC_SETVERSION _IOW('v', 2, long)
|
||||
|
||||
/*
|
||||
* Structure of an inode on the disk
|
||||
*/
|
||||
struct ext2_inode {
|
||||
__u16 i_mode; /* File mode */
|
||||
__u16 i_uid; /* Low 16 bits of Owner Uid */
|
||||
__u32 i_size; /* Size in bytes */
|
||||
__u32 i_atime; /* Access time */
|
||||
__u32 i_ctime; /* Creation time */
|
||||
__u32 i_mtime; /* Modification time */
|
||||
__u32 i_dtime; /* Deletion Time */
|
||||
__u16 i_gid; /* Low 16 bits of Group Id */
|
||||
__u16 i_links_count; /* Links count */
|
||||
__u32 i_blocks; /* Blocks count */
|
||||
__u32 i_flags; /* File flags */
|
||||
union {
|
||||
struct {
|
||||
__u32 l_i_reserved1;
|
||||
} linux1;
|
||||
struct {
|
||||
__u32 h_i_translator;
|
||||
} hurd1;
|
||||
struct {
|
||||
__u32 m_i_reserved1;
|
||||
} masix1;
|
||||
} osd1; /* OS dependent 1 */
|
||||
__u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
|
||||
__u32 i_generation; /* File version (for NFS) */
|
||||
__u32 i_file_acl; /* File ACL */
|
||||
__u32 i_dir_acl; /* Directory ACL */
|
||||
__u32 i_faddr; /* Fragment address */
|
||||
union {
|
||||
struct {
|
||||
__u8 l_i_frag; /* Fragment number */
|
||||
__u8 l_i_fsize; /* Fragment size */
|
||||
__u16 i_pad1;
|
||||
__u16 l_i_uid_high; /* these 2 fields */
|
||||
__u16 l_i_gid_high; /* were reserved2[0] */
|
||||
__u32 l_i_reserved2;
|
||||
} linux2;
|
||||
struct {
|
||||
__u8 h_i_frag; /* Fragment number */
|
||||
__u8 h_i_fsize; /* Fragment size */
|
||||
__u16 h_i_mode_high;
|
||||
__u16 h_i_uid_high;
|
||||
__u16 h_i_gid_high;
|
||||
__u32 h_i_author;
|
||||
} hurd2;
|
||||
struct {
|
||||
__u8 m_i_frag; /* Fragment number */
|
||||
__u8 m_i_fsize; /* Fragment size */
|
||||
__u16 m_pad1;
|
||||
__u32 m_i_reserved2[2];
|
||||
} masix2;
|
||||
} osd2; /* OS dependent 2 */
|
||||
};
|
||||
|
||||
#define i_size_high i_dir_acl
|
||||
|
||||
#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_uid_low i_uid
|
||||
#define i_gid_low i_gid
|
||||
#define i_uid_high osd2.linux2.l_i_uid_high
|
||||
#define i_gid_high osd2.linux2.l_i_gid_high
|
||||
#define i_reserved2 osd2.linux2.l_i_reserved2
|
||||
|
||||
#elif defined(__GNU__)
|
||||
|
||||
#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
|
||||
|
||||
#elif defined(__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 /* defined(__KERNEL) || defined(__linux__) */
|
||||
|
||||
/*
|
||||
* File system states
|
||||
*/
|
||||
#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */
|
||||
#define EXT2_ERROR_FS 0x0002 /* Errors detected */
|
||||
|
||||
/*
|
||||
* Mount flags
|
||||
*/
|
||||
#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */
|
||||
#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */
|
||||
#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */
|
||||
#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */
|
||||
#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
|
||||
#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
|
||||
#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
|
||||
#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
|
||||
|
||||
#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
|
||||
#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
|
||||
#define test_opt(sb, opt) ((sb)->u.ext2_sb.s_mount_opt & \
|
||||
EXT2_MOUNT_##opt)
|
||||
/*
|
||||
* Maximal mount counts between two filesystem checks
|
||||
*/
|
||||
#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
|
||||
#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */
|
||||
|
||||
/*
|
||||
* Behaviour when detecting errors
|
||||
*/
|
||||
#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */
|
||||
#define EXT2_ERRORS_RO 2 /* Remount fs read-only */
|
||||
#define EXT2_ERRORS_PANIC 3 /* Panic */
|
||||
#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE
|
||||
|
||||
/*
|
||||
* Structure of the super block
|
||||
*/
|
||||
struct ext2_super_block {
|
||||
__u32 s_inodes_count; /* Inodes count */
|
||||
__u32 s_blocks_count; /* Blocks count */
|
||||
__u32 s_r_blocks_count; /* Reserved blocks count */
|
||||
__u32 s_free_blocks_count; /* Free blocks count */
|
||||
__u32 s_free_inodes_count; /* Free inodes count */
|
||||
__u32 s_first_data_block; /* First Data Block */
|
||||
__u32 s_log_block_size; /* Block size */
|
||||
__s32 s_log_frag_size; /* Fragment size */
|
||||
__u32 s_blocks_per_group; /* # Blocks per group */
|
||||
__u32 s_frags_per_group; /* # Fragments per group */
|
||||
__u32 s_inodes_per_group; /* # Inodes per group */
|
||||
__u32 s_mtime; /* Mount time */
|
||||
__u32 s_wtime; /* Write time */
|
||||
__u16 s_mnt_count; /* Mount count */
|
||||
__s16 s_max_mnt_count; /* Maximal mount count */
|
||||
__u16 s_magic; /* Magic signature */
|
||||
__u16 s_state; /* File system state */
|
||||
__u16 s_errors; /* Behaviour when detecting errors */
|
||||
__u16 s_minor_rev_level; /* minor revision level */
|
||||
__u32 s_lastcheck; /* time of last check */
|
||||
__u32 s_checkinterval; /* max. time between checks */
|
||||
__u32 s_creator_os; /* OS */
|
||||
__u32 s_rev_level; /* Revision level */
|
||||
__u16 s_def_resuid; /* Default uid for reserved blocks */
|
||||
__u16 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...
|
||||
*/
|
||||
__u32 s_first_ino; /* First non-reserved inode */
|
||||
__u16 s_inode_size; /* size of inode structure */
|
||||
__u16 s_block_group_nr; /* block group # of this superblock */
|
||||
__u32 s_feature_compat; /* compatible feature set */
|
||||
__u32 s_feature_incompat; /* incompatible feature set */
|
||||
__u32 s_feature_ro_compat; /* readonly-compatible feature set */
|
||||
__u8 s_uuid[16]; /* 128-bit uuid for volume */
|
||||
char s_volume_name[16]; /* volume name */
|
||||
char s_last_mounted[64]; /* directory where last mounted */
|
||||
__u32 s_algorithm_usage_bitmap; /* For compression */
|
||||
/*
|
||||
* Performance hints. Directory preallocation should only
|
||||
* happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
|
||||
*/
|
||||
__u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
|
||||
__u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
|
||||
__u16 s_padding1;
|
||||
/*
|
||||
* Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
|
||||
*/
|
||||
__u8 s_journal_uuid[16]; /* uuid of journal superblock */
|
||||
__u32 s_journal_inum; /* inode number of journal file */
|
||||
__u32 s_journal_dev; /* device number of journal file */
|
||||
__u32 s_last_orphan; /* start of list of inodes to delete */
|
||||
|
||||
__u32 s_reserved[197]; /* Padding to the end of the block */
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#define EXT2_SB(sb) (&((sb)->u.ext2_sb))
|
||||
#else
|
||||
/* Assume that user mode programs are passing in an ext2fs superblock, not
|
||||
* a kernel struct super_block. This will allow us to call the feature-test
|
||||
* macros from user land. */
|
||||
#define EXT2_SB(sb) (sb)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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
|
||||
#define EXT2_OS_WINNT 5
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
#define EXT2_GOOD_OLD_INODE_SIZE 128
|
||||
|
||||
/*
|
||||
* Feature set definitions
|
||||
*/
|
||||
|
||||
#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \
|
||||
( EXT2_SB(sb)->s_feature_compat & (mask) )
|
||||
#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \
|
||||
( EXT2_SB(sb)->s_feature_ro_compat & (mask) )
|
||||
#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \
|
||||
( EXT2_SB(sb)->s_feature_incompat & (mask) )
|
||||
|
||||
#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
|
||||
#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002
|
||||
#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
|
||||
#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008
|
||||
#define EXT2_FEATURE_COMPAT_RESIZE_INODE 0x0010
|
||||
#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020
|
||||
|
||||
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
|
||||
#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
|
||||
#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
|
||||
|
||||
#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
|
||||
#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
|
||||
#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
|
||||
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
|
||||
|
||||
#define EXT2_FEATURE_COMPAT_SUPP 0
|
||||
#define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE
|
||||
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
|
||||
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
|
||||
EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
|
||||
|
||||
/*
|
||||
* Default values for user and/or group using reserved blocks
|
||||
*/
|
||||
#define EXT2_DEF_RESUID 0
|
||||
#define EXT2_DEF_RESGID 0
|
||||
|
||||
/*
|
||||
* Structure of a directory entry
|
||||
*/
|
||||
#define EXT2_NAME_LEN 255
|
||||
|
||||
struct ext2_dir_entry {
|
||||
__u32 inode; /* Inode number */
|
||||
__u16 rec_len; /* Directory entry length */
|
||||
__u16 name_len; /* Name length */
|
||||
char name[EXT2_NAME_LEN]; /* File name */
|
||||
};
|
||||
|
||||
/*
|
||||
* The new version of the directory entry. Since EXT2 structures are
|
||||
* stored in intel byte order, and the name_len field could never be
|
||||
* bigger than 255 chars, it's safe to reclaim the extra byte for the
|
||||
* file_type field.
|
||||
*/
|
||||
struct ext2_dir_entry_2 {
|
||||
__u32 inode; /* Inode number */
|
||||
__u16 rec_len; /* Directory entry length */
|
||||
__u8 name_len; /* Name length */
|
||||
__u8 file_type;
|
||||
char name[EXT2_NAME_LEN]; /* File name */
|
||||
};
|
||||
|
||||
/*
|
||||
* Ext2 directory file types. Only the low 3 bits are used. The
|
||||
* other bits are reserved for now.
|
||||
*/
|
||||
#define EXT2_FT_UNKNOWN 0
|
||||
#define EXT2_FT_REG_FILE 1
|
||||
#define EXT2_FT_DIR 2
|
||||
#define EXT2_FT_CHRDEV 3
|
||||
#define EXT2_FT_BLKDEV 4
|
||||
#define EXT2_FT_FIFO 5
|
||||
#define EXT2_FT_SOCK 6
|
||||
#define EXT2_FT_SYMLINK 7
|
||||
|
||||
#define EXT2_FT_MAX 8
|
||||
|
||||
/*
|
||||
* EXT2_DIR_PAD defines the directory entries boundaries
|
||||
*
|
||||
* NOTE: It must be a multiple of 4
|
||||
*/
|
||||
#define EXT2_DIR_PAD 4
|
||||
#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
|
||||
#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
|
||||
~EXT2_DIR_ROUND)
|
||||
|
||||
#ifdef __KERNEL__
|
||||
/*
|
||||
* Function prototypes
|
||||
*/
|
||||
|
||||
/*
|
||||
* Ok, these declarations are also in <linux/kernel.h> but none of the
|
||||
* ext2 source programs needs to include it so they are duplicated here.
|
||||
*/
|
||||
# define NORET_TYPE /**/
|
||||
# define ATTRIB_NORET __attribute__((noreturn))
|
||||
# define NORET_AND noreturn,
|
||||
|
||||
/* acl.c */
|
||||
extern int ext2_permission (struct inode *, int);
|
||||
|
||||
/* balloc.c */
|
||||
extern int ext2_bg_has_super(struct super_block *sb, int group);
|
||||
extern unsigned long ext2_bg_num_gdb(struct super_block *sb, int group);
|
||||
extern int ext2_new_block (const struct inode *, unsigned long,
|
||||
__u32 *, __u32 *, int *);
|
||||
extern void ext2_free_blocks (const struct inode *, unsigned long,
|
||||
unsigned long);
|
||||
extern unsigned long ext2_count_free_blocks (struct super_block *);
|
||||
extern void ext2_check_blocks_bitmap (struct super_block *);
|
||||
extern struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
|
||||
unsigned int block_group,
|
||||
struct buffer_head ** bh);
|
||||
|
||||
/* bitmap.c */
|
||||
extern unsigned long ext2_count_free (struct buffer_head *, unsigned);
|
||||
|
||||
/* dir.c */
|
||||
extern int ext2_check_dir_entry (const char *, struct inode *,
|
||||
struct ext2_dir_entry_2 *, struct buffer_head *,
|
||||
unsigned long);
|
||||
|
||||
/* file.c */
|
||||
extern int ext2_read (struct inode *, struct file *, char *, int);
|
||||
extern int ext2_write (struct inode *, struct file *, char *, int);
|
||||
|
||||
/* fsync.c */
|
||||
extern int ext2_sync_file (struct file *, struct dentry *, int);
|
||||
extern int ext2_fsync_inode (struct inode *, int);
|
||||
|
||||
/* ialloc.c */
|
||||
extern struct inode * ext2_new_inode (const struct inode *, int);
|
||||
extern void ext2_free_inode (struct inode *);
|
||||
extern unsigned long ext2_count_free_inodes (struct super_block *);
|
||||
extern void ext2_check_inodes_bitmap (struct super_block *);
|
||||
|
||||
/* inode.c */
|
||||
|
||||
extern struct buffer_head * ext2_getblk (struct inode *, long, int, int *);
|
||||
extern struct buffer_head * ext2_bread (struct inode *, int, int, int *);
|
||||
|
||||
extern void ext2_read_inode (struct inode *);
|
||||
extern void ext2_write_inode (struct inode *, int);
|
||||
extern void ext2_put_inode (struct inode *);
|
||||
extern void ext2_delete_inode (struct inode *);
|
||||
extern int ext2_sync_inode (struct inode *);
|
||||
extern void ext2_discard_prealloc (struct inode *);
|
||||
|
||||
/* ioctl.c */
|
||||
extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
|
||||
unsigned long);
|
||||
|
||||
/* namei.c */
|
||||
extern struct inode_operations ext2_dir_inode_operations;
|
||||
|
||||
/* super.c */
|
||||
extern void ext2_error (struct super_block *, const char *, const char *, ...)
|
||||
__attribute__ ((format (printf, 3, 4)));
|
||||
extern NORET_TYPE void ext2_panic (struct super_block *, const char *,
|
||||
const char *, ...)
|
||||
__attribute__ ((NORET_AND format (printf, 3, 4)));
|
||||
extern void ext2_warning (struct super_block *, const char *, const char *, ...)
|
||||
__attribute__ ((format (printf, 3, 4)));
|
||||
extern void ext2_update_dynamic_rev (struct super_block *sb);
|
||||
extern void ext2_put_super (struct super_block *);
|
||||
extern void ext2_write_super (struct super_block *);
|
||||
extern int ext2_remount (struct super_block *, int *, char *);
|
||||
extern struct super_block * ext2_read_super (struct super_block *,void *,int);
|
||||
extern int ext2_statfs (struct super_block *, struct statfs *);
|
||||
|
||||
/* truncate.c */
|
||||
extern void ext2_truncate (struct inode *);
|
||||
|
||||
/*
|
||||
* Inodes and files operations
|
||||
*/
|
||||
|
||||
/* dir.c */
|
||||
extern struct file_operations ext2_dir_operations;
|
||||
|
||||
/* file.c */
|
||||
extern struct inode_operations ext2_file_inode_operations;
|
||||
extern struct file_operations ext2_file_operations;
|
||||
|
||||
/* symlink.c */
|
||||
extern struct inode_operations ext2_fast_symlink_inode_operations;
|
||||
|
||||
extern struct address_space_operations ext2_aops;
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _LINUX_EXT2_FS_H */
|
10
reactos/lib/fslib/ext2lib/types.h
Normal file
10
reactos/lib/fslib/ext2lib/types.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef _LINUX_TYPES_H
|
||||
#define _LINUX_TYPES_H
|
||||
|
||||
typedef unsigned long __u32;
|
||||
typedef signed long __s32;
|
||||
typedef unsigned short int __u16;
|
||||
typedef signed short int __s16;
|
||||
typedef unsigned char __u8;
|
||||
|
||||
#endif /* LINUX_TYPES_H */
|
Loading…
Add table
Add a link
Reference in a new issue