Import the FFS driver by Jae-Hong Lee.
Patch by Peter Hater

CORE-11040

svn path=/trunk/; revision=71425
This commit is contained in:
Pierre Schweitzer 2016-05-27 12:08:38 +00:00
parent c8fc495780
commit 3a3ef631d1
35 changed files with 36396 additions and 0 deletions

View file

@ -4,6 +4,7 @@ add_subdirectory(cdfs)
add_subdirectory(ext2)
add_subdirectory(fastfat)
#add_subdirectory(fastfat_new)
add_subdirectory(ffs)
add_subdirectory(fs_rec)
add_subdirectory(msfs)
add_subdirectory(mup)

View file

@ -0,0 +1,48 @@
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/drivers
inc)
list(APPEND SOURCE
src/block.c
src/cleanup.c
src/close.c
src/cmcb.c
src/create.c
src/debug.c
src/devctl.c
src/dirctl.c
src/dispatch.c
src/except.c
src/fastio.c
src/ffs.c
src/fileinfo.c
src/flush.c
src/fsctl.c
src/init.c
src/lock.c
src/memory.c
src/misc.c
src/pnp.c
src/read.c
src/shutdown.c
src/volinfo.c
src/write.c
inc/ffsdrv.h)
add_library(ffs SHARED ${SOURCE} src/ffsdrv.rc)
if(NOT MSVC)
add_target_compile_flags(ffs "-Wno-pointer-sign -Wno-unused-function")
if(NOT CMAKE_C_COMPILER_ID STREQUAL "Clang")
add_target_compile_flags(ffs "-Wno-unused-but-set-variable -Wno-unused-variable -Wno-missing-braces")
endif()
#else()
# replace_compile_flags("/we\"4189\"" " ")
endif()
add_definitions(-D__KERNEL__)
set_module_type(ffs kernelmodedriver)
target_link_libraries(ffs memcmp ${PSEH_LIB})
add_importlibs(ffs ntoskrnl hal)
add_pch(ffs inc/ffsdrv.h SOURCE)
add_cd_file(TARGET ffs DESTINATION reactos/system32/drivers NO_CAB FOR all)

View file

@ -0,0 +1,892 @@
/* $NetBSD: bootblock.h,v 1.24 2004/03/22 07:11:00 lukem Exp $ */
/*-
* Copyright (c) 2002-2004 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo,
* Michael L. Finch, Bradley A. Grantham, and
* Lawrence A. Kesteloot
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the Alice Group.
* 4. The names of the Alice Group or any of its members may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE ALICE GROUP BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
* Copyright (c) 1994, 1999 Christopher G. Demetriou
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Christopher G. Demetriou
* for the NetBSD Project.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1994 Rolf Grossmann
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Rolf Grossmann.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SYS_BOOTBLOCK_H
#define _SYS_BOOTBLOCK_H
#include "type.h"
#if 0 /* XXX ffsdrv */
#if !defined(__ASSEMBLER__)
#if defined(_KERNEL) || defined(_STANDALONE)
#include <sys/stdint.h>
#else
#include <stdint.h>
#endif
#endif /* !defined(__ASSEMBLER__) */
#endif
/* ------------------------------------------
* MBR (Master Boot Record) --
* definitions for systems that use MBRs
*/
/*
* Layout of boot records:
*
* Byte range Use Description
* ---------- --- -----------
*
* 0 - 2 FMP JMP xxx, NOP
* 3 - 10 FP OEM Name
*
* 11 - 61 FMP FAT12/16 BPB
* Whilst not strictly necessary for MBR,
* GRUB reserves this area
*
* 11 - 89 P FAT32 BPB
* (are we ever going to boot off this?)
*
*
* 62 - 217 FMP Boot code
*
* 90 - 217 P FAT32 boot code
*
* 218 - 223 M Win95b/98/me "drive time"
* http://www.geocities.com/thestarman3/asm/mbr/95BMEMBR.htm#MYST
* only changed if all 6 bytes are 0
*
* 224 - 436 FMP boot code (continued)
*
* 437 - 439 M WinNT/2K/XP MBR "boot language"
* http://www.geocities.com/thestarman3/asm/mbr/Win2kmbr.htm
* not needed by us
*
* 400 - 439 MP NetBSD: mbr_bootsel
*
* 440 - 443 M WinNT/2K/XP Drive Serial Number (NT DSN)
* http://www.geocities.com/thestarman3/asm/mbr/Win2kmbr.htm
*
* 444 - 445 FMP bootcode or unused
* NetBSD: mbr_bootsel_magic
*
* 446 - 509 M partition table
*
* 510 - 511 FMP magic number (0xAA55)
*
* Use:
* ----
* F Floppy boot sector
* M Master Boot Record
* P Partition Boot record
*
*/
/*
* MBR (Master Boot Record)
*/
#define MBR_BBSECTOR 0 /* MBR relative sector # */
#define MBR_BPB_OFFSET 11 /* offsetof(mbr_sector, mbr_bpb) */
#define MBR_BOOTCODE_OFFSET 90 /* offsetof(mbr_sector, mbr_bootcode) */
#define MBR_BS_OFFSET 400 /* offsetof(mbr_sector, mbr_bootsel) */
#define MBR_DSN_OFFSET 440 /* offsetof(mbr_sector, mbr_dsn) */
#define MBR_BS_MAGIC_OFFSET 444 /* offsetof(mbr_sector, mbr_bootsel_magic) */
#define MBR_PART_OFFSET 446 /* offsetof(mbr_sector, mbr_part[0]) */
#define MBR_MAGIC_OFFSET 510 /* offsetof(mbr_sector, mbr_magic) */
#define MBR_MAGIC 0xaa55 /* MBR magic number */
#define MBR_BS_MAGIC 0xb5e1 /* mbr_bootsel magic number */
#define MBR_PART_COUNT 4 /* Number of partitions in MBR */
#define MBR_BS_PARTNAMESIZE 8 /* Size of name mbr_bootsel nametab */
/* (excluding trailing NUL) */
/* values for mbr_partition.mbrp_flag */
#define MBR_PFLAG_ACTIVE 0x80 /* The active partition */
/* values for mbr_partition.mbrp_type */
#define MBR_PTYPE_FAT12 0x01 /* 12-bit FAT */
#define MBR_PTYPE_FAT16S 0x04 /* 16-bit FAT, less than 32M */
#define MBR_PTYPE_EXT 0x05 /* extended partition */
#define MBR_PTYPE_FAT16B 0x06 /* 16-bit FAT, more than 32M */
#define MBR_PTYPE_NTFS 0x07 /* OS/2 HPFS, NTFS, QNX2, Adv. UNIX */
#define MBR_PTYPE_FAT32 0x0b /* 32-bit FAT */
#define MBR_PTYPE_FAT32L 0x0c /* 32-bit FAT, LBA-mapped */
#define MBR_PTYPE_FAT16L 0x0e /* 16-bit FAT, LBA-mapped */
#define MBR_PTYPE_EXT_LBA 0x0f /* extended partition, LBA-mapped */
#define MBR_PTYPE_ONTRACK 0x54
#define MBR_PTYPE_LNXSWAP 0x82 /* Linux swap or Solaris */
#define MBR_PTYPE_LNXEXT2 0x83 /* Linux native */
#define MBR_PTYPE_EXT_LNX 0x85 /* Linux extended partition */
#define MBR_PTYPE_NTFSVOL 0x87 /* NTFS volume set or HPFS mirrored */
#define MBR_PTYPE_PREP 0x41 /* PReP */
#define MBR_PTYPE_386BSD 0xa5 /* 386BSD partition type */
#define MBR_PTYPE_APPLEUFS 0xa8 /* Apple UFS */
#define MBR_PTYPE_NETBSD 0xa9 /* NetBSD partition type */
#define MBR_PTYPE_OPENBSD 0xa6 /* OpenBSD partition type */
#define MBR_PSECT(s) ((s) & 0x3f)
#define MBR_PCYL(c, s) ((c) + (((s) & 0xc0) << 2))
#define MBR_IS_EXTENDED(x) ((x) == MBR_PTYPE_EXT || \
(x) == MBR_PTYPE_EXT_LBA || \
(x) == MBR_PTYPE_EXT_LNX)
/* values for mbr_bootsel.mbrbs_flags */
#define MBR_BS_ACTIVE 0x01 /* Bootselector active (or code present) */
#define MBR_BS_EXTINT13 0x02 /* Set by fdisk if LBA needed (deprecated) */
#define MBR_BS_READ_LBA 0x04 /* Force LBA reads - even for low numbers */
#define MBR_BS_EXTLBA 0x08 /* Extended ptn capable (LBA reads) */
#define MBR_BS_NEWMBR 0x80 /* New bootsel at offset 440 */
#if !defined(__ASSEMBLER__) /* { */
#pragma pack(1)
/*
* (x86) BIOS Parameter Block for FAT12
*/
struct mbr_bpbFAT12 {
uint16_t bpbBytesPerSec; /* bytes per sector */
uint8_t bpbSecPerClust; /* sectors per cluster */
uint16_t bpbResSectors; /* number of reserved sectors */
uint8_t bpbFATs; /* number of FATs */
uint16_t bpbRootDirEnts; /* number of root directory entries */
uint16_t bpbSectors; /* total number of sectors */
uint8_t bpbMedia; /* media descriptor */
uint16_t bpbFATsecs; /* number of sectors per FAT */
uint16_t bpbSecPerTrack; /* sectors per track */
uint16_t bpbHeads; /* number of heads */
uint16_t bpbHiddenSecs; /* # of hidden sectors */
}; /* __attribute__((__packed__)); */
/*
* (x86) BIOS Parameter Block for FAT16
*/
struct mbr_bpbFAT16 {
uint16_t bpbBytesPerSec; /* bytes per sector */
uint8_t bpbSecPerClust; /* sectors per cluster */
uint16_t bpbResSectors; /* number of reserved sectors */
uint8_t bpbFATs; /* number of FATs */
uint16_t bpbRootDirEnts; /* number of root directory entries */
uint16_t bpbSectors; /* total number of sectors */
uint8_t bpbMedia; /* media descriptor */
uint16_t bpbFATsecs; /* number of sectors per FAT */
uint16_t bpbSecPerTrack; /* sectors per track */
uint16_t bpbHeads; /* number of heads */
uint32_t bpbHiddenSecs; /* # of hidden sectors */
uint32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */
uint8_t bsDrvNum; /* Int 0x13 drive number (e.g. 0x80) */
uint8_t bsReserved1; /* Reserved; set to 0 */
uint8_t bsBootSig; /* 0x29 if next 3 fields are present */
uint8_t bsVolID[4]; /* Volume serial number */
uint8_t bsVolLab[11]; /* Volume label */
uint8_t bsFileSysType[8];
/* "FAT12 ", "FAT16 ", "FAT " */
}; /* __attribute__((__packed__)); */
/*
* (x86) BIOS Parameter Block for FAT32
*/
struct mbr_bpbFAT32 {
uint16_t bpbBytesPerSec; /* bytes per sector */
uint8_t bpbSecPerClust; /* sectors per cluster */
uint16_t bpbResSectors; /* number of reserved sectors */
uint8_t bpbFATs; /* number of FATs */
uint16_t bpbRootDirEnts; /* number of root directory entries */
uint16_t bpbSectors; /* total number of sectors */
uint8_t bpbMedia; /* media descriptor */
uint16_t bpbFATsecs; /* number of sectors per FAT */
uint16_t bpbSecPerTrack; /* sectors per track */
uint16_t bpbHeads; /* number of heads */
uint32_t bpbHiddenSecs; /* # of hidden sectors */
uint32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */
uint32_t bpbBigFATsecs; /* like bpbFATsecs for FAT32 */
uint16_t bpbExtFlags; /* extended flags: */
#define MBR_FAT32_FATNUM 0x0F /* mask for numbering active FAT */
#define MBR_FAT32_FATMIRROR 0x80 /* FAT is mirrored (as previously) */
uint16_t bpbFSVers; /* filesystem version */
#define MBR_FAT32_FSVERS 0 /* currently only 0 is understood */
uint32_t bpbRootClust; /* start cluster for root directory */
uint16_t bpbFSInfo; /* filesystem info structure sector */
uint16_t bpbBackup; /* backup boot sector */
uint8_t bsReserved[12]; /* Reserved for future expansion */
uint8_t bsDrvNum; /* Int 0x13 drive number (e.g. 0x80) */
uint8_t bsReserved1; /* Reserved; set to 0 */
uint8_t bsBootSig; /* 0x29 if next 3 fields are present */
uint8_t bsVolID[4]; /* Volume serial number */
uint8_t bsVolLab[11]; /* Volume label */
uint8_t bsFileSysType[8]; /* "FAT32 " */
}; /* __attribute__((__packed__)); */
/*
* (x86) MBR boot selector
*/
struct mbr_bootsel {
uint8_t mbrbs_defkey;
uint8_t mbrbs_flags;
uint16_t mbrbs_timeo;
uint8_t mbrbs_nametab[MBR_PART_COUNT][MBR_BS_PARTNAMESIZE + 1];
}; /* __attribute__((__packed__)); */
/*
* MBR partition
*/
struct mbr_partition {
uint8_t mbrp_flag; /* MBR partition flags */
uint8_t mbrp_shd; /* Starting head */
uint8_t mbrp_ssect; /* Starting sector */
uint8_t mbrp_scyl; /* Starting cylinder */
uint8_t mbrp_type; /* Partition type (see below) */
uint8_t mbrp_ehd; /* End head */
uint8_t mbrp_esect; /* End sector */
uint8_t mbrp_ecyl; /* End cylinder */
uint32_t mbrp_start; /* Absolute starting sector number */
uint32_t mbrp_size; /* Partition size in sectors */
}; /* __attribute__((__packed__)); */
int xlat_mbr_fstype(int); /* in sys/lib/libkern/xlat_mbr_fstype.c */
/*
* MBR boot sector.
* This is used by both the MBR (Master Boot Record) in sector 0 of the disk
* and the PBR (Partition Boot Record) in sector 0 of an MBR partition.
*/
struct mbr_sector {
/* Jump instruction to boot code. */
/* Usually 0xE9nnnn or 0xEBnn90 */
uint8_t mbr_jmpboot[3];
/* OEM name and version */
uint8_t mbr_oemname[8];
union { /* BIOS Parameter Block */
struct mbr_bpbFAT12 bpb12;
struct mbr_bpbFAT16 bpb16;
struct mbr_bpbFAT32 bpb32;
} mbr_bpb;
/* Boot code */
uint8_t mbr_bootcode[310];
/* Config for /usr/mdec/mbr_bootsel */
struct mbr_bootsel mbr_bootsel;
/* NT Drive Serial Number */
uint32_t mbr_dsn;
/* mbr_bootsel magic */
uint16_t mbr_bootsel_magic;
/* MBR partition table */
struct mbr_partition mbr_parts[MBR_PART_COUNT];
/* MBR magic (0xaa55) */
uint16_t mbr_magic;
}; /* __attribute__((__packed__)); */
#endif /* !defined(__ASSEMBLER__) */ /* } */
#pragma pack()
/* ------------------------------------------
* shared --
* definitions shared by many platforms
*/
#if !defined(__ASSEMBLER__) /* { */
/* Maximum # of blocks in bbi_block_table, each bbi_block_size long */
#define SHARED_BBINFO_MAXBLOCKS 118 /* so sizeof(shared_bbinfo) == 512 */
struct shared_bbinfo {
uint8_t bbi_magic[32];
int32_t bbi_block_size;
int32_t bbi_block_count;
int32_t bbi_block_table[SHARED_BBINFO_MAXBLOCKS];
};
#if 0 /* XXX ffsdrv */
/* ------------------------------------------
* alpha --
* Alpha (disk, but also tape) Boot Block.
*
* See Section (III) 3.6.1 of the Alpha Architecture Reference Manual.
*/
struct alpha_boot_block {
uint64_t bb_data[63]; /* data (disklabel, also as below) */
uint64_t bb_cksum; /* checksum of the boot block,
* taken as uint64_t's
*/
};
#define bb_secsize bb_data[60] /* secondary size (blocks) */
#define bb_secstart bb_data[61] /* secondary start (blocks) */
#define bb_flags bb_data[62] /* unknown flags (set to zero) */
#define ALPHA_BOOT_BLOCK_OFFSET 0 /* offset of boot block. */
#define ALPHA_BOOT_BLOCK_BLOCKSIZE 512 /* block size for sector
* size/start, and for boot
* block itself.
*/
#define ALPHA_BOOT_BLOCK_CKSUM(bb,cksum) \
do { \
const struct alpha_boot_block *_bb = (bb); \
uint64_t _cksum; \
int _i; \
\
_cksum = 0; \
for (_i = 0; \
_i < (sizeof _bb->bb_data / sizeof _bb->bb_data[0]); \
_i++) \
_cksum += _bb->bb_data[_i]; \
*(cksum) = _cksum; \
} while (/*CONSTCOND*/ 0)
/* ------------------------------------------
* apple --
* Apple computers boot block related information
*/
/*
* Driver Descriptor Map, from Inside Macintosh: Devices, SCSI Manager
* pp 12-13. The driver descriptor map always resides on physical block 0.
*/
struct apple_drvr_descriptor {
uint32_t descBlock; /* first block of driver */
uint16_t descSize; /* driver size in blocks */
uint16_t descType; /* system type */
};
/*
* system types; Apple reserves 0-15
*/
#define APPLE_DRVR_TYPE_MACINTOSH 1
#define APPLE_DRVR_MAP_MAGIC 0x4552
#define APPLE_DRVR_MAP_MAX_DESCRIPTORS 61
struct apple_drvr_map {
uint16_t sbSig; /* map signature */
uint16_t sbBlockSize; /* block size of device */
uint32_t sbBlkCount; /* number of blocks on device */
uint16_t sbDevType; /* (used internally by ROM) */
uint16_t sbDevID; /* (used internally by ROM) */
uint32_t sbData; /* (used internally by ROM) */
uint16_t sbDrvrCount; /* number of driver descriptors */
struct apple_drvr_descriptor sb_dd[APPLE_DRVR_MAP_MAX_DESCRIPTORS];
uint16_t pad[3];
} __attribute__((__packed__));
/*
* Partition map structure from Inside Macintosh: Devices, SCSI Manager
* pp. 13-14. The partition map always begins on physical block 1.
*
* With the exception of block 0, all blocks on the disk must belong to
* exactly one partition. The partition map itself belongs to a partition
* of type `APPLE_PARTITION_MAP', and is not limited in size by anything
* other than available disk space. The partition map is not necessarily
* the first partition listed.
*/
#define APPLE_PART_MAP_ENTRY_MAGIC 0x504d
struct apple_part_map_entry {
uint16_t pmSig; /* partition signature */
uint16_t pmSigPad; /* (reserved) */
uint32_t pmMapBlkCnt; /* number of blocks in partition map */
uint32_t pmPyPartStart; /* first physical block of partition */
uint32_t pmPartBlkCnt; /* number of blocks in partition */
uint8_t pmPartName[32]; /* partition name */
uint8_t pmPartType[32]; /* partition type */
uint32_t pmLgDataStart; /* first logical block of data area */
uint32_t pmDataCnt; /* number of blocks in data area */
uint32_t pmPartStatus; /* partition status information */
uint32_t pmLgBootStart; /* first logical block of boot code */
uint32_t pmBootSize; /* size of boot code, in bytes */
uint32_t pmBootLoad; /* boot code load address */
uint32_t pmBootLoad2; /* (reserved) */
uint32_t pmBootEntry; /* boot code entry point */
uint32_t pmBootEntry2; /* (reserved) */
uint32_t pmBootCksum; /* boot code checksum */
int8_t pmProcessor[16]; /* processor type (e.g. "68020") */
uint8_t pmBootArgs[128]; /* A/UX boot arguments */
uint8_t pad[248]; /* pad to end of block */
};
#define APPLE_PART_TYPE_DRIVER "APPLE_DRIVER"
#define APPLE_PART_TYPE_DRIVER43 "APPLE_DRIVER43"
#define APPLE_PART_TYPE_DRIVERATA "APPLE_DRIVER_ATA"
#define APPLE_PART_TYPE_DRIVERIOKIT "APPLE_DRIVER_IOKIT"
#define APPLE_PART_TYPE_FWDRIVER "APPLE_FWDRIVER"
#define APPLE_PART_TYPE_FWB_COMPONENT "FWB DRIVER COMPONENTS"
#define APPLE_PART_TYPE_FREE "APPLE_FREE"
#define APPLE_PART_TYPE_MAC "APPLE_HFS"
#define APPLE_PART_TYPE_NETBSD "NETBSD"
#define APPLE_PART_TYPE_NBSD_PPCBOOT "NETBSD/MACPPC"
#define APPLE_PART_TYPE_NBSD_68KBOOT "NETBSD/MAC68K"
#define APPLE_PART_TYPE_PATCHES "APPLE_PATCHES"
#define APPLE_PART_TYPE_PARTMAP "APPLE_PARTITION_MAP"
#define APPLE_PART_TYPE_PATCHES "APPLE_PATCHES"
#define APPLE_PART_TYPE_SCRATCH "APPLE_SCRATCH"
#define APPLE_PART_TYPE_UNIX "APPLE_UNIX_SVR2"
/*
* "pmBootArgs" for APPLE_UNIX_SVR2 partition.
* NetBSD/mac68k only uses Magic, Cluster, Type, and Flags.
*/
struct apple_blockzeroblock {
uint32_t bzbMagic;
uint8_t bzbCluster;
uint8_t bzbType;
uint16_t bzbBadBlockInode;
uint16_t bzbFlags;
uint16_t bzbReserved;
uint32_t bzbCreationTime;
uint32_t bzbMountTime;
uint32_t bzbUMountTime;
};
#define APPLE_BZB_MAGIC 0xABADBABE
#define APPLE_BZB_TYPEFS 1
#define APPLE_BZB_TYPESWAP 3
#define APPLE_BZB_ROOTFS 0x8000
#define APPLE_BZB_USRFS 0x4000
/* ------------------------------------------
* hp300
*
*/
/* volume header for "LIF" format volumes */
struct hp300_lifvol {
int16_t vol_id;
char vol_label[6];
int32_t vol_addr;
int16_t vol_oct;
int16_t vol_dummy;
int32_t vol_dirsize;
int16_t vol_version;
int16_t vol_zero;
int32_t vol_huh1;
int32_t vol_huh2;
int32_t vol_length;
};
/* LIF directory entry format */
struct hp300_lifdir {
char dir_name[10];
int16_t dir_type;
int32_t dir_addr;
int32_t dir_length;
char dir_toc[6];
int16_t dir_flag;
int32_t dir_exec;
};
/* load header for boot rom */
struct hp300_load {
int32_t address;
int32_t count;
};
#define HP300_VOL_ID -32768
#define HP300_VOL_OCT 4096
#define HP300_DIR_TYPE -5822
#define HP300_DIR_FLAG 0x8001 /* dont ask me! */
#define HP300_SECTSIZE 256
#endif
/* ------------------------------------------
* x86
*
*/
/*
* Parameters for NetBSD /boot written to start of pbr code by installboot
*/
struct x86_boot_params {
uint32_t bp_length; /* length of patchable data */
uint32_t bp_flags;
uint32_t bp_timeout; /* boot timeout in seconds */
uint32_t bp_consdev;
uint32_t bp_conspeed;
uint8_t bp_password[16]; /* md5 hash of password */
char bp_keymap[16]; /* keyboard traslation map */
};
#endif /* !defined(__ASSEMBLER__) */ /* } */
#define X86_BOOT_MAGIC(n) ('x' << 24 | 0x86b << 12 | 'm' << 4 | (n))
#define X86_BOOT_MAGIC_1 X86_BOOT_MAGIC(1) /* pbr.S */
#define X86_BOOT_MAGIC_2 X86_BOOT_MAGIC(2) /* bootxx.S */
#define X86_BOOT_MAGIC_PXE X86_BOOT_MAGIC(3) /* start_pxe.S */
/* values for bp_flags */
#define X86_BP_FLAGS_RESET_VIDEO 1
#define X86_BP_FLAGS_PASSWORD 2
/* values for bp_consdev */
#define X86_BP_CONSDEV_PC 0
#define X86_BP_CONSDEV_COM0 1
#define X86_BP_CONSDEV_COM1 2
#define X86_BP_CONSDEV_COM2 3
#define X86_BP_CONSDEV_COM3 4
#define X86_BP_CONSDEV_COM0KBD 5
#define X86_BP_CONSDEV_COM1KBD 6
#define X86_BP_CONSDEV_COM2KBD 7
#define X86_BP_CONSDEV_COM3KBD 8
#if !defined(__ASSEMBLER__) /* { */
#if 0 /* XXX ffsdrv */
/* ------------------------------------------
* macppc
*/
#define MACPPC_BOOT_BLOCK_OFFSET 2048
#define MACPPC_BOOT_BLOCK_BLOCKSIZE 512
#define MACPPC_BOOT_BLOCK_MAX_SIZE 2048 /* XXX: could be up to 6144 */
/* Magic string -- 32 bytes long (including the NUL) */
#define MACPPC_BBINFO_MAGIC "NetBSD/macppc bootxx 20020515"
/* ------------------------------------------
* news68k, newsmips
*/
#define NEWS_BOOT_BLOCK_LABELOFFSET 64 /* XXX from <machine/disklabel.h> */
#define NEWS_BOOT_BLOCK_OFFSET 0
#define NEWS_BOOT_BLOCK_BLOCKSIZE 512
#define NEWS_BOOT_BLOCK_MAX_SIZE (512 * 16)
/* Magic string -- 32 bytes long (including the NUL) */
#define NEWS68K_BBINFO_MAGIC "NetBSD/news68k bootxx 20020518"
#define NEWSMIPS_BBINFO_MAGIC "NetBSD/newsmips bootxx 20020518"
/* ------------------------------------------
* next68k
*/
#define NEXT68K_LABEL_MAXPARTITIONS 8 /* number of partitions in next68k_disklabel */
#define NEXT68K_LABEL_CPULBLLEN 24
#define NEXT68K_LABEL_MAXDNMLEN 24
#define NEXT68K_LABEL_MAXTYPLEN 24
#define NEXT68K_LABEL_MAXBFLEN 24
#define NEXT68K_LABEL_MAXHNLEN 32
#define NEXT68K_LABEL_MAXMPTLEN 16
#define NEXT68K_LABEL_MAXFSTLEN 8
#define NEXT68K_LABEL_NBAD 1670 /* sized to make label ~= 8KB */
struct next68k_partition {
int32_t cp_offset; /* starting sector */
int32_t cp_size; /* number of sectors in partition */
int16_t cp_bsize; /* block size in bytes */
int16_t cp_fsize; /* filesystem basic fragment size */
char cp_opt; /* optimization type: 's'pace/'t'ime */
char cp_pad1;
int16_t cp_cpg; /* filesystem cylinders per group */
int16_t cp_density; /* bytes per inode density */
int8_t cp_minfree; /* minfree (%) */
int8_t cp_newfs; /* run newfs during init */
char cp_mountpt[NEXT68K_LABEL_MAXMPTLEN];
/* default/standard mount point */
int8_t cp_automnt; /* auto-mount when inserted */
char cp_type[NEXT68K_LABEL_MAXFSTLEN]; /* file system type name */
char cp_pad2;
} __attribute__ ((packed));
/* The disklabel the way it is on the disk */
struct next68k_disklabel {
int32_t cd_version; /* label version */
int32_t cd_label_blkno; /* block # of this label */
int32_t cd_size; /* size of media area (sectors) */
char cd_label[NEXT68K_LABEL_CPULBLLEN]; /* disk name (label) */
uint32_t cd_flags; /* flags */
uint32_t cd_tag; /* volume tag */
char cd_name[NEXT68K_LABEL_MAXDNMLEN]; /* drive (hardware) name */
char cd_type[NEXT68K_LABEL_MAXTYPLEN]; /* drive type */
int32_t cd_secsize; /* # of bytes per sector */
int32_t cd_ntracks; /* # of tracks per cylinder */
int32_t cd_nsectors; /* # of data sectors per track */
int32_t cd_ncylinders; /* # of data cylinders per unit */
int32_t cd_rpm; /* rotational speed */
int16_t cd_front; /* # of sectors in "front porch" */
int16_t cd_back; /* # of sectors in "back porch" */
int16_t cd_ngroups; /* # of alt groups */
int16_t cd_ag_size; /* alt group size (sectors) */
int16_t cd_ag_alts; /* alternate sectors / alt group */
int16_t cd_ag_off; /* sector offset to first alternate */
int32_t cd_boot_blkno[2]; /* boot program locations */
char cd_kernel[NEXT68K_LABEL_MAXBFLEN]; /* default kernel name */
char cd_hostname[NEXT68K_LABEL_MAXHNLEN];
/* host name (usu. where disk was labeled) */
char cd_rootpartition; /* root partition letter e.g. 'a' */
char cd_rwpartition; /* r/w partition letter e.g. 'b' */
struct next68k_partition cd_partitions[NEXT68K_LABEL_MAXPARTITIONS];
union {
uint16_t CD_v3_checksum; /* label version 3 checksum */
int32_t CD_bad[NEXT68K_LABEL_NBAD];
/* block number that is bad */
} cd_un;
uint16_t cd_checksum; /* label version 1 or 2 checksum */
} __attribute__ ((packed));
#define NEXT68K_LABEL_cd_checksum cd_checksum
#define NEXT68K_LABEL_cd_v3_checksum cd_un.CD_v3_checksum
#define NEXT68K_LABEL_cd_bad cd_un.CD_bad
#define NEXT68K_LABEL_SECTOR 0 /* sector containing label */
#define NEXT68K_LABEL_OFFSET 0 /* offset of label in sector */
#define NEXT68K_LABEL_SIZE 8192 /* size of label */
#define NEXT68K_LABEL_CD_V1 0x4e655854 /* version #1: "NeXT" */
#define NEXT68K_LABEL_CD_V2 0x646c5632 /* version #2: "dlV2" */
#define NEXT68K_LABEL_CD_V3 0x646c5633 /* version #3: "dlV3" */
#define NEXT68K_LABEL_DEFAULTFRONTPORCH (160 * 2)
#define NEXT68K_LABEL_DEFAULTBOOT0_1 (32 * 2)
#define NEXT68K_LABEL_DEFAULTBOOT0_2 (96 * 2)
/* ------------------------------------------
* pmax --
* PMAX (DECstation / MIPS) boot block information
*/
/*
* If mode is 0, there is just one sequence of blocks and one Dec_BootMap
* is used. If mode is 1, there are multiple sequences of blocks
* and multiple Dec_BootMaps are used, the last with numBlocks = 0.
*/
struct pmax_boot_map {
int32_t num_blocks; /* Number of blocks to read. */
int32_t start_block; /* Starting block on disk. */
};
/*
* This is the structure of a disk or tape boot block. The boot_map
* can either be a single boot count and start block (contiguous mode)
* or a list of up to 61 (to fill a 512 byte sector) block count and
* start block pairs. Under NetBSD, contiguous mode is always used.
*/
struct pmax_boot_block {
uint8_t pad[8];
int32_t magic; /* PMAX_BOOT_MAGIC */
int32_t mode; /* Mode for boot info. */
uint32_t load_addr; /* Address to start loading. */
uint32_t exec_addr; /* Address to start execing. */
struct pmax_boot_map map[61]; /* boot program section(s). */
} __attribute__((__packed__));
#define PMAX_BOOT_MAGIC 0x0002757a
#define PMAX_BOOTMODE_CONTIGUOUS 0
#define PMAX_BOOTMODE_SCATTERED 1
#define PMAX_BOOT_BLOCK_OFFSET 0
#define PMAX_BOOT_BLOCK_BLOCKSIZE 512
/* ------------------------------------------
* sparc
*/
#define SPARC_BOOT_BLOCK_OFFSET 512
#define SPARC_BOOT_BLOCK_BLOCKSIZE 512
#define SPARC_BOOT_BLOCK_MAX_SIZE (512 * 15)
/* Magic string -- 32 bytes long (including the NUL) */
#define SPARC_BBINFO_MAGIC "NetBSD/sparc bootxx 20020515"
/* ------------------------------------------
* sparc64
*/
#define SPARC64_BOOT_BLOCK_OFFSET 512
#define SPARC64_BOOT_BLOCK_BLOCKSIZE 512
#define SPARC64_BOOT_BLOCK_MAX_SIZE (512 * 15)
/* ------------------------------------------
* sun68k (sun2, sun3)
*/
#define SUN68K_BOOT_BLOCK_OFFSET 512
#define SUN68K_BOOT_BLOCK_BLOCKSIZE 512
#define SUN68K_BOOT_BLOCK_MAX_SIZE (512 * 15)
/* Magic string -- 32 bytes long (including the NUL) */
#define SUN68K_BBINFO_MAGIC "NetBSD/sun68k bootxx 20020515"
/* ------------------------------------------
* vax --
* VAX boot block information
*/
struct vax_boot_block {
/* Note that these don't overlap any of the pmax boot block */
uint8_t pad0[2];
uint8_t bb_id_offset; /* offset in words to id (magic1)*/
uint8_t bb_mbone; /* must be one */
uint16_t bb_lbn_hi; /* lbn (hi word) of bootstrap */
uint16_t bb_lbn_low; /* lbn (low word) of bootstrap */
uint8_t pad1[332];
/* The rest of these fields are identification area and describe
* the secondary block for uVAX VMB.
*/
uint8_t bb_magic1; /* magic number */
uint8_t bb_mbz1; /* must be zero */
uint8_t bb_pad1; /* any value */
uint8_t bb_sum1; /* ~(magic1 + mbz1 + pad1) */
uint8_t bb_mbz2; /* must be zero */
uint8_t bb_volinfo; /* volinfo */
uint8_t bb_pad2a; /* any value */
uint8_t bb_pad2b; /* any value */
uint32_t bb_size; /* size in blocks of bootstrap */
uint32_t bb_load; /* load offset to bootstrap */
uint32_t bb_entry; /* byte offset in bootstrap */
uint32_t bb_sum3; /* sum of previous 3 fields */
/* The rest is unused.
*/
uint8_t pad2[148];
} __attribute__((__packed__));
#define VAX_BOOT_MAGIC1 0x18 /* size of BB info? */
#define VAX_BOOT_VOLINFO_NONE 0x00 /* no special info */
#define VAX_BOOT_VOLINFO_SS 0x01 /* single sided */
#define VAX_BOOT_VOLINFO_DS 0x81 /* double sided */
#define VAX_BOOT_SIZE 15 /* 15 blocks */
#define VAX_BOOT_LOAD 0 /* no load offset */
#define VAX_BOOT_ENTRY 0x200 /* one block in */
#define VAX_BOOT_BLOCK_OFFSET 0
#define VAX_BOOT_BLOCK_BLOCKSIZE 512
/* ------------------------------------------
* x68k
*/
#define X68K_BOOT_BLOCK_OFFSET 0
#define X68K_BOOT_BLOCK_BLOCKSIZE 512
#define X68K_BOOT_BLOCK_MAX_SIZE (512 * 16)
/* Magic string -- 32 bytes long (including the NUL) */
#define X68K_BBINFO_MAGIC "NetBSD/x68k bootxx 20020601"
#endif /* !defined(__ASSEMBLER__) */ /* } */
#endif
#endif /* !_SYS_BOOTBLOCK_H */

View file

@ -0,0 +1,177 @@
/* $NetBSD: dinode.h,v 1.18 2003/08/07 16:34:42 agc Exp $ */
/*
* Copyright (c) 2002 Networks Associates Technology, Inc.
* All rights reserved.
*
* This software was developed for the FreeBSD Project by Marshall
* Kirk McKusick and Network Associates Laboratories, the Security
* Research Division of Network Associates, Inc. under DARPA/SPAWAR
* contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
* research program
*
* Copyright (c) 1982, 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)dinode.h 8.9 (Berkeley) 3/29/95
*/
#ifndef _UFS_UFS_DINODE_H_
#define _UFS_UFS_DINODE_H_
#include "type.h"
/*
* The root inode is the root of the file system. Inode 0 can't be used for
* normal purposes and historically bad blocks were linked to inode 1, thus
* the root inode is 2. (Inode 1 is no longer used for this purpose, however
* numerous dump tapes make this assumption, so we are stuck with it).
*/
#define ROOTINO ((ino_t)2)
/*
* The Whiteout inode# is a dummy non-zero inode number which will
* never be allocated to a real file. It is used as a place holder
* in the directory entry which has been tagged as a DT_W entry.
* See the comments about ROOTINO above.
*/
#define WINO ((ino_t)1)
/*
* A dinode contains all the meta-data associated with a UFS file.
* This structure defines the on-disk format of a dinode. Since
* this structure describes an on-disk structure, all its fields
* are defined by types with precise widths.
*/
#define NXADDR 2
#define NDADDR 12 /* Direct addresses in inode. */
#define NIADDR 3 /* Indirect addresses in inode. */
struct ufs1_dinode {
u_int16_t di_mode; /* 0: IFMT, permissions; see below. */
int16_t di_nlink; /* 2: File link count. */
union {
u_int16_t oldids[2]; /* 4: Ffs: old user and group ids. */
u_int32_t inumber; /* 4: Lfs: inode number. */
} di_u;
u_int64_t di_size; /* 8: File byte count. */
int32_t di_atime; /* 16: Last access time. */
int32_t di_atimensec; /* 20: Last access time. */
int32_t di_mtime; /* 24: Last modified time. */
int32_t di_mtimensec; /* 28: Last modified time. */
int32_t di_ctime; /* 32: Last inode change time. */
int32_t di_ctimensec; /* 36: Last inode change time. */
int32_t di_db[NDADDR]; /* 40: Direct disk blocks. */
int32_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */
u_int32_t di_flags; /* 100: Status flags (chflags). */
u_int32_t di_blocks; /* 104: Blocks actually held. */
int32_t di_gen; /* 108: Generation number. */
u_int32_t di_uid; /* 112: File owner. */
u_int32_t di_gid; /* 116: File group. */
int32_t di_spare[2]; /* 120: Reserved; currently unused */
};
struct ufs2_dinode {
u_int16_t di_mode; /* 0: IFMT, permissions; see below. */
int16_t di_nlink; /* 2: File link count. */
u_int32_t di_uid; /* 4: File owner. */
u_int32_t di_gid; /* 8: File group. */
u_int32_t di_blksize; /* 12: Inode blocksize. */
u_int64_t di_size; /* 16: File byte count. */
u_int64_t di_blocks; /* 24: Bytes actually held. */
int64_t di_atime; /* 32: Last access time. */
int64_t di_mtime; /* 40: Last modified time. */
int64_t di_ctime; /* 48: Last inode change time. */
int64_t di_birthtime; /* 56: Inode creation time. */
int32_t di_mtimensec; /* 64: Last modified time. */
int32_t di_atimensec; /* 68: Last access time. */
int32_t di_ctimensec; /* 72: Last inode change time. */
int32_t di_birthnsec; /* 76: Inode creation time. */
int32_t di_gen; /* 80: Generation number. */
u_int32_t di_kernflags; /* 84: Kernel flags. */
u_int32_t di_flags; /* 88: Status flags (chflags). */
int32_t di_extsize; /* 92: External attributes block. */
int64_t di_extb[NXADDR];/* 96: External attributes block. */
int64_t di_db[NDADDR]; /* 112: Direct disk blocks. */
int64_t di_ib[NIADDR]; /* 208: Indirect disk blocks. */
int64_t di_spare[3]; /* 232: Reserved; currently unused */
};
/*
* The di_db fields may be overlaid with other information for
* file types that do not have associated disk storage. Block
* and character devices overlay the first data block with their
* dev_t value. Short symbolic links place their path in the
* di_db area.
*/
#define di_inumber di_u.inumber
#define di_ogid di_u.oldids[1]
#define di_ouid di_u.oldids[0]
#define di_rdev di_db[0]
#define MAXSYMLINKLEN_UFS1 ((NDADDR + NIADDR) * sizeof(int32_t))
#define MAXSYMLINKLEN_UFS2 ((NDADDR + NIADDR) * sizeof(int64_t))
#define MAXSYMLINKLEN(ip) \
((ip)->i_ump->um_fstype == UFS1) ? \
MAXSYMLINKLEN_UFS1 : MAXSYMLINKLEN_UFS2
/* NeXT used to keep short symlinks in the inode even when using
* FS_42INODEFMT. In that case fs->fs_maxsymlinklen is probably -1,
* but short symlinks were stored in inodes shorter than this:
*/
#define APPLEUFS_MAXSYMLINKLEN 60
/* File permissions. */
#define IEXEC 0000100 /* Executable. */
#define IWRITE 0000200 /* Writable. */
#define IREAD 0000400 /* Readable. */
#define ISVTX 0001000 /* Sticky bit. */
#define ISGID 0002000 /* Set-gid. */
#define ISUID 0004000 /* Set-uid. */
/* File types. */
#define IFMT 0170000 /* Mask of file type. */
#define IFIFO 0010000 /* Named pipe (fifo). */
#define IFCHR 0020000 /* Character device. */
#define IFDIR 0040000 /* Directory file. */
#define IFBLK 0060000 /* Block device. */
#define IFREG 0100000 /* Regular file. */
#define IFLNK 0120000 /* Symbolic link. */
#define IFSOCK 0140000 /* UNIX domain socket. */
#define IFWHT 0160000 /* Whiteout. */
/* Size of the on-disk inode. */
#define DINODE1_SIZE (sizeof(struct ufs1_dinode)) /* 128 */
#define DINODE2_SIZE (sizeof(struct ufs2_dinode))
#endif /* !_UFS_UFS_DINODE_H_ */

View file

@ -0,0 +1,162 @@
/* $NetBSD: dir.h,v 1.17 2003/08/07 16:34:42 agc Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)dir.h 8.5 (Berkeley) 4/27/95
*/
#ifndef _UFS_UFS_DIR_H_
#define _UFS_UFS_DIR_H_
#include "type.h"
/*
* Theoretically, directories can be more than 2Gb in length, however, in
* practice this seems unlikely. So, we define the type doff_t as a 32-bit
* quantity to keep down the cost of doing lookup on a 32-bit machine.
*/
#define doff_t int32_t
#define MAXDIRSIZE (0x7fffffff)
/*
* A directory consists of some number of blocks of DIRBLKSIZ
* bytes, where DIRBLKSIZ is chosen such that it can be transferred
* to disk in a single atomic operation (e.g. 512 bytes on most machines).
*
* Each DIRBLKSIZ byte block contains some number of directory entry
* structures, which are of variable length. Each directory entry has
* a struct direct at the front of it, containing its inode number,
* the length of the entry, and the length of the name contained in
* the entry. These are followed by the name padded to a 4 byte boundary.
* All names are guaranteed null terminated.
* The maximum length of a name in a directory is MAXNAMLEN.
*
* The macro DIRSIZ(fmt, dp) gives the amount of space required to represent
* a directory entry. Free space in a directory is represented by
* entries which have dp->d_reclen > DIRSIZ(fmt, dp). All DIRBLKSIZ bytes
* in a directory block are claimed by the directory entries. This
* usually results in the last entry in a directory having a large
* dp->d_reclen. When entries are deleted from a directory, the
* space is returned to the previous entry in the same directory
* block by increasing its dp->d_reclen. If the first entry of
* a directory block is free, then its dp->d_ino is set to 0.
* Entries other than the first in a directory do not normally have
* dp->d_ino set to 0.
*/
#undef DIRBLKSIZ
#define DIRBLKSIZ DEV_BSIZE
#undef MAXNAMLEN
#define MAXNAMLEN 255
#define APPLEUFS_DIRBLKSIZ 1024
struct direct {
u_int32_t d_ino; /* inode number of entry */
u_int16_t d_reclen; /* length of this record */
u_int8_t d_type; /* file type, see below */
u_int8_t d_namlen; /* length of string in d_name */
char d_name[MAXNAMLEN + 1];/* name with length <= MAXNAMLEN */
};
/*
* File types
*/
#define DT_UNKNOWN 0
#define DT_FIFO 1
#define DT_CHR 2
#define DT_DIR 4
#define DT_BLK 6
#define DT_REG 8
#define DT_LNK 10
#define DT_SOCK 12
#define DT_WHT 14
/*
* Convert between stat structure types and directory types.
*/
#define IFTODT(mode) (((mode) & 0170000) >> 12)
#define DTTOIF(dirtype) ((dirtype) << 12)
/*
* The DIRSIZ macro gives the minimum record length which will hold
* the directory entry. This requires the amount of space in struct direct
* without the d_name field, plus enough space for the name with a terminating
* null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
*/
#define DIRECTSIZ(namlen) \
((sizeof(struct direct) - (MAXNAMLEN+1)) + (((namlen)+1 + 3) &~ 3))
#if (BYTE_ORDER == LITTLE_ENDIAN)
#define DIRSIZ(oldfmt, dp, needswap) \
(((oldfmt) && !(needswap)) ? \
DIRECTSIZ((dp)->d_type) : DIRECTSIZ((dp)->d_namlen))
#else
#define DIRSIZ(oldfmt, dp, needswap) \
(((oldfmt) && (needswap)) ? \
DIRECTSIZ((dp)->d_type) : DIRECTSIZ((dp)->d_namlen))
#endif
#define OLDDIRFMT 1
#define NEWDIRFMT 0
/*
* Template for manipulating directories. Should use struct direct's,
* but the name field is MAXNAMLEN - 1, and this just won't do.
*/
struct dirtemplate {
u_int32_t dot_ino;
int16_t dot_reclen;
u_int8_t dot_type;
u_int8_t dot_namlen;
char dot_name[4]; /* must be multiple of 4 */
u_int32_t dotdot_ino;
int16_t dotdot_reclen;
u_int8_t dotdot_type;
u_int8_t dotdot_namlen;
char dotdot_name[4]; /* ditto */
};
/*
* This is the old format of directories, sanz type element.
*/
struct odirtemplate {
u_int32_t dot_ino;
int16_t dot_reclen;
u_int16_t dot_namlen;
char dot_name[4]; /* must be multiple of 4 */
u_int32_t dotdot_ino;
int16_t dotdot_reclen;
u_int16_t dotdot_namlen;
char dotdot_name[4]; /* ditto */
};
#endif /* !_UFS_UFS_DIR_H_ */

View file

@ -0,0 +1,555 @@
/* $NetBSD: disklabel.h,v 1.88 2003/11/14 12:07:42 lukem Exp $ */
/*
* Copyright (c) 1987, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)disklabel.h 8.2 (Berkeley) 7/10/94
*/
#ifndef _SYS_DISKLABEL_H_
#define _SYS_DISKLABEL_H_
#include "type.h"
/*
* We need <machine/types.h> for __HAVE_OLD_DISKLABEL
*/
#if 0 /* XXX ffsdrv */
#ifndef _LOCORE
#include <sys/types.h>
#endif
#endif
/* sys/arch/i386/include/type.h XXX ffsdrv */
#define __HAVE_OLD_DISKLABEL
/*
* Each disk has a label which includes information about the hardware
* disk geometry, filesystem partitions, and drive specific information.
* The location of the label, as well as the number of partitions the
* label can describe and the number of the "whole disk" (raw)
* paritition are machine dependent.
*/
#if 0 /* XXX ffsdrv */
#include <machine/disklabel.h>
#endif
/* arch/i386/include/disklabel.h */
#define LABELSECTOR 1 /* sector containing label */
#define LABELOFFSET 0 /* offset of label in sector */
#define MAXPARTITIONS 16 /* number of partitions */
#define OLDMAXPARTITIONS 8 /* number of partitions before 1.6 */
#define RAW_PART 3 /* raw partition: XX?d (XXX) */
/*
* We use the highest bit of the minor number for the partition number.
* This maintains backward compatibility with device nodes created before
* MAXPARTITIONS was increased.
*/
#define __I386_MAXDISKS ((1 << 20) / MAXPARTITIONS)
#define DISKUNIT(dev) ((minor(dev) / OLDMAXPARTITIONS) % __I386_MAXDISKS)
#define DISKPART(dev) ((minor(dev) % OLDMAXPARTITIONS) + \
((minor(dev) / (__I386_MAXDISKS * OLDMAXPARTITIONS)) * OLDMAXPARTITIONS))
#define DISKMINOR(unit, part) \
(((unit) * OLDMAXPARTITIONS) + ((part) % OLDMAXPARTITIONS) + \
((part) / OLDMAXPARTITIONS) * (__I386_MAXDISKS * OLDMAXPARTITIONS))
/* Pull in MBR partition definitions. */
#include "bootblock.h"
/* end of arch/i386/include/disklabel.h */
/*
* The absolute maximum number of disk partitions allowed.
* This is the maximum value of MAXPARTITIONS for which 'struct disklabel'
* is <= DEV_BSIZE bytes long. If MAXPARTITIONS is greater than this, beware.
*/
#define MAXMAXPARTITIONS 22
#if MAXPARTITIONS > MAXMAXPARTITIONS
#warning beware: MAXPARTITIONS bigger than MAXMAXPARTITIONS
#endif
/*
* Ports can switch their MAXPARTITIONS once, as follows:
*
* - define OLDMAXPARTITIONS in <machine/disklabel.h> as the old number
* - define MAXPARTITIONS as the new number
* - define DISKUNIT, DISKPART and DISKMINOR macros in <machine/disklabel.h>
* as appropriate for the port (see the i386 one for an example).
* - define __HAVE_OLD_DISKLABEL in <machine/types.h>
*/
#if defined(_KERNEL) && defined(__HAVE_OLD_DISKLABEL) && \
(MAXPARTITIONS < OLDMAXPARTITIONS)
#error "can only grow disklabel size"
#endif
/*
* Translate between device numbers and major/disk unit/disk partition.
*/
#ifndef __HAVE_OLD_DISKLABEL
#define DISKUNIT(dev) (minor(dev) / MAXPARTITIONS)
#define DISKPART(dev) (minor(dev) % MAXPARTITIONS)
#define DISKMINOR(unit, part) \
(((unit) * MAXPARTITIONS) + (part))
#endif
#define MAKEDISKDEV(maj, unit, part) \
(makedev((maj), DISKMINOR((unit), (part))))
#define DISKMAGIC ((u_int32_t)0x82564557) /* The disk magic number */
#ifndef _LOCORE
struct disklabel {
u_int32_t d_magic; /* the magic number */
u_int16_t d_type; /* drive type */
u_int16_t d_subtype; /* controller/d_type specific */
char d_typename[16]; /* type name, e.g. "eagle" */
/*
* d_packname contains the pack identifier and is returned when
* the disklabel is read off the disk or in-core copy.
* d_boot0 and d_boot1 are the (optional) names of the
* primary (block 0) and secondary (block 1-15) bootstraps
* as found in /usr/mdec. These are returned when using
* getdiskbyname(3) to retrieve the values from /etc/disktab.
*/
union {
char un_d_packname[16]; /* pack identifier */
struct {
char *un_d_boot0; /* primary bootstrap name */
char *un_d_boot1; /* secondary bootstrap name */
} un_b;
} d_un;
#define d_packname d_un.un_d_packname
#define d_boot0 d_un.un_b.un_d_boot0
#define d_boot1 d_un.un_b.un_d_boot1
/* disk geometry: */
u_int32_t d_secsize; /* # of bytes per sector */
u_int32_t d_nsectors; /* # of data sectors per track */
u_int32_t d_ntracks; /* # of tracks per cylinder */
u_int32_t d_ncylinders; /* # of data cylinders per unit */
u_int32_t d_secpercyl; /* # of data sectors per cylinder */
u_int32_t d_secperunit; /* # of data sectors per unit */
/*
* Spares (bad sector replacements) below are not counted in
* d_nsectors or d_secpercyl. Spare sectors are assumed to
* be physical sectors which occupy space at the end of each
* track and/or cylinder.
*/
u_int16_t d_sparespertrack; /* # of spare sectors per track */
u_int16_t d_sparespercyl; /* # of spare sectors per cylinder */
/*
* Alternative cylinders include maintenance, replacement,
* configuration description areas, etc.
*/
u_int32_t d_acylinders; /* # of alt. cylinders per unit */
/* hardware characteristics: */
/*
* d_interleave, d_trackskew and d_cylskew describe perturbations
* in the media format used to compensate for a slow controller.
* Interleave is physical sector interleave, set up by the
* formatter or controller when formatting. When interleaving is
* in use, logically adjacent sectors are not physically
* contiguous, but instead are separated by some number of
* sectors. It is specified as the ratio of physical sectors
* traversed per logical sector. Thus an interleave of 1:1
* implies contiguous layout, while 2:1 implies that logical
* sector 0 is separated by one sector from logical sector 1.
* d_trackskew is the offset of sector 0 on track N relative to
* sector 0 on track N-1 on the same cylinder. Finally, d_cylskew
* is the offset of sector 0 on cylinder N relative to sector 0
* on cylinder N-1.
*/
u_int16_t d_rpm; /* rotational speed */
u_int16_t d_interleave; /* hardware sector interleave */
u_int16_t d_trackskew; /* sector 0 skew, per track */
u_int16_t d_cylskew; /* sector 0 skew, per cylinder */
u_int32_t d_headswitch; /* head switch time, usec */
u_int32_t d_trkseek; /* track-to-track seek, usec */
u_int32_t d_flags; /* generic flags */
#define NDDATA 5
u_int32_t d_drivedata[NDDATA]; /* drive-type specific information */
#define NSPARE 5
u_int32_t d_spare[NSPARE]; /* reserved for future use */
u_int32_t d_magic2; /* the magic number (again) */
u_int16_t d_checksum; /* xor of data incl. partitions */
/* filesystem and partition information: */
u_int16_t d_npartitions; /* number of partitions in following */
u_int32_t d_bbsize; /* size of boot area at sn0, bytes */
u_int32_t d_sbsize; /* max size of fs superblock, bytes */
struct partition { /* the partition table */
u_int32_t p_size; /* number of sectors in partition */
u_int32_t p_offset; /* starting sector */
union {
u_int32_t fsize; /* FFS, ADOS:
filesystem basic fragment size */
u_int32_t cdsession; /* ISO9660: session offset */
} __partition_u2;
#define p_fsize __partition_u2.fsize
#define p_cdsession __partition_u2.cdsession
u_int8_t p_fstype; /* filesystem type, see below */
u_int8_t p_frag; /* filesystem fragments per block */
union {
u_int16_t cpg; /* UFS: FS cylinders per group */
u_int16_t sgs; /* LFS: FS segment shift */
} __partition_u1;
#define p_cpg __partition_u1.cpg
#define p_sgs __partition_u1.sgs
} d_partitions[MAXPARTITIONS]; /* actually may be more */
};
#ifdef __HAVE_OLD_DISKLABEL
/*
* Same as above, but with OLDMAXPARTITIONS partitions. For use in
* the old DIOC* ioctl calls.
*/
struct olddisklabel {
u_int32_t d_magic;
u_int16_t d_type;
u_int16_t d_subtype;
char d_typename[16];
union {
char un_d_packname[16];
struct {
char *un_d_boot0;
char *un_d_boot1;
} un_b;
} d_un;
u_int32_t d_secsize;
u_int32_t d_nsectors;
u_int32_t d_ntracks;
u_int32_t d_ncylinders;
u_int32_t d_secpercyl;
u_int32_t d_secperunit;
u_int16_t d_sparespertrack;
u_int16_t d_sparespercyl;
u_int32_t d_acylinders;
u_int16_t d_rpm;
u_int16_t d_interleave;
u_int16_t d_trackskew;
u_int16_t d_cylskew;
u_int32_t d_headswitch;
u_int32_t d_trkseek;
u_int32_t d_flags;
u_int32_t d_drivedata[NDDATA];
u_int32_t d_spare[NSPARE];
u_int32_t d_magic2;
u_int16_t d_checksum;
u_int16_t d_npartitions;
u_int32_t d_bbsize;
u_int32_t d_sbsize;
struct opartition {
u_int32_t p_size;
u_int32_t p_offset;
union {
u_int32_t fsize;
u_int32_t cdsession;
} __partition_u2;
u_int8_t p_fstype;
u_int8_t p_frag;
union {
u_int16_t cpg;
u_int16_t sgs;
} __partition_u1;
} d_partitions[OLDMAXPARTITIONS];
};
#endif /* __HAVE_OLD_DISKLABEL */
#else /* _LOCORE */
/*
* offsets for asm boot files.
*/
.set d_secsize,40
.set d_nsectors,44
.set d_ntracks,48
.set d_ncylinders,52
.set d_secpercyl,56
.set d_secperunit,60
.set d_end_,276 /* size of disk label */
#endif /* _LOCORE */
/* d_type values: */
#define DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
#define DTYPE_MSCP 2 /* MSCP */
#define DTYPE_DEC 3 /* other DEC (rk, rl) */
#define DTYPE_SCSI 4 /* SCSI */
#define DTYPE_ESDI 5 /* ESDI interface */
#define DTYPE_ST506 6 /* ST506 etc. */
#define DTYPE_HPIB 7 /* CS/80 on HP-IB */
#define DTYPE_HPFL 8 /* HP Fiber-link */
#define DTYPE_FLOPPY 10 /* floppy */
#define DTYPE_CCD 11 /* concatenated disk device */
#define DTYPE_VND 12 /* vnode pseudo-disk */
#define DTYPE_ATAPI 13 /* ATAPI */
#define DTYPE_RAID 14 /* RAIDframe */
#define DTYPE_LD 15 /* logical disk */
#define DTYPE_JFS2 16 /* IBM JFS2 */
#define DTYPE_CGD 17 /* cryptographic pseudo-disk */
#define DTYPE_VINUM 18 /* vinum volume */
#ifdef DKTYPENAMES
static const char *const dktypenames[] = {
"unknown",
"SMD",
"MSCP",
"old DEC",
"SCSI",
"ESDI",
"ST506",
"HP-IB",
"HP-FL",
"type 9",
"floppy",
"ccd",
"vnd",
"ATAPI",
"RAID",
"ld",
"jfs",
"cgd",
"vinum",
NULL
};
#define DKMAXTYPES (sizeof(dktypenames) / sizeof(dktypenames[0]) - 1)
#endif
/*
* Filesystem type and version.
* Used to interpret other filesystem-specific
* per-partition information.
*
* These are used only for COMPAT_09 support.
*/
#define FS_UNUSED 0 /* unused */
#define FS_SWAP 1 /* swap */
#define FS_V6 2 /* Sixth Edition */
#define FS_V7 3 /* Seventh Edition */
#define FS_SYSV 4 /* System V */
#define FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
#define FS_V8 6 /* Eighth Edition, 4K blocks */
#define FS_BSDFFS 7 /* 4.2BSD fast file system */
#define FS_MSDOS 8 /* MSDOS file system */
#define FS_BSDLFS 9 /* 4.4BSD log-structured file system */
#define FS_OTHER 10 /* in use, but unknown/unsupported */
#define FS_HPFS 11 /* OS/2 high-performance file system */
#define FS_ISO9660 12 /* ISO 9660, normally CD-ROM */
#define FS_BOOT 13 /* partition contains bootstrap */
#define FS_ADOS 14 /* AmigaDOS fast file system */
#define FS_HFS 15 /* Macintosh HFS */
#define FS_FILECORE 16 /* Acorn Filecore Filing System */
#define FS_EX2FS 17 /* Linux Extended 2 file system */
#define FS_NTFS 18 /* Windows/NT file system */
#define FS_RAID 19 /* RAIDframe component */
#define FS_CCD 20 /* concatenated disk component */
#define FS_JFS2 21 /* IBM JFS2 */
#define FS_APPLEUFS 22 /* Apple UFS */
/* XXX this is not the same as FreeBSD. How to solve? */
#define FS_VINUM 23 /* Vinum */
/* Adjust the FSMAXTYPES def below if you add something after APPLEUFS */
#ifdef FSTYPENAMES
static const char *const fstypenames[] = {
"unused",
"swap",
"Version 6",
"Version 7",
"System V",
"4.1BSD",
"Eighth Edition",
"4.2BSD",
"MSDOS",
"4.4LFS",
"unknown",
"HPFS",
"ISO9660",
"boot",
"ADOS",
"HFS",
"FILECORE",
"Linux Ext2",
"NTFS",
"RAID",
"ccd",
"jfs",
"Apple UFS",
"vinum",
NULL
};
#define FSMAXTYPES (sizeof(fstypenames) / sizeof(fstypenames[0]) - 1)
#else
#define FSMAXTYPES (FS_VINUM + 1)
#endif
#ifdef FSCKNAMES
/* These are the names MOUNT_XXX from <sys/mount.h> */
static const char *const fscknames[] = {
NULL, /* unused */
NULL, /* swap */
NULL, /* Version 6 */
NULL, /* Version 7 */
NULL, /* System V */
NULL, /* 4.1BSD */
NULL, /* Eighth edition */
"ffs", /* 4.2BSD */
"msdos", /* MSDOS */
"lfs", /* 4.4LFS */
NULL, /* unknown */
NULL, /* HPFS */
NULL, /* ISO9660 */
NULL, /* boot */
NULL, /* ADOS */
NULL, /* HFS */
NULL, /* FILECORE */
"ext2fs", /* Linux Ext2 */
NULL, /* Windows/NT */
NULL, /* RAID Component */
NULL, /* concatenated disk component */
NULL, /* IBM JFS2 */
"ffs", /* Apple UFS */
NULL /* NULL */
};
#define FSMAXNAMES (sizeof(fscknames) / sizeof(fscknames[0]) - 1)
#endif
#ifdef MOUNTNAMES
/* These are the names MOUNT_XXX from <sys/mount.h> */
static const char *const mountnames[] = {
NULL, /* unused */
NULL, /* swap */
NULL, /* Version 6 */
NULL, /* Version 7 */
NULL, /* System V */
NULL, /* 4.1BSD */
NULL, /* Eighth edition */
"ffs", /* 4.2BSD */
"msdos", /* MSDOS */
"lfs", /* 4.4LFS */
NULL, /* unknown */
NULL, /* HPFS */
"cd9660", /* ISO9660 */
NULL, /* boot */
"ados", /* ADOS */
NULL, /* HFS */
"filecore", /* FILECORE */
"ext2fs", /* Linux Ext2 */
"ntfs", /* Windows/NT */
NULL, /* RAID Component */
NULL, /* concatenated disk component */
NULL, /* IBM JFS2 */
"ffs", /* Apple UFS */
NULL /* NULL */
};
#define FSMAXMOUNTNAMES (sizeof(mountnames) / sizeof(mountnames[0]) - 1)
#endif
/*
* flags shared by various drives:
*/
#define D_REMOVABLE 0x01 /* removable media */
#define D_ECC 0x02 /* supports ECC */
#define D_BADSECT 0x04 /* supports bad sector forw. */
#define D_RAMDISK 0x08 /* disk emulator */
#define D_CHAIN 0x10 /* can do back-back transfers */
/*
* Drive data for SMD.
*/
#define d_smdflags d_drivedata[0]
#define D_SSE 0x1 /* supports skip sectoring */
#define d_mindist d_drivedata[1]
#define d_maxdist d_drivedata[2]
#define d_sdist d_drivedata[3]
/*
* Drive data for ST506.
*/
#define d_precompcyl d_drivedata[0]
#define d_gap3 d_drivedata[1] /* used only when formatting */
/*
* Drive data for SCSI.
*/
#define d_blind d_drivedata[0]
#ifndef _LOCORE
/*
* Structure used to perform a format or other raw operation,
* returning data and/or register values. Register identification
* and format are device- and driver-dependent. Currently unused.
*/
struct format_op {
char *df_buf;
int df_count; /* value-result */
daddr_t df_startblk;
int df_reg[8]; /* result */
};
/*
* Structure used internally to retrieve information about a partition
* on a disk.
*/
struct partinfo {
struct disklabel *disklab;
struct partition *part;
};
#ifdef _KERNEL
struct disk;
void diskerr __P((const struct buf *, const char *, const char *, int,
int, const struct disklabel *));
u_int dkcksum __P((struct disklabel *));
int setdisklabel __P((struct disklabel *, struct disklabel *, u_long,
struct cpu_disklabel *));
const char *readdisklabel __P((dev_t, void (*)(struct buf *),
struct disklabel *, struct cpu_disklabel *));
int writedisklabel __P((dev_t, void (*)(struct buf *), struct disklabel *,
struct cpu_disklabel *));
int bounds_check_with_label __P((struct disk *, struct buf *, int));
int bounds_check_with_mediasize __P((struct buf *, int, u_int64_t));
#endif
#endif /* _LOCORE */
#if !defined(_KERNEL) && !defined(_LOCORE)
#if 0 /* XXX ffsdrv */
#include <sys/cdefs.h>
#endif
#endif
#endif /* !_SYS_DISKLABEL_H_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,697 @@
/* $NetBSD: fs.h,v 1.43 2004/03/21 18:48:24 dsl Exp $ */
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)fs.h 8.13 (Berkeley) 3/21/95
*/
#ifndef _UFS_FFS_FS_H_
#define _UFS_FFS_FS_H_
#include "type.h"
/*
* Each disk drive contains some number of file systems.
* A file system consists of a number of cylinder groups.
* Each cylinder group has inodes and data.
*
* A file system is described by its super-block, which in turn
* describes the cylinder groups. The super-block is critical
* data and is replicated in each cylinder group to protect against
* catastrophic loss. This is done at `newfs' time and the critical
* super-block data does not change, so the copies need not be
* referenced further unless disaster strikes.
*
* For file system fs, the offsets of the various blocks of interest
* are given in the super block as:
* [fs->fs_sblkno] Super-block
* [fs->fs_cblkno] Cylinder group block
* [fs->fs_iblkno] Inode blocks
* [fs->fs_dblkno] Data blocks
* The beginning of cylinder group cg in fs, is given by
* the ``cgbase(fs, cg)'' macro.
*
* Depending on the architecture and the media, the superblock may
* reside in any one of four places. For tiny media where every block
* counts, it is placed at the very front of the partition. Historically,
* UFS1 placed it 8K from the front to leave room for the disk label and
* a small bootstrap. For UFS2 it got moved to 64K from the front to leave
* room for the disk label and a bigger bootstrap, and for really piggy
* systems we check at 256K from the front if the first three fail. In
* all cases the size of the superblock will be SBLOCKSIZE. All values are
* given in byte-offset form, so they do not imply a sector size. The
* SBLOCKSEARCH specifies the order in which the locations should be searched.
*
* Unfortunately the UFS2/FFSv2 change was done without adequate consideration
* of backward compatibility. In particular 'newfs' for a FFSv2 partition
* must overwrite any old FFSv1 superblock at 8k, and preferrably as many
* of the alternates as it can find - otherwise attempting to mount on a
* system that only supports FFSv1 is likely to succeed!.
* For a small FFSv1 filesystem, an old FFSv2 superblock can be left on
* the disk, and a system that tries to find an FFSv2 filesystem in preference
* to and FFSv1 one (as NetBSD does) can mount the old FFSv2 filesystem.
* As a added bonus, the 'first alternate' superblock of a FFSv1 filesystem
* with 64k blocks is at 64k - just where the code looks first when playing
* 'hunt the superblock'.
*
* The ffsv2 superblock layout (which might contain an ffsv1 filesystem)
* can be detected by checking for sb->fs_old_flags & FS_FLAGS_UPDATED.
* This is the default suberblock type for NetBSD since ffsv2 support was added.
*/
#define BBSIZE 8192
#define BBOFF ((off_t)(0))
#define BBLOCK ((daddr_t)(0))
#define SBLOCK_FLOPPY 0
#define SBLOCK_UFS1 8192
#define SBLOCK_UFS2 65536
#define SBLOCK_PIGGY 262144
#define SBLOCKSIZE 8192
/*
* NB: Do not, under any circumstances, look for an ffsv1 filesystem at
* SBLOCK_UFS2. Doing so will find the wrong superblock for filesystems
* with a 64k block size.
*/
#define SBLOCKSEARCH \
{ SBLOCK_UFS2, SBLOCK_UFS1, SBLOCK_FLOPPY, SBLOCK_PIGGY, -1 }
/*
* Max number of fragments per block. This value is NOT tweakable.
*/
#define MAXFRAG 8
/*
* Addresses stored in inodes are capable of addressing fragments
* of `blocks'. File system blocks of at most size MAXBSIZE can
* be optionally broken into 2, 4, or 8 pieces, each of which is
* addressable; these pieces may be DEV_BSIZE, or some multiple of
* a DEV_BSIZE unit.
*
* Large files consist of exclusively large data blocks. To avoid
* undue wasted disk space, the last data block of a small file may be
* allocated as only as many fragments of a large block as are
* necessary. The file system format retains only a single pointer
* to such a fragment, which is a piece of a single large block that
* has been divided. The size of such a fragment is determinable from
* information in the inode, using the ``blksize(fs, ip, lbn)'' macro.
*
* The file system records space availability at the fragment level;
* to determine block availability, aligned fragments are examined.
*/
/*
* MINBSIZE is the smallest allowable block size.
* In order to insure that it is possible to create files of size
* 2^32 with only two levels of indirection, MINBSIZE is set to 4096.
* MINBSIZE must be big enough to hold a cylinder group block,
* thus changes to (struct cg) must keep its size within MINBSIZE.
* Note that super blocks are always of size SBSIZE,
* and that both SBSIZE and MAXBSIZE must be >= MINBSIZE.
*/
#define MINBSIZE 4096
/*
* The path name on which the file system is mounted is maintained
* in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in
* the super block for this name.
*/
#define MAXMNTLEN 468
/*
* The volume name for this filesystem is maintained in fs_volname.
* MAXVOLLEN defines the length of the buffer allocated.
* This space used to be part of of fs_fsmnt.
*/
#define MAXVOLLEN 32
/*
* There is a 128-byte region in the superblock reserved for in-core
* pointers to summary information. Originally this included an array
* of pointers to blocks of struct csum; now there are just four
* pointers and the remaining space is padded with fs_ocsp[].
* NOCSPTRS determines the size of this padding. One pointer (fs_csp)
* is taken away to point to a contiguous array of struct csum for
* all cylinder groups; a second (fs_maxcluster) points to an array
* of cluster sizes that is computed as cylinder groups are inspected;
* the third (fs_contigdirs) points to an array that tracks the
* creation of new directories; and the fourth (fs_active) is used
* by snapshots.
*/
#define NOCSPTRS ((128 / sizeof(void *)) - 4)
/*
* A summary of contiguous blocks of various sizes is maintained
* in each cylinder group. Normally this is set by the initial
* value of fs_maxcontig. To conserve space, a maximum summary size
* is set by FS_MAXCONTIG.
*/
#define FS_MAXCONTIG 16
/*
* Unused value currently, FreeBSD compat.
*/
#define FSMAXSNAP 20
/*
* MINFREE gives the minimum acceptable percentage of file system
* blocks which may be free. If the freelist drops below this level
* only the superuser may continue to allocate blocks. This may
* be set to 0 if no reserve of free blocks is deemed necessary,
* however throughput drops by fifty percent if the file system
* is run at between 95% and 100% full; thus the minimum default
* value of fs_minfree is 5%. However, to get good clustering
* performance, 10% is a better choice. hence we use 10% as our
* default value. With 10% free space, fragmentation is not a
* problem, so we choose to optimize for time.
*/
#define MINFREE 5
#define DEFAULTOPT FS_OPTTIME
/*
* Grigoriy Orlov <gluk@ptci.ru> has done some extensive work to fine
* tune the layout preferences for directories within a filesystem.
* His algorithm can be tuned by adjusting the following parameters
* which tell the system the average file size and the average number
* of files per directory. These defaults are well selected for typical
* filesystems, but may need to be tuned for odd cases like filesystems
* being used for squid caches or news spools.
*/
#define AVFILESIZ 16384 /* expected average file size */
#define AFPDIR 64 /* expected number of files per directory */
/*
* Per cylinder group information; summarized in blocks allocated
* from first cylinder group data blocks. These blocks have to be
* read in from fs_csaddr (size fs_cssize) in addition to the
* super block.
*/
struct csum {
int32_t cs_ndir; /* number of directories */
int32_t cs_nbfree; /* number of free blocks */
int32_t cs_nifree; /* number of free inodes */
int32_t cs_nffree; /* number of free frags */
};
struct csum_total {
int64_t cs_ndir; /* number of directories */
int64_t cs_nbfree; /* number of free blocks */
int64_t cs_nifree; /* number of free inodes */
int64_t cs_nffree; /* number of free frags */
int64_t cs_spare[4]; /* future expansion */
};
/*
* Super block for an FFS file system in memory.
*/
struct fs {
int32_t fs_firstfield; /* historic file system linked list, */
int32_t fs_unused_1; /* used for incore super blocks */
int32_t fs_sblkno; /* addr of super-block in filesys */
int32_t fs_cblkno; /* offset of cyl-block in filesys */
int32_t fs_iblkno; /* offset of inode-blocks in filesys */
int32_t fs_dblkno; /* offset of first data after cg */
int32_t fs_old_cgoffset; /* cylinder group offset in cylinder */
int32_t fs_old_cgmask; /* used to calc mod fs_ntrak */
int32_t fs_old_time; /* last time written */
int32_t fs_old_size; /* number of blocks in fs */
int32_t fs_old_dsize; /* number of data blocks in fs */
int32_t fs_ncg; /* number of cylinder groups */
int32_t fs_bsize; /* size of basic blocks in fs */
int32_t fs_fsize; /* size of frag blocks in fs */
int32_t fs_frag; /* number of frags in a block in fs */
/* these are configuration parameters */
int32_t fs_minfree; /* minimum percentage of free blocks */
int32_t fs_old_rotdelay; /* num of ms for optimal next block */
int32_t fs_old_rps; /* disk revolutions per second */
/* these fields can be computed from the others */
int32_t fs_bmask; /* ``blkoff'' calc of blk offsets */
int32_t fs_fmask; /* ``fragoff'' calc of frag offsets */
int32_t fs_bshift; /* ``lblkno'' calc of logical blkno */
int32_t fs_fshift; /* ``numfrags'' calc number of frags */
/* these are configuration parameters */
int32_t fs_maxcontig; /* max number of contiguous blks */
int32_t fs_maxbpg; /* max number of blks per cyl group */
/* these fields can be computed from the others */
int32_t fs_fragshift; /* block to frag shift */
int32_t fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */
int32_t fs_sbsize; /* actual size of super block */
int32_t fs_spare1[2]; /* old fs_csmask */
/* old fs_csshift */
int32_t fs_nindir; /* value of NINDIR */
int32_t fs_inopb; /* value of INOPB */
int32_t fs_old_nspf; /* value of NSPF */
/* yet another configuration parameter */
int32_t fs_optim; /* optimization preference, see below */
/* these fields are derived from the hardware */
int32_t fs_old_npsect; /* # sectors/track including spares */
int32_t fs_old_interleave; /* hardware sector interleave */
int32_t fs_old_trackskew; /* sector 0 skew, per track */
/* fs_id takes the space of the unused fs_headswitch and fs_trkseek fields */
int32_t fs_id[2]; /* unique file system id */
/* sizes determined by number of cylinder groups and their sizes */
int32_t fs_old_csaddr; /* blk addr of cyl grp summary area */
int32_t fs_cssize; /* size of cyl grp summary area */
int32_t fs_cgsize; /* cylinder group size */
/* these fields are derived from the hardware */
int32_t fs_spare2; /* old fs_ntrak */
int32_t fs_old_nsect; /* sectors per track */
int32_t fs_old_spc; /* sectors per cylinder */
int32_t fs_old_ncyl; /* cylinders in file system */
int32_t fs_old_cpg; /* cylinders per group */
int32_t fs_ipg; /* inodes per group */
int32_t fs_fpg; /* blocks per group * fs_frag */
/* this data must be re-computed after crashes */
struct csum fs_old_cstotal; /* cylinder summary information */
/* these fields are cleared at mount time */
int8_t fs_fmod; /* super block modified flag */
int8_t fs_clean; /* file system is clean flag */
int8_t fs_ronly; /* mounted read-only flag */
uint8_t fs_old_flags; /* see FS_ flags below */
u_char fs_fsmnt[MAXMNTLEN]; /* name mounted on */
u_char fs_volname[MAXVOLLEN]; /* volume name */
uint64_t fs_swuid; /* system-wide uid */
int32_t fs_pad;
/* these fields retain the current block allocation info */
int32_t fs_cgrotor; /* last cg searched (UNUSED) */
void *fs_ocsp[NOCSPTRS]; /* padding; was list of fs_cs buffers */
u_int8_t *fs_contigdirs; /* # of contiguously allocated dirs */
struct csum *fs_csp; /* cg summary info buffer for fs_cs */
int32_t *fs_maxcluster; /* max cluster in each cyl group */
u_int *fs_active; /* used by snapshots to track fs */
int32_t fs_old_cpc; /* cyl per cycle in postbl */
/* this area is otherwise allocated unless fs_old_flags & FS_FLAGS_UPDATED */
int32_t fs_maxbsize; /* maximum blocking factor permitted */
int64_t fs_sparecon64[17]; /* old rotation block list head */
int64_t fs_sblockloc; /* byte offset of standard superblock */
struct csum_total fs_cstotal; /* cylinder summary information */
int64_t fs_time; /* last time written */
int64_t fs_size; /* number of blocks in fs */
int64_t fs_dsize; /* number of data blocks in fs */
int64_t fs_csaddr; /* blk addr of cyl grp summary area */
int64_t fs_pendingblocks; /* blocks in process of being freed */
int32_t fs_pendinginodes; /* inodes in process of being freed */
int32_t fs_snapinum[FSMAXSNAP];/* list of snapshot inode numbers */
/* back to stuff that has been around a while */
int32_t fs_avgfilesize; /* expected average file size */
int32_t fs_avgfpdir; /* expected # of files per directory */
int32_t fs_save_cgsize; /* save real cg size to use fs_bsize */
int32_t fs_sparecon32[26]; /* reserved for future constants */
uint32_t fs_flags; /* see FS_ flags below */
/* back to stuff that has been around a while (again) */
int32_t fs_contigsumsize; /* size of cluster summary array */
int32_t fs_maxsymlinklen; /* max length of an internal symlink */
int32_t fs_old_inodefmt; /* format of on-disk inodes */
u_int64_t fs_maxfilesize; /* maximum representable file size */
int64_t fs_qbmask; /* ~fs_bmask for use with 64-bit size */
int64_t fs_qfmask; /* ~fs_fmask for use with 64-bit size */
int32_t fs_state; /* validate fs_clean field (UNUSED) */
int32_t fs_old_postblformat; /* format of positional layout tables */
int32_t fs_old_nrpos; /* number of rotational positions */
int32_t fs_spare5[2]; /* old fs_postbloff */
/* old fs_rotbloff */
int32_t fs_magic; /* magic number */
};
#define fs_old_postbloff fs_spare5[0]
#define fs_old_rotbloff fs_spare5[1]
#define fs_old_postbl_start fs_maxbsize
#define fs_old_headswitch fs_id[0]
#define fs_old_trkseek fs_id[1]
#define fs_old_csmask fs_spare1[0]
#define fs_old_csshift fs_spare1[1]
#define FS_42POSTBLFMT -1 /* 4.2BSD rotational table format */
#define FS_DYNAMICPOSTBLFMT 1 /* dynamic rotational table format */
#define old_fs_postbl(fs_, cylno, opostblsave) \
((((fs_)->fs_old_postblformat == FS_42POSTBLFMT) || \
((fs_)->fs_old_postbloff == offsetof(struct fs, fs_old_postbl_start))) \
? ((int16_t *)(opostblsave) + (cylno) * (fs_)->fs_old_nrpos) \
: ((int16_t *)((uint8_t *)(fs_) + \
(fs_)->fs_old_postbloff) + (cylno) * (fs_)->fs_old_nrpos))
#define old_fs_rotbl(fs) \
(((fs)->fs_old_postblformat == FS_42POSTBLFMT) \
? ((uint8_t *)(&(fs)->fs_magic+1)) \
: ((uint8_t *)((uint8_t *)(fs) + (fs)->fs_old_rotbloff)))
/*
* File system identification
*/
#define FS_UFS1_MAGIC 0x011954 /* UFS1 fast file system magic number */
#define FS_UFS2_MAGIC 0x19540119 /* UFS2 fast file system magic number */
#define FS_UFS1_MAGIC_SWAPPED 0x54190100
#define FS_UFS2_MAGIC_SWAPPED 0x19015419
#define FS_OKAY 0x7c269d38 /* superblock checksum */
#define FS_42INODEFMT -1 /* 4.2BSD inode format */
#define FS_44INODEFMT 2 /* 4.4BSD inode format */
/*
* File system clean flags
*/
#define FS_ISCLEAN 0x01
#define FS_WASCLEAN 0x02
/*
* Preference for optimization.
*/
#define FS_OPTTIME 0 /* minimize allocation time */
#define FS_OPTSPACE 1 /* minimize disk fragmentation */
/*
* File system flags
*/
#define FS_UNCLEAN 0x01 /* file system not clean at mount (unused) */
#define FS_DOSOFTDEP 0x02 /* file system using soft dependencies */
#define FS_NEEDSFSCK 0x04 /* needs sync fsck (FreeBSD compat, unused) */
#define FS_INDEXDIRS 0x08 /* kernel supports indexed directories */
#define FS_ACLS 0x10 /* file system has ACLs enabled */
#define FS_MULTILABEL 0x20 /* file system is MAC multi-label */
#define FS_FLAGS_UPDATED 0x80 /* flags have been moved to new location */
/*
* File system internal flags, also in fs_flags.
* (Pick highest number to avoid conflicts with others)
*/
#define FS_SWAPPED 0x80000000 /* file system is endian swapped */
#define FS_INTERNAL 0x80000000 /* mask for internal flags */
/*
* The size of a cylinder group is calculated by CGSIZE. The maximum size
* is limited by the fact that cylinder groups are at most one block.
* Its size is derived from the size of the maps maintained in the
* cylinder group and the (struct cg) size.
*/
#define CGSIZE_IF(fs, ipg, fpg) \
/* base cg */ (sizeof(struct cg) + sizeof(int32_t) + \
/* old btotoff */ (fs)->fs_old_cpg * sizeof(int32_t) + \
/* old boff */ (fs)->fs_old_cpg * sizeof(u_int16_t) + \
/* inode map */ howmany((ipg), NBBY) + \
/* block map */ howmany((fpg), NBBY) +\
/* if present */ ((fs)->fs_contigsumsize <= 0 ? 0 : \
/* cluster sum */ (fs)->fs_contigsumsize * sizeof(int32_t) + \
/* cluster map */ howmany(fragstoblks(fs, (fpg)), NBBY)))
#define CGSIZE(fs) CGSIZE_IF((fs), (fs)->fs_ipg, (fs)->fs_fpg)
/*
* The minimal number of cylinder groups that should be created.
*/
#define MINCYLGRPS 4
/*
* Convert cylinder group to base address of its global summary info.
*/
#define fs_cs(fs, indx) fs_csp[indx]
/*
* Cylinder group block for a file system.
*/
#define CG_MAGIC 0x090255
struct cg {
int32_t cg_firstfield; /* historic cyl groups linked list */
int32_t cg_magic; /* magic number */
int32_t cg_old_time; /* time last written */
int32_t cg_cgx; /* we are the cgx'th cylinder group */
int16_t cg_old_ncyl; /* number of cyl's this cg */
int16_t cg_old_niblk; /* number of inode blocks this cg */
int32_t cg_ndblk; /* number of data blocks this cg */
struct csum cg_cs; /* cylinder summary information */
int32_t cg_rotor; /* position of last used block */
int32_t cg_frotor; /* position of last used frag */
int32_t cg_irotor; /* position of last used inode */
int32_t cg_frsum[MAXFRAG]; /* counts of available frags */
int32_t cg_old_btotoff; /* (int32) block totals per cylinder */
int32_t cg_old_boff; /* (u_int16) free block positions */
int32_t cg_iusedoff; /* (u_int8) used inode map */
int32_t cg_freeoff; /* (u_int8) free block map */
int32_t cg_nextfreeoff; /* (u_int8) next available space */
int32_t cg_clustersumoff; /* (u_int32) counts of avail clusters */
int32_t cg_clusteroff; /* (u_int8) free cluster map */
int32_t cg_nclusterblks; /* number of clusters this cg */
int32_t cg_niblk; /* number of inode blocks this cg */
int32_t cg_initediblk; /* last initialized inode */
int32_t cg_sparecon32[3]; /* reserved for future use */
int64_t cg_time; /* time last written */
int64_t cg_sparecon64[3]; /* reserved for future use */
u_int8_t cg_space[1]; /* space for cylinder group maps */
/* actually longer */
};
/*
* The following structure is defined
* for compatibility with old file systems.
*/
struct ocg {
int32_t cg_firstfield; /* historic linked list of cyl groups */
int32_t cg_unused_1; /* used for incore cyl groups */
int32_t cg_time; /* time last written */
int32_t cg_cgx; /* we are the cgx'th cylinder group */
int16_t cg_ncyl; /* number of cyl's this cg */
int16_t cg_niblk; /* number of inode blocks this cg */
int32_t cg_ndblk; /* number of data blocks this cg */
struct csum cg_cs; /* cylinder summary information */
int32_t cg_rotor; /* position of last used block */
int32_t cg_frotor; /* position of last used frag */
int32_t cg_irotor; /* position of last used inode */
int32_t cg_frsum[8]; /* counts of available frags */
int32_t cg_btot[32]; /* block totals per cylinder */
int16_t cg_b[32][8]; /* positions of free blocks */
u_int8_t cg_iused[256]; /* used inode map */
int32_t cg_magic; /* magic number */
u_int8_t cg_free[1]; /* free block map */
/* actually longer */
};
/*
* Macros for access to cylinder group array structures.
*/
#define old_cg_blktot_old(cgp, ns) \
(((struct ocg *)(cgp))->cg_btot)
#define old_cg_blks_old(fs, cgp, cylno, ns) \
(((struct ocg *)(cgp))->cg_b[cylno])
#define old_cg_blktot_new(cgp, ns) \
((int32_t *)((u_int8_t *)(cgp) + \
ufs_rw32((cgp)->cg_old_btotoff, (ns))))
#define old_cg_blks_new(fs, cgp, cylno, ns) \
((int16_t *)((u_int8_t *)(cgp) + \
ufs_rw32((cgp)->cg_old_boff, (ns))) + (cylno) * (fs)->fs_old_nrpos)
#define old_cg_blktot(cgp, ns) \
((ufs_rw32((cgp)->cg_magic, (ns)) != CG_MAGIC) ? \
old_cg_blktot_old(cgp, ns) : old_cg_blktot_new(cgp, ns))
#define old_cg_blks(fs, cgp, cylno, ns) \
((ufs_rw32((cgp)->cg_magic, (ns)) != CG_MAGIC) ? \
old_cg_blks_old(fs, cgp, cylno, ns) : old_cg_blks_new(fs, cgp, cylno, ns))
#define cg_inosused_new(cgp, ns) \
((u_int8_t *)((u_int8_t *)(cgp) + \
ufs_rw32((cgp)->cg_iusedoff, (ns))))
#define cg_blksfree_new(cgp, ns) \
((u_int8_t *)((u_int8_t *)(cgp) + \
ufs_rw32((cgp)->cg_freeoff, (ns))))
#define cg_chkmagic_new(cgp, ns) \
(ufs_rw32((cgp)->cg_magic, (ns)) == CG_MAGIC)
#define cg_inosused_old(cgp, ns) \
(((struct ocg *)(cgp))->cg_iused)
#define cg_blksfree_old(cgp, ns) \
(((struct ocg *)(cgp))->cg_free)
#define cg_chkmagic_old(cgp, ns) \
(ufs_rw32(((struct ocg *)(cgp))->cg_magic, (ns)) == CG_MAGIC)
#define cg_inosused(cgp, ns) \
((ufs_rw32((cgp)->cg_magic, (ns)) != CG_MAGIC) ? \
cg_inosused_old(cgp, ns) : cg_inosused_new(cgp, ns))
#define cg_blksfree(cgp, ns) \
((ufs_rw32((cgp)->cg_magic, (ns)) != CG_MAGIC) ? \
cg_blksfree_old(cgp, ns) : cg_blksfree_new(cgp, ns))
#define cg_chkmagic(cgp, ns) \
(cg_chkmagic_new(cgp, ns) || cg_chkmagic_old(cgp, ns))
#define cg_clustersfree(cgp, ns) \
((u_int8_t *)((u_int8_t *)(cgp) + \
ufs_rw32((cgp)->cg_clusteroff, (ns))))
#define cg_clustersum(cgp, ns) \
((int32_t *)((u_int8_t *)(cgp) + \
ufs_rw32((cgp)->cg_clustersumoff, (ns))))
/*
* Turn file system block numbers into disk block addresses.
* This maps file system blocks to device size blocks.
*/
#define fsbtodb(fs, b) ((b) << (fs)->fs_fsbtodb)
#define dbtofsb(fs, b) ((b) >> (fs)->fs_fsbtodb)
/*
* Cylinder group macros to locate things in cylinder groups.
* They calc file system addresses of cylinder group data structures.
*/
#define cgbase(fs, c) (((daddr_t)(fs)->fs_fpg) * (c))
#define cgstart_ufs1(fs, c) \
(cgbase(fs, c) + (fs)->fs_old_cgoffset * ((c) & ~((fs)->fs_old_cgmask)))
#define cgstart_ufs2(fs, c) cgbase((fs), (c))
#define cgstart(fs, c) ((fs)->fs_magic == FS_UFS2_MAGIC \
? cgstart_ufs2((fs), (c)) : cgstart_ufs1((fs), (c)))
#define cgdmin(fs, c) (cgstart(fs, c) + (fs)->fs_dblkno) /* 1st data */
#define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */
#define cgsblock(fs, c) (cgstart(fs, c) + (fs)->fs_sblkno) /* super blk */
#define cgtod(fs, c) (cgstart(fs, c) + (fs)->fs_cblkno) /* cg block */
/*
* Macros for handling inode numbers:
* inode number to file system block offset.
* inode number to cylinder group number.
* inode number to file system block address.
*/
#define ino_to_cg(fs, x) ((x) / (fs)->fs_ipg)
#define ino_to_fsba(fs, x) \
((daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \
(blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs))))))
#define ino_to_fsbo(fs, x) ((x) % INOPB(fs))
/*
* Give cylinder group number for a file system block.
* Give cylinder group block number for a file system block.
*/
#define dtog(fs, d) ((d) / (fs)->fs_fpg)
#define dtogd(fs, d) ((d) % (fs)->fs_fpg)
/*
* Extract the bits for a block from a map.
* Compute the cylinder and rotational position of a cyl block addr.
*/
#define blkmap(fs, map, loc) \
(((map)[(loc) / NBBY] >> ((loc) % NBBY)) & (0xff >> (NBBY - (fs)->fs_frag)))
#define old_cbtocylno(fs, bno) \
(fsbtodb(fs, bno) / (fs)->fs_old_spc)
#define old_cbtorpos(fs, bno) \
((fs)->fs_old_nrpos <= 1 ? 0 : \
(fsbtodb(fs, bno) % (fs)->fs_old_spc / (fs)->fs_old_nsect * (fs)->fs_old_trackskew + \
fsbtodb(fs, bno) % (fs)->fs_old_spc % (fs)->fs_old_nsect * (fs)->fs_old_interleave) % \
(fs)->fs_old_nsect * (fs)->fs_old_nrpos / (fs)->fs_old_npsect)
/*
* The following macros optimize certain frequently calculated
* quantities by using shifts and masks in place of divisions
* modulos and multiplications.
*/
#define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \
((loc) & (fs)->fs_qbmask)
#define fragoff(fs, loc) /* calculates (loc % fs->fs_fsize) */ \
((loc) & (fs)->fs_qfmask)
#define lfragtosize(fs, frag) /* calculates ((off_t)frag * fs->fs_fsize) */ \
(((off_t)(frag)) << (fs)->fs_fshift)
#define lblktosize(fs, blk) /* calculates ((off_t)blk * fs->fs_bsize) */ \
(((off_t)(blk)) << (fs)->fs_bshift)
#define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \
((loc) >> (fs)->fs_bshift)
#define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \
((loc) >> (fs)->fs_fshift)
#define blkroundup(fs, size) /* calculates roundup(size, fs->fs_bsize) */ \
(((size) + (fs)->fs_qbmask) & (fs)->fs_bmask)
#define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \
(((size) + (fs)->fs_qfmask) & (fs)->fs_fmask)
#define fragstoblks(fs, frags) /* calculates (frags / fs->fs_frag) */ \
((frags) >> (fs)->fs_fragshift)
#define blkstofrags(fs, blks) /* calculates (blks * fs->fs_frag) */ \
((blks) << (fs)->fs_fragshift)
#define fragnum(fs, fsb) /* calculates (fsb % fs->fs_frag) */ \
((fsb) & ((fs)->fs_frag - 1))
#define blknum(fs, fsb) /* calculates rounddown(fsb, fs->fs_frag) */ \
((fsb) &~ ((fs)->fs_frag - 1))
/*
* Determine the number of available frags given a
* percentage to hold in reserve.
*/
#define freespace(fs, percentreserved) \
(blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \
(fs)->fs_cstotal.cs_nffree - \
(((off_t)((fs)->fs_dsize)) * (percentreserved) / 100))
/*
* Determining the size of a file block in the file system.
*/
#define blksize(fs, ip, lbn) \
(((lbn) >= NDADDR || (ip)->i_size >= lblktosize(fs, (lbn) + 1)) \
? (fs)->fs_bsize \
: (fragroundup(fs, blkoff(fs, (ip)->i_size))))
#define sblksize(fs, size, lbn) \
(((lbn) >= NDADDR || (size) >= ((lbn) + 1) << (fs)->fs_bshift) \
? (fs)->fs_bsize \
: (fragroundup(fs, blkoff(fs, (size)))))
/*
* Number of inodes in a secondary storage block/fragment.
*/
#define INOPB(fs) ((fs)->fs_inopb)
#define INOPF(fs) ((fs)->fs_inopb >> (fs)->fs_fragshift)
/*
* Number of indirects in a file system block.
*/
#define NINDIR(fs) ((fs)->fs_nindir)
/*
* Apple UFS Label:
* We check for this to decide to use APPLEUFS_DIRBLKSIZ
*/
#define APPLEUFS_LABEL_MAGIC 0x4c41424c /* LABL */
#define APPLEUFS_LABEL_SIZE 1024
#define APPLEUFS_LABEL_OFFSET (BBSIZE - APPLEUFS_LABEL_SIZE) /* located at 7k */
#define APPLEUFS_LABEL_VERSION 1
#define APPLEUFS_MAX_LABEL_NAME 512
#if 0
struct appleufslabel {
u_int32_t ul_magic;
u_int16_t ul_checksum;
u_int16_t ul_unused0;
u_int32_t ul_version;
u_int32_t ul_time;
u_int16_t ul_namelen;
u_char ul_name[APPLEUFS_MAX_LABEL_NAME]; /* Warning: may not be null terminated */
u_int16_t ul_unused1;
u_int64_t ul_uuid; /* Note this is only 4 byte aligned */
u_char ul_reserved[24];
u_char ul_unused[460];
} __attribute__((__packed__));
#endif
#endif /* !_UFS_FFS_FS_H_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,22 @@
/* type.h */
typedef unsigned char u_char;
typedef __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int8 u_int8_t;
typedef __int16 int16_t;
typedef unsigned __int16 u_int16_t;
typedef unsigned __int16 uint16_t;
typedef __int32 int32_t;
typedef unsigned __int32 u_int;
typedef unsigned __int32 uint32_t;
typedef unsigned __int32 u_int32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
typedef unsigned __int64 u_int64_t;
typedef __int64 daddr_t;

View file

@ -0,0 +1,681 @@
/*
* FFS File System Driver for Windows
*
* block.c
*
* 2004.5.6 ~
*
* Lee Jae-Hong, http://www.pyrasis.com
*
* See License.txt
*
*/
#include "ntifs.h"
#include "ffsdrv.h"
/* Globals */
extern PFFS_GLOBAL FFSGlobal;
/* Definitions */
typedef struct _FFS_RW_CONTEXT {
PIRP MasterIrp;
KEVENT Event;
BOOLEAN Wait;
LONG Blocks;
ULONG Length;
} FFS_RW_CONTEXT, *PFFS_RW_CONTEXT;
#ifdef _PREFAST_
IO_COMPLETION_ROUTINE FFSReadWriteBlockSyncCompletionRoutine;
IO_COMPLETION_ROUTINE FFSReadWriteBlockAsyncCompletionRoutine;
IO_COMPLETION_ROUTINE FFSMediaEjectControlCompletion;
#endif // _PREFAST_
NTSTATUS NTAPI
FFSReadWriteBlockSyncCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context);
NTSTATUS NTAPI
FFSReadWriteBlockAsyncCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context);
NTSTATUS NTAPI
FFSMediaEjectControlCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSLockUserBuffer)
#pragma alloc_text(PAGE, FFSGetUserBuffer)
#pragma alloc_text(PAGE, FFSReadSync)
#pragma alloc_text(PAGE, FFSReadDisk)
#pragma alloc_text(PAGE, FFSDiskIoControl)
#pragma alloc_text(PAGE, FFSReadWriteBlocks)
#pragma alloc_text(PAGE, FFSMediaEjectControl)
#pragma alloc_text(PAGE, FFSDiskShutDown)
#endif
NTSTATUS
FFSLockUserBuffer(
IN PIRP Irp,
IN ULONG Length,
IN LOCK_OPERATION Operation)
{
NTSTATUS Status;
PAGED_CODE();
ASSERT(Irp != NULL);
if (Irp->MdlAddress != NULL)
{
return STATUS_SUCCESS;
}
IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp);
if (Irp->MdlAddress == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
_SEH2_TRY
{
MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation);
Status = STATUS_SUCCESS;
}
_SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER)
{
IoFreeMdl(Irp->MdlAddress);
Irp->MdlAddress = NULL;
FFSBreakPoint();
Status = STATUS_INVALID_USER_BUFFER;
} _SEH2_END;
return Status;
}
PVOID
FFSGetUserBuffer(
IN PIRP Irp)
{
PAGED_CODE();
ASSERT(Irp != NULL);
if (Irp->MdlAddress)
{
#if (_WIN32_WINNT >= 0x0500)
return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
#else
return MmGetSystemAddressForMdl(Irp->MdlAddress);
#endif
}
else
{
return Irp->UserBuffer;
}
}
NTSTATUS NTAPI
FFSReadWriteBlockSyncCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
PFFS_RW_CONTEXT pContext = (PFFS_RW_CONTEXT)Context;
if (!NT_SUCCESS(Irp->IoStatus.Status))
{
pContext->MasterIrp->IoStatus = Irp->IoStatus;
}
IoFreeMdl(Irp->MdlAddress);
IoFreeIrp(Irp);
if (InterlockedDecrement(&pContext->Blocks) == 0)
{
pContext->MasterIrp->IoStatus.Information = 0;
if (NT_SUCCESS(pContext->MasterIrp->IoStatus.Status))
{
pContext->MasterIrp->IoStatus.Information =
pContext->Length;
}
KeSetEvent(&pContext->Event, 0, FALSE);
}
UNREFERENCED_PARAMETER(DeviceObject);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS NTAPI
FFSReadWriteBlockAsyncCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
PFFS_RW_CONTEXT pContext = (PFFS_RW_CONTEXT)Context;
if (!NT_SUCCESS(Irp->IoStatus.Status))
{
pContext->MasterIrp->IoStatus = Irp->IoStatus;
}
if (InterlockedDecrement(&pContext->Blocks) == 0)
{
pContext->MasterIrp->IoStatus.Information = 0;
if (NT_SUCCESS(pContext->MasterIrp->IoStatus.Status))
{
pContext->MasterIrp->IoStatus.Information =
pContext->Length;
}
IoMarkIrpPending(pContext->MasterIrp);
ExFreePool(pContext);
}
UNREFERENCED_PARAMETER(DeviceObject);
return STATUS_SUCCESS;
}
NTSTATUS
FFSReadWriteBlocks(
IN PFFS_IRP_CONTEXT IrpContext,
IN PFFS_VCB Vcb,
IN PFFS_BDL FFSBDL,
IN ULONG Length,
IN ULONG Count,
IN BOOLEAN bVerify)
{
PMDL Mdl;
PIRP Irp;
PIRP MasterIrp = IrpContext->Irp;
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status = STATUS_SUCCESS;
PFFS_RW_CONTEXT pContext = NULL;
ULONG i;
BOOLEAN bBugCheck = FALSE;
PAGED_CODE();
ASSERT(MasterIrp);
_SEH2_TRY
{
pContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(FFS_RW_CONTEXT), FFS_POOL_TAG);
if (!pContext)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
_SEH2_LEAVE;
}
RtlZeroMemory(pContext, sizeof(FFS_RW_CONTEXT));
pContext->Wait = IrpContext->IsSynchronous;
pContext->MasterIrp = MasterIrp;
pContext->Blocks = Count;
pContext->Length = 0;
if (pContext->Wait)
{
KeInitializeEvent(&(pContext->Event), NotificationEvent, FALSE);
}
for (i = 0; i < Count; i++)
{
Irp = IoMakeAssociatedIrp(MasterIrp,
(CCHAR)(Vcb->TargetDeviceObject->StackSize + 1));
if (!Irp)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
_SEH2_LEAVE;
}
Mdl = IoAllocateMdl((PCHAR)MasterIrp->UserBuffer +
FFSBDL[i].Offset,
FFSBDL[i].Length,
FALSE,
FALSE,
Irp);
if (!Mdl)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
_SEH2_LEAVE;
}
IoBuildPartialMdl(MasterIrp->MdlAddress,
Mdl,
(PCHAR)MasterIrp->UserBuffer + FFSBDL[i].Offset,
FFSBDL[i].Length);
IoSetNextIrpStackLocation(Irp);
IrpSp = IoGetCurrentIrpStackLocation(Irp);
IrpSp->MajorFunction = IrpContext->MajorFunction;
IrpSp->Parameters.Read.Length = FFSBDL[i].Length;
IrpSp->Parameters.Read.ByteOffset.QuadPart = FFSBDL[i].Lba;
IoSetCompletionRoutine(Irp,
IrpContext->IsSynchronous ?
&FFSReadWriteBlockSyncCompletionRoutine :
&FFSReadWriteBlockAsyncCompletionRoutine,
(PVOID) pContext,
TRUE,
TRUE,
TRUE);
IrpSp = IoGetNextIrpStackLocation(Irp);
IrpSp->MajorFunction = IrpContext->MajorFunction;
IrpSp->Parameters.Read.Length = FFSBDL[i].Length;
IrpSp->Parameters.Read.ByteOffset.QuadPart = FFSBDL[i].Lba;
if (bVerify)
{
SetFlag(IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME);
}
FFSBDL[i].Irp = Irp;
}
MasterIrp->AssociatedIrp.IrpCount = Count;
if (IrpContext->IsSynchronous)
{
MasterIrp->AssociatedIrp.IrpCount += 1;
}
pContext->Length = Length;
bBugCheck = TRUE;
for (i = 0; i < Count; i++)
{
Status = IoCallDriver(Vcb->TargetDeviceObject,
FFSBDL[i].Irp);
}
if (IrpContext->IsSynchronous)
{
KeWaitForSingleObject(&(pContext->Event),
Executive, KernelMode, FALSE, NULL);
KeClearEvent(&(pContext->Event));
}
}
_SEH2_FINALLY
{
if (IrpContext->IsSynchronous)
{
if (MasterIrp)
Status = MasterIrp->IoStatus.Status;
if (pContext)
ExFreePool(pContext);
}
else
{
IrpContext->Irp = NULL;
Status = STATUS_PENDING;
}
if (_SEH2_AbnormalTermination())
{
if (bBugCheck)
{
FFSBugCheck(FFS_BUGCHK_BLOCK, 0, 0, 0);
}
for (i = 0; i < Count; i++)
{
if (FFSBDL[i].Irp != NULL)
{
if (FFSBDL[i].Irp->MdlAddress != NULL)
{
IoFreeMdl(FFSBDL[i].Irp->MdlAddress);
}
IoFreeIrp(FFSBDL[i].Irp);
}
}
}
} _SEH2_END;
return Status;
}
NTSTATUS
FFSReadSync(
IN PFFS_VCB Vcb,
IN ULONGLONG Offset,
IN ULONG Length,
OUT PVOID Buffer,
IN BOOLEAN bVerify)
{
KEVENT Event;
PIRP Irp;
IO_STATUS_BLOCK IoStatus;
NTSTATUS Status;
PAGED_CODE();
ASSERT(Vcb != NULL);
ASSERT(Vcb->TargetDeviceObject != NULL);
ASSERT(Buffer != NULL);
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildSynchronousFsdRequest(
IRP_MJ_READ,
Vcb->TargetDeviceObject,
Buffer,
Length,
(PLARGE_INTEGER)(&Offset),
&Event,
&IoStatus);
if (!Irp)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
if (bVerify)
{
SetFlag(IoGetNextIrpStackLocation(Irp)->Flags,
SL_OVERRIDE_VERIFY_VOLUME);
}
Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(
&Event,
Suspended,
KernelMode,
FALSE,
NULL);
Status = IoStatus.Status;
}
return Status;
}
NTSTATUS
FFSReadDisk(
IN PFFS_VCB Vcb,
IN ULONGLONG Offset,
IN ULONG Size,
IN PVOID Buffer,
IN BOOLEAN bVerify)
{
NTSTATUS Status;
PUCHAR Buf;
ULONG Length;
ULONGLONG Lba;
PAGED_CODE();
Lba = Offset & (~((ULONGLONG)SECTOR_SIZE - 1));
Length = (ULONG)(Size + Offset + SECTOR_SIZE - 1 - Lba) &
(~((ULONG)SECTOR_SIZE - 1));
Buf = ExAllocatePoolWithTag(PagedPool, Length, FFS_POOL_TAG);
if (!Buf)
{
FFSPrint((DBG_ERROR, "FFSReadDisk: no enough memory.\n"));
Status = STATUS_INSUFFICIENT_RESOURCES;
goto errorout;
}
Status = FFSReadSync(Vcb,
Lba,
Length,
Buf,
FALSE);
if (!NT_SUCCESS(Status))
{
FFSPrint((DBG_ERROR, "FFSReadDisk: Read Block Device error.\n"));
goto errorout;
}
RtlCopyMemory(Buffer, &Buf[Offset - Lba], Size);
errorout:
if (Buf)
ExFreePool(Buf);
return Status;
}
NTSTATUS
FFSDiskIoControl(
IN PDEVICE_OBJECT DeviceObject,
IN ULONG IoctlCode,
IN PVOID InputBuffer,
IN ULONG InputBufferSize,
IN OUT PVOID OutputBuffer,
IN OUT PULONG OutputBufferSize)
{
ULONG OutBufferSize = 0;
KEVENT Event;
PIRP Irp;
IO_STATUS_BLOCK IoStatus;
NTSTATUS Status;
PAGED_CODE();
ASSERT(DeviceObject != NULL);
if (OutputBufferSize)
{
OutBufferSize = *OutputBufferSize;
}
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(
IoctlCode,
DeviceObject,
InputBuffer,
InputBufferSize,
OutputBuffer,
OutBufferSize,
FALSE,
&Event,
&IoStatus);
if (Irp == NULL)
{
FFSPrint((DBG_ERROR, "FFSDiskIoControl: Building IRQ error!\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
if (OutputBufferSize)
{
*OutputBufferSize = (ULONG) IoStatus.Information;
}
return Status;
}
NTSTATUS NTAPI
FFSMediaEjectControlCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt)
{
PKEVENT Event = (PKEVENT)Contxt;
KeSetEvent(Event, 0, FALSE);
UNREFERENCED_PARAMETER(DeviceObject);
return STATUS_SUCCESS;
}
__drv_mustHoldCriticalRegion
VOID
FFSMediaEjectControl(
IN PFFS_IRP_CONTEXT IrpContext,
IN PFFS_VCB Vcb,
IN BOOLEAN bPrevent)
{
PIRP Irp;
KEVENT Event;
NTSTATUS Status;
PREVENT_MEDIA_REMOVAL Prevent;
IO_STATUS_BLOCK IoStatus;
PAGED_CODE();
ExAcquireResourceExclusiveLite(
&Vcb->MainResource,
TRUE);
if (bPrevent != IsFlagOn(Vcb->Flags, VCB_REMOVAL_PREVENTED))
{
if (bPrevent)
{
SetFlag(Vcb->Flags, VCB_REMOVAL_PREVENTED);
}
else
{
ClearFlag(Vcb->Flags, VCB_REMOVAL_PREVENTED);
}
}
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread());
Prevent.PreventMediaRemoval = bPrevent;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_MEDIA_REMOVAL,
Vcb->TargetDeviceObject,
&Prevent,
sizeof(PREVENT_MEDIA_REMOVAL),
NULL,
0,
FALSE,
NULL,
&IoStatus);
if (Irp != NULL)
{
IoSetCompletionRoutine(Irp,
FFSMediaEjectControlCompletion,
&Event,
TRUE,
TRUE,
TRUE);
Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
if (Status == STATUS_PENDING)
{
Status = KeWaitForSingleObject(&Event,
Executive,
KernelMode,
FALSE,
NULL);
}
}
}
NTSTATUS
FFSDiskShutDown(
PFFS_VCB Vcb)
{
PIRP Irp;
KEVENT Event;
NTSTATUS Status;
IO_STATUS_BLOCK IoStatus;
PAGED_CODE();
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN,
Vcb->TargetDeviceObject,
NULL,
0,
NULL,
&Event,
&IoStatus);
if (Irp)
{
Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event,
Executive,
KernelMode,
FALSE,
NULL);
Status = IoStatus.Status;
}
}
else
{
Status = IoStatus.Status;
}
return Status;
}

View file

@ -0,0 +1,380 @@
/*
* FFS File System Driver for Windows
*
* cleanup.c
*
* 2004.5.6 ~
*
* Lee Jae-Hong, http://www.pyrasis.com
*
* See License.txt
*
*/
#include "ntifs.h"
#include "ffsdrv.h"
/* Globals */
extern PFFS_GLOBAL FFSGlobal;
/* Definitions */
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSCleanup)
#endif
__drv_mustHoldCriticalRegion
NTSTATUS
FFSCleanup(
IN PFFS_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status = STATUS_SUCCESS;
PFFS_VCB Vcb = 0;
BOOLEAN VcbResourceAcquired = FALSE;
PFILE_OBJECT FileObject;
PFFS_FCB Fcb = 0;
BOOLEAN FcbResourceAcquired = FALSE;
BOOLEAN FcbPagingIoAcquired = FALSE;
PFFS_CCB Ccb;
PIRP Irp;
PAGED_CODE();
_SEH2_TRY
{
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
if (DeviceObject == FFSGlobal->DeviceObject)
{
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == FFSVCB) &&
(Vcb->Identifier.Size == sizeof(FFS_VCB)));
if (!IsFlagOn(Vcb->Flags, VCB_INITIALIZED))
{
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
if (!ExAcquireResourceExclusiveLite(
&Vcb->MainResource,
IrpContext->IsSynchronous))
{
Status = STATUS_PENDING;
_SEH2_LEAVE;
}
VcbResourceAcquired = TRUE;
FileObject = IrpContext->FileObject;
Fcb = (PFFS_FCB)FileObject->FsContext;
if (!Fcb)
{
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
if (Fcb->Identifier.Type == FFSVCB)
{
if (IsFlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
(Vcb->LockFile == FileObject))
{
ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
Vcb->LockFile = NULL;
FFSClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
}
Vcb->OpenHandleCount--;
if (!Vcb->OpenHandleCount)
{
IoRemoveShareAccess(FileObject, &Vcb->ShareAccess);
}
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
ASSERT((Fcb->Identifier.Type == FFSFCB) &&
(Fcb->Identifier.Size == sizeof(FFS_FCB)));
/*
if (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY) &&
!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE))
*/
{
#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
if (!ExAcquireResourceExclusiveLite(
&Fcb->MainResource,
IrpContext->IsSynchronous))
{
Status = STATUS_PENDING;
_SEH2_LEAVE;
}
FcbResourceAcquired = TRUE;
}
Ccb = (PFFS_CCB)FileObject->FsContext2;
if (!Ccb)
{
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE))
{
if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) &&
!IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
{
Status = FFSFlushFile(Fcb);
}
_SEH2_LEAVE;
}
ASSERT((Ccb->Identifier.Type == FFSCCB) &&
(Ccb->Identifier.Size == sizeof(FFS_CCB)));
Irp = IrpContext->Irp;
Fcb->OpenHandleCount--;
if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED))
{
Fcb->NonCachedOpenCount--;
}
Vcb->OpenFileHandleCount--;
if (IsFlagOn(Fcb->Flags, FCB_DELETE_ON_CLOSE))
{
SetFlag(Fcb->Flags, FCB_DELETE_PENDING);
if (IsDirectory(Fcb))
{
FsRtlNotifyFullChangeDirectory(
Vcb->NotifySync,
&Vcb->NotifyList,
Fcb,
NULL,
FALSE,
FALSE,
0,
NULL,
NULL,
NULL);
}
}
if (IsDirectory(Fcb))
{
FsRtlNotifyCleanup(
Vcb->NotifySync,
&Vcb->NotifyList,
Ccb);
}
else
{
//
// Drop any byte range locks this process may have on the file.
//
FsRtlFastUnlockAll(
&Fcb->FileLockAnchor,
FileObject,
IoGetRequestorProcess(Irp),
NULL);
//
// If there are no byte range locks owned by other processes on the
// file the fast I/O read/write functions doesn't have to check for
// locks so we set IsFastIoPossible to FastIoIsPossible again.
//
if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE))
{
if (Fcb->Header.IsFastIoPossible != FastIoIsPossible)
{
FFSPrint((
DBG_INFO, ": %-16.16s %-31s %s\n",
FFSGetCurrentProcessName(),
"FastIoIsPossible",
Fcb->AnsiFileName.Buffer));
Fcb->Header.IsFastIoPossible = FastIoIsPossible;
}
}
}
if (IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
(Fcb->NonCachedOpenCount != 0) &&
(Fcb->NonCachedOpenCount == Fcb->ReferenceCount) &&
(Fcb->SectionObject.DataSectionObject != NULL))
{
if(!IsFlagOn(Vcb->Flags, VCB_READ_ONLY) &&
!IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
{
CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
}
ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE);
ExReleaseResourceLite(&(Fcb->PagingIoResource));
CcPurgeCacheSection(&Fcb->SectionObject,
NULL,
0,
FALSE);
}
#if !FFS_READ_ONLY
if (Fcb->OpenHandleCount == 0)
{
if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING))
{
BOOLEAN bDeleted = FALSE;
//
// Have to delete this file...
//
#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
if (!ExAcquireResourceExclusiveLite(
&Fcb->PagingIoResource,
IrpContext->IsSynchronous))
{
Status = STATUS_PENDING;
_SEH2_LEAVE;
}
FcbPagingIoAcquired = TRUE;
bDeleted = FFSDeleteFile(IrpContext, Vcb, Fcb);
if (bDeleted)
{
if (IsDirectory(Fcb))
{
FFSNotifyReportChange(IrpContext, Vcb, Fcb,
FILE_NOTIFY_CHANGE_DIR_NAME,
FILE_ACTION_REMOVED);
}
else
{
FFSNotifyReportChange(IrpContext, Vcb, Fcb,
FILE_NOTIFY_CHANGE_FILE_NAME,
FILE_ACTION_REMOVED);
}
}
if (FcbPagingIoAcquired)
{
ExReleaseResourceForThreadLite(
&Fcb->PagingIoResource,
ExGetCurrentResourceThread());
FcbPagingIoAcquired = FALSE;
}
/*
if (bDeleted)
{
FFSPurgeFile(Fcb, FALSE);
}
*/
}
}
#endif // !FFS_READ_ONLY
if (!IsDirectory(Fcb) && FileObject->PrivateCacheMap)
{
FFSPrint((DBG_INFO, "FFSCleanup: CcUninitializeCacheMap is called for %s.\n",
Fcb->AnsiFileName.Buffer));
CcUninitializeCacheMap(
FileObject,
(PLARGE_INTEGER)(&(Fcb->Header.FileSize)),
NULL);
}
if (!Fcb->OpenHandleCount)
{
IoRemoveShareAccess(FileObject, &Fcb->ShareAccess);
}
FFSPrint((DBG_INFO, "FFSCleanup: OpenCount: %u ReferCount: %u %s\n",
Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->AnsiFileName.Buffer));
Status = STATUS_SUCCESS;
if (FileObject)
{
SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
}
}
_SEH2_FINALLY
{
if (FcbPagingIoAcquired)
{
ExReleaseResourceForThreadLite(
&Fcb->PagingIoResource,
ExGetCurrentResourceThread());
}
if (FcbResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Fcb->MainResource,
ExGetCurrentResourceThread());
}
if (VcbResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread());
}
if (!IrpContext->ExceptionInProgress)
{
if (Status == STATUS_PENDING)
{
FFSQueueRequest(IrpContext);
}
else
{
IrpContext->Irp->IoStatus.Status = Status;
FFSCompleteIrpContext(IrpContext, Status);
}
}
} _SEH2_END;
return Status;
}

View file

@ -0,0 +1,342 @@
/*
* FFS File System Driver for Windows
*
* close.c
*
* 2004.5.6 ~
*
* Lee Jae-Hong, http://www.pyrasis.com
*
* See License.txt
*
*/
#include "ntifs.h"
#include "ffsdrv.h"
/* Globals */
extern PFFS_GLOBAL FFSGlobal;
/* Definitions */
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSClose)
#pragma alloc_text(PAGE, FFSQueueCloseRequest)
#pragma alloc_text(PAGE, FFSDeQueueCloseRequest)
#endif
__drv_mustHoldCriticalRegion
NTSTATUS
FFSClose(
IN PFFS_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status = STATUS_SUCCESS;
PFFS_VCB Vcb = 0;
BOOLEAN VcbResourceAcquired = FALSE;
PFILE_OBJECT FileObject;
PFFS_FCB Fcb = 0;
BOOLEAN FcbResourceAcquired = FALSE;
PFFS_CCB Ccb;
BOOLEAN FreeVcb = FALSE;
PAGED_CODE();
_SEH2_TRY
{
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
if (DeviceObject == FFSGlobal->DeviceObject)
{
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
Vcb = (PFFS_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == FFSVCB) &&
(Vcb->Identifier.Size == sizeof(FFS_VCB)));
ASSERT(IsMounted(Vcb));
if (!ExAcquireResourceExclusiveLite(
&Vcb->MainResource,
IrpContext->IsSynchronous))
{
FFSPrint((DBG_INFO, "FFSClose: PENDING ... Vcb: %xh/%xh\n",
Vcb->OpenFileHandleCount, Vcb->ReferenceCount));
Status = STATUS_PENDING;
_SEH2_LEAVE;
}
VcbResourceAcquired = TRUE;
FileObject = IrpContext->FileObject;
if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE))
{
Fcb = IrpContext->Fcb;
Ccb = IrpContext->Ccb;
}
else
{
Fcb = (PFFS_FCB)FileObject->FsContext;
if (!Fcb)
{
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
ASSERT(Fcb != NULL);
Ccb = (PFFS_CCB)FileObject->FsContext2;
}
if (Fcb->Identifier.Type == FFSVCB)
{
Vcb->ReferenceCount--;
if (!Vcb->ReferenceCount && FlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
{
FreeVcb = TRUE;
}
if (Ccb)
{
FFSFreeCcb(Ccb);
if (FileObject)
{
FileObject->FsContext2 = Ccb = NULL;
}
}
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
if (Fcb->Identifier.Type != FFSFCB || Fcb->Identifier.Size != sizeof(FFS_FCB))
{
#if DBG
FFSPrint((DBG_ERROR, "FFSClose: Strange IRP_MJ_CLOSE by system!\n"));
ExAcquireResourceExclusiveLite(
&FFSGlobal->CountResource,
TRUE);
FFSGlobal->IRPCloseCount++;
ExReleaseResourceForThreadLite(
&FFSGlobal->CountResource,
ExGetCurrentResourceThread());
#endif
_SEH2_LEAVE;
}
ASSERT((Fcb->Identifier.Type == FFSFCB) &&
(Fcb->Identifier.Size == sizeof(FFS_FCB)));
/*
if ((!IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) &&
(!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)))
*/
{
if (!ExAcquireResourceExclusiveLite(
&Fcb->MainResource,
IrpContext->IsSynchronous))
{
Status = STATUS_PENDING;
_SEH2_LEAVE;
}
FcbResourceAcquired = TRUE;
}
if (!Ccb)
{
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
ASSERT((Ccb->Identifier.Type == FFSCCB) &&
(Ccb->Identifier.Size == sizeof(FFS_CCB)));
Fcb->ReferenceCount--;
Vcb->ReferenceCount--;
if (!Vcb->ReferenceCount && IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
{
FreeVcb = TRUE;
}
FFSPrint((DBG_INFO, "FFSClose: OpenHandleCount: %u ReferenceCount: %u %s\n",
Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->AnsiFileName.Buffer));
if (Ccb)
{
FFSFreeCcb(Ccb);
if (FileObject)
{
FileObject->FsContext2 = Ccb = NULL;
}
}
if (!Fcb->ReferenceCount)
{
//
// Remove Fcb from Vcb->FcbList ...
//
RemoveEntryList(&Fcb->Next);
FFSFreeFcb(Fcb);
FcbResourceAcquired = FALSE;
}
Status = STATUS_SUCCESS;
}
_SEH2_FINALLY
{
if (FcbResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Fcb->MainResource,
ExGetCurrentResourceThread());
}
if (VcbResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread());
}
if (!IrpContext->ExceptionInProgress)
{
if (Status == STATUS_PENDING)
{
FFSQueueCloseRequest(IrpContext);
#if 0
/*
Status = STATUS_SUCCESS;
if (IrpContext->Irp != NULL)
{
IrpContext->Irp->IoStatus.Status = Status;
FFSCompleteRequest(
IrpContext->Irp,
(BOOLEAN)!IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED),
(CCHAR)
(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
IrpContext->Irp = NULL;
}
*/
#endif
}
else
{
FFSCompleteIrpContext(IrpContext, Status);
if (FreeVcb)
{
ExAcquireResourceExclusiveLite(
&FFSGlobal->Resource, TRUE);
FFSClearVpbFlag(Vcb->Vpb, VPB_MOUNTED);
FFSRemoveVcb(Vcb);
ExReleaseResourceForThreadLite(
&FFSGlobal->Resource,
ExGetCurrentResourceThread());
FFSFreeVcb(Vcb);
}
}
}
} _SEH2_END;
return Status;
}
VOID
FFSQueueCloseRequest(
IN PFFS_IRP_CONTEXT IrpContext)
{
PAGED_CODE();
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
if (!IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE))
{
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE);
IrpContext->Fcb = (PFFS_FCB)IrpContext->FileObject->FsContext;
IrpContext->Ccb = (PFFS_CCB)IrpContext->FileObject->FsContext2;
IrpContext->FileObject = NULL;
}
// IsSynchronous means we can block (so we don't requeue it)
IrpContext->IsSynchronous = TRUE;
ExInitializeWorkItem(
&IrpContext->WorkQueueItem,
FFSDeQueueCloseRequest,
IrpContext);
ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
}
VOID NTAPI
FFSDeQueueCloseRequest(
IN PVOID Context)
{
PFFS_IRP_CONTEXT IrpContext;
PAGED_CODE();
IrpContext = (PFFS_IRP_CONTEXT) Context;
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
_SEH2_TRY
{
_SEH2_TRY
{
FsRtlEnterFileSystem();
FFSClose(IrpContext);
}
_SEH2_EXCEPT (FFSExceptionFilter(IrpContext, _SEH2_GetExceptionInformation()))
{
FFSExceptionHandler(IrpContext);
} _SEH2_END;
}
_SEH2_FINALLY
{
FsRtlExitFileSystem();
} _SEH2_END;
}

View file

@ -0,0 +1,218 @@
/*
* FFS File System Driver for Windows
*
* cmcb.c
*
* 2004.5.6 ~
*
* Lee Jae-Hong, http://www.pyrasis.com
*
* See License.txt
*
*/
#include "ntifs.h"
#include "ffsdrv.h"
/* Globals */
extern PFFS_GLOBAL FFSGlobal;
/* Definitions */
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSAcquireForLazyWrite)
#pragma alloc_text(PAGE, FFSReleaseFromLazyWrite)
#pragma alloc_text(PAGE, FFSAcquireForReadAhead)
#pragma alloc_text(PAGE, FFSReleaseFromReadAhead)
#pragma alloc_text(PAGE, FFSNoOpAcquire)
#pragma alloc_text(PAGE, FFSNoOpRelease)
#endif
__drv_mustHoldCriticalRegion
BOOLEAN NTAPI
FFSAcquireForLazyWrite(
IN PVOID Context,
IN BOOLEAN Wait)
{
//
// On a readonly filesystem this function still has to exist but it
// doesn't need to do anything.
PFFS_FCB Fcb;
PAGED_CODE();
Fcb = (PFFS_FCB)Context;
ASSERT(Fcb != NULL);
ASSERT((Fcb->Identifier.Type == FFSFCB) &&
(Fcb->Identifier.Size == sizeof(FFS_FCB)));
FFSPrint((DBG_INFO, "FFSAcquireForLazyWrite: %s %s %s\n",
FFSGetCurrentProcessName(),
"ACQUIRE_FOR_LAZY_WRITE",
Fcb->AnsiFileName.Buffer));
if (!IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY))
{
FFSPrint((DBG_INFO, "FFSAcquireForLazyWrite: Inode=%xh %S\n",
Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer));
if(!ExAcquireResourceSharedLite(
&Fcb->PagingIoResource, Wait))
{
return FALSE;
}
}
ASSERT(IoGetTopLevelIrp() == NULL);
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
return TRUE;
}
__drv_mustHoldCriticalRegion
VOID NTAPI
FFSReleaseFromLazyWrite(
IN PVOID Context)
{
//
// On a readonly filesystem this function still has to exist but it
// doesn't need to do anything.
PFFS_FCB Fcb;
PAGED_CODE();
Fcb = (PFFS_FCB)Context;
ASSERT(Fcb != NULL);
ASSERT((Fcb->Identifier.Type == FFSFCB) &&
(Fcb->Identifier.Size == sizeof(FFS_FCB)));
FFSPrint((DBG_INFO, "FFSReleaseFromLazyWrite: %s %s %s\n",
FFSGetCurrentProcessName(),
"RELEASE_FROM_LAZY_WRITE",
Fcb->AnsiFileName.Buffer));
if (!IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY))
{
FFSPrint((DBG_INFO, "FFSReleaseFromLazyWrite: Inode=%xh %S\n",
Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer));
ExReleaseResourceLite(&Fcb->PagingIoResource);
}
ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
IoSetTopLevelIrp(NULL);
}
__drv_mustHoldCriticalRegion
BOOLEAN NTAPI
FFSAcquireForReadAhead(
IN PVOID Context,
IN BOOLEAN Wait)
{
PFFS_FCB Fcb;
PAGED_CODE();
Fcb = (PFFS_FCB)Context;
ASSERT(Fcb != NULL);
ASSERT((Fcb->Identifier.Type == FFSFCB) &&
(Fcb->Identifier.Size == sizeof(FFS_FCB)));
FFSPrint((DBG_INFO, "FFSAcquireForReadAhead: Inode=%xh %S\n",
Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer));
if (!ExAcquireResourceSharedLite(
&Fcb->MainResource, Wait))
return FALSE;
ASSERT(IoGetTopLevelIrp() == NULL);
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
return TRUE;
}
__drv_mustHoldCriticalRegion
VOID NTAPI
FFSReleaseFromReadAhead(
IN PVOID Context)
{
PFFS_FCB Fcb;
PAGED_CODE();
Fcb = (PFFS_FCB)Context;
ASSERT(Fcb != NULL);
ASSERT((Fcb->Identifier.Type == FFSFCB) &&
(Fcb->Identifier.Size == sizeof(FFS_FCB)));
FFSPrint((DBG_INFO, "FFSReleaseFromReadAhead: Inode=%xh %S\n",
Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer));
IoSetTopLevelIrp(NULL);
ExReleaseResourceLite(&Fcb->MainResource);
}
BOOLEAN NTAPI
FFSNoOpAcquire(
IN PVOID Fcb,
IN BOOLEAN Wait)
{
UNREFERENCED_PARAMETER(Fcb);
UNREFERENCED_PARAMETER(Wait);
//
// This is a kludge because Cc is really the top level. We it
// enters the file system, we will think it is a resursive call
// and complete the request with hard errors or verify. It will
// have to deal with them, somehow....
//
PAGED_CODE();
ASSERT(IoGetTopLevelIrp() == NULL);
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
return TRUE;
}
VOID NTAPI
FFSNoOpRelease(
IN PVOID Fcb)
{
//
// Clear the kludge at this point.
//
PAGED_CODE();
ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
IoSetTopLevelIrp(NULL);
UNREFERENCED_PARAMETER(Fcb);
return;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,302 @@
/*
* FFS File System Driver for Windows
*
* devctl.c
*
* 2004.5.6 ~
*
* Lee Jae-Hong, http://www.pyrasis.com
*
* See License.txt
*
*/
#include "ntifs.h"
#include "ffsdrv.h"
/* Globals */
extern PFFS_GLOBAL FFSGlobal;
/* Definitions */
#ifdef _PREFAST_
IO_COMPLETION_ROUTINE FFSDeviceControlCompletion;
#endif // _PREFAST_
NTSTATUS NTAPI
FFSDeviceControlCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSDeviceControl)
#pragma alloc_text(PAGE, FFSDeviceControlNormal)
#if FFS_UNLOAD
#pragma alloc_text(PAGE, FFSPrepareToUnload)
#endif
#endif
NTSTATUS NTAPI
FFSDeviceControlCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
if (Irp->PendingReturned)
{
IoMarkIrpPending(Irp);
}
return STATUS_SUCCESS;
}
__drv_mustHoldCriticalRegion
NTSTATUS
FFSDeviceControlNormal(
IN PFFS_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT DeviceObject;
BOOLEAN CompleteRequest = TRUE;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PFFS_VCB Vcb;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
PIO_STACK_LOCATION NextIrpSp;
PDEVICE_OBJECT TargetDeviceObject;
PAGED_CODE();
_SEH2_TRY
{
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
CompleteRequest = TRUE;
DeviceObject = IrpContext->DeviceObject;
if (DeviceObject == FFSGlobal->DeviceObject)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
_SEH2_LEAVE;
}
Irp = IrpContext->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Vcb = (PFFS_VCB)IrpSp->FileObject->FsContext;
if (!((Vcb) && (Vcb->Identifier.Type == FFSVCB) &&
(Vcb->Identifier.Size == sizeof(FFS_VCB))
)
)
{
Status = STATUS_INVALID_PARAMETER;
_SEH2_LEAVE;
}
TargetDeviceObject = Vcb->TargetDeviceObject;
//
// Pass on the IOCTL to the driver below
//
CompleteRequest = FALSE;
NextIrpSp = IoGetNextIrpStackLocation(Irp);
*NextIrpSp = *IrpSp;
IoSetCompletionRoutine(
Irp,
FFSDeviceControlCompletion,
NULL,
FALSE,
TRUE,
TRUE);
Status = IoCallDriver(TargetDeviceObject, Irp);
}
_SEH2_FINALLY
{
if (!IrpContext->ExceptionInProgress)
{
if (IrpContext)
{
if (!CompleteRequest)
{
IrpContext->Irp = NULL;
}
FFSCompleteIrpContext(IrpContext, Status);
}
}
} _SEH2_END;
return Status;
}
#if FFS_UNLOAD
__drv_mustHoldCriticalRegion
NTSTATUS
FFSPrepareToUnload(
IN PFFS_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
BOOLEAN GlobalDataResourceAcquired = FALSE;
PAGED_CODE();
_SEH2_TRY
{
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
if (DeviceObject != FFSGlobal->DeviceObject)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
_SEH2_LEAVE;
}
ExAcquireResourceExclusiveLite(
&FFSGlobal->Resource,
TRUE);
GlobalDataResourceAcquired = TRUE;
if (FlagOn(FFSGlobal->Flags, FFS_UNLOAD_PENDING))
{
FFSPrint((DBG_ERROR, "FFSPrepareUnload: Already ready to unload.\n"));
Status = STATUS_ACCESS_DENIED;
_SEH2_LEAVE;
}
{
PFFS_VCB Vcb;
PLIST_ENTRY ListEntry;
ListEntry = FFSGlobal->VcbList.Flink;
while (ListEntry != &(FFSGlobal->VcbList))
{
Vcb = CONTAINING_RECORD(ListEntry, FFS_VCB, Next);
ListEntry = ListEntry->Flink;
if (Vcb && (!Vcb->ReferenceCount) &&
IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
{
FFSRemoveVcb(Vcb);
FFSClearVpbFlag(Vcb->Vpb, VPB_MOUNTED);
FFSFreeVcb(Vcb);
}
}
}
if (!IsListEmpty(&(FFSGlobal->VcbList)))
{
FFSPrint((DBG_ERROR, "FFSPrepareUnload: Mounted volumes exists.\n"));
Status = STATUS_ACCESS_DENIED;
_SEH2_LEAVE;
}
IoUnregisterFileSystem(FFSGlobal->DeviceObject);
#ifdef _MSC_VER
#pragma prefast( suppress: 28175, "allowed to unload" )
#endif
FFSGlobal->DriverObject->DriverUnload = DriverUnload;
SetFlag(FFSGlobal->Flags, FFS_UNLOAD_PENDING);
FFSPrint((DBG_INFO, "FFSPrepareToUnload: Driver is ready to unload.\n"));
Status = STATUS_SUCCESS;
}
_SEH2_FINALLY
{
if (GlobalDataResourceAcquired)
{
ExReleaseResourceForThreadLite(
&FFSGlobal->Resource,
ExGetCurrentResourceThread());
}
if (!IrpContext->ExceptionInProgress)
{
FFSCompleteIrpContext(IrpContext, Status);
}
} _SEH2_END;
return Status;
}
#endif
__drv_mustHoldCriticalRegion
NTSTATUS
FFSDeviceControl(
IN PFFS_IRP_CONTEXT IrpContext)
{
PIRP Irp;
PIO_STACK_LOCATION IoStackLocation;
ULONG IoControlCode;
NTSTATUS Status;
PAGED_CODE();
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
Irp = IrpContext->Irp;
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
IoControlCode =
IoStackLocation->Parameters.DeviceIoControl.IoControlCode;
switch (IoControlCode)
{
#if FFS_UNLOAD
case IOCTL_PREPARE_TO_UNLOAD:
Status = FFSPrepareToUnload(IrpContext);
break;
#endif
case IOCTL_SELECT_BSD_PARTITION:
Status = FFSSelectBSDPartition(IrpContext);
break;
default:
Status = FFSDeviceControlNormal(IrpContext);
}
return Status;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,252 @@
/*
* FFS File System Driver for Windows
*
* dipatch.c
*
* 2004.5.6 ~
*
* Lee Jae-Hong, http://www.pyrasis.com
*
* See License.txt
*
*/
#include "ntifs.h"
#include "ffsdrv.h"
/* Globals */
extern PFFS_GLOBAL FFSGlobal;
/* Definitions */
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSQueueRequest)
#pragma alloc_text(PAGE, FFSDeQueueRequest)
#pragma alloc_text(PAGE, FFSDispatchRequest)
#pragma alloc_text(PAGE, FFSBuildRequest)
#endif
NTSTATUS
FFSQueueRequest(
IN PFFS_IRP_CONTEXT IrpContext)
{
PAGED_CODE();
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
// IsSynchronous means we can block (so we don't requeue it)
IrpContext->IsSynchronous = TRUE;
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
IoMarkIrpPending(IrpContext->Irp);
ExInitializeWorkItem(
&IrpContext->WorkQueueItem,
FFSDeQueueRequest,
IrpContext);
ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
return STATUS_PENDING;
}
VOID NTAPI
FFSDeQueueRequest(
IN PVOID Context)
{
PFFS_IRP_CONTEXT IrpContext;
PAGED_CODE();
IrpContext = (PFFS_IRP_CONTEXT) Context;
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
_SEH2_TRY
{
_SEH2_TRY
{
FsRtlEnterFileSystem();
if (!IrpContext->IsTopLevel)
{
IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP);
}
FFSDispatchRequest(IrpContext);
}
_SEH2_EXCEPT (FFSExceptionFilter(IrpContext, _SEH2_GetExceptionInformation()))
{
FFSExceptionHandler(IrpContext);
} _SEH2_END;
}
_SEH2_FINALLY
{
IoSetTopLevelIrp(NULL);
FsRtlExitFileSystem();
} _SEH2_END;
}
NTSTATUS
FFSDispatchRequest(
IN PFFS_IRP_CONTEXT IrpContext)
{
PAGED_CODE();
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
switch (IrpContext->MajorFunction)
{
case IRP_MJ_CREATE:
return FFSCreate(IrpContext);
case IRP_MJ_CLOSE:
return FFSClose(IrpContext);
case IRP_MJ_READ:
return FFSRead(IrpContext);
#if !FFS_READ_ONLY
case IRP_MJ_WRITE:
return FFSWrite(IrpContext);
#endif // !FFS_READ_ONLY
case IRP_MJ_FLUSH_BUFFERS:
return FFSFlush(IrpContext);
case IRP_MJ_QUERY_INFORMATION:
return FFSQueryInformation(IrpContext);
case IRP_MJ_SET_INFORMATION:
return FFSSetInformation(IrpContext);
case IRP_MJ_QUERY_VOLUME_INFORMATION:
return FFSQueryVolumeInformation(IrpContext);
#if !FFS_READ_ONLY
case IRP_MJ_SET_VOLUME_INFORMATION:
return FFSSetVolumeInformation(IrpContext);
#endif // !FFS_READ_ONLY
case IRP_MJ_DIRECTORY_CONTROL:
return FFSDirectoryControl(IrpContext);
case IRP_MJ_FILE_SYSTEM_CONTROL:
return FFSFileSystemControl(IrpContext);
case IRP_MJ_DEVICE_CONTROL:
return FFSDeviceControl(IrpContext);
case IRP_MJ_LOCK_CONTROL:
return FFSLockControl(IrpContext);
case IRP_MJ_CLEANUP:
return FFSCleanup(IrpContext);
case IRP_MJ_SHUTDOWN:
return FFSShutDown(IrpContext);
#if (_WIN32_WINNT >= 0x0500)
case IRP_MJ_PNP:
return FFSPnp(IrpContext);
#endif //(_WIN32_WINNT >= 0x0500)
default:
FFSPrint((DBG_ERROR, "FFSDispatchRequest: Unexpected major function: %xh\n",
IrpContext->MajorFunction));
FFSCompleteIrpContext(IrpContext, STATUS_DRIVER_INTERNAL_ERROR);
return STATUS_DRIVER_INTERNAL_ERROR;
}
}
NTSTATUS NTAPI
FFSBuildRequest(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
BOOLEAN AtIrqlPassiveLevel = FALSE;
BOOLEAN IsTopLevelIrp = FALSE;
PFFS_IRP_CONTEXT IrpContext = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PAGED_CODE();
_SEH2_TRY
{
_SEH2_TRY
{
#if DBG
FFSDbgPrintCall(DeviceObject, Irp);
#endif
AtIrqlPassiveLevel = (KeGetCurrentIrql() == PASSIVE_LEVEL);
if (AtIrqlPassiveLevel)
{
FsRtlEnterFileSystem();
}
if (!IoGetTopLevelIrp())
{
IsTopLevelIrp = TRUE;
IoSetTopLevelIrp(Irp);
}
IrpContext = FFSAllocateIrpContext(DeviceObject, Irp);
if (!IrpContext)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Status = Status;
FFSCompleteRequest(Irp, TRUE, IO_NO_INCREMENT);
}
else
{
if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
!AtIrqlPassiveLevel)
{
FFSBreakPoint();
}
Status = FFSDispatchRequest(IrpContext);
}
}
_SEH2_EXCEPT (FFSExceptionFilter(IrpContext, _SEH2_GetExceptionInformation()))
{
Status = FFSExceptionHandler(IrpContext);
} _SEH2_END;
}
_SEH2_FINALLY
{
if (IsTopLevelIrp)
{
IoSetTopLevelIrp(NULL);
}
if (AtIrqlPassiveLevel)
{
FsRtlExitFileSystem();
}
} _SEH2_END;
return Status;
}

View file

@ -0,0 +1,210 @@
/*
* FFS File System Driver for Windows
*
* except.c
*
* 2004.5.6 ~
*
* Lee Jae-Hong, http://www.pyrasis.com
*
* See License.txt
*
*/
#include "ntifs.h"
#include "ffsdrv.h"
/* Globals */
extern PFFS_GLOBAL FFSGlobal;
/* Definitions */
#ifdef ALLOC_PRAGMA
//#pragma alloc_text(PAGE, FFSExceptionFilter)
//#pragma alloc_text(PAGE, FFSExceptionHandler)
#endif
NTSTATUS
FFSExceptionFilter(
IN PFFS_IRP_CONTEXT IrpContext,
IN PEXCEPTION_POINTERS ExceptionPointer)
{
NTSTATUS Status, ExceptionCode;
PEXCEPTION_RECORD ExceptRecord;
ExceptRecord = ExceptionPointer->ExceptionRecord;
ExceptionCode = ExceptRecord->ExceptionCode;
FFSBreakPoint();
//
// Check IrpContext is valid or not
//
if (IrpContext)
{
if ((IrpContext->Identifier.Type != FFSICX) ||
(IrpContext->Identifier.Size != sizeof(FFS_IRP_CONTEXT)))
{
IrpContext = NULL;
}
}
else
{
if (FsRtlIsNtstatusExpected(ExceptionCode))
{
return EXCEPTION_EXECUTE_HANDLER;
}
else
{
FFSBugCheck(FFS_BUGCHK_EXCEPT, (ULONG_PTR)ExceptRecord,
(ULONG_PTR)ExceptionPointer->ContextRecord,
(ULONG_PTR)ExceptRecord->ExceptionAddress);
}
}
//
// For the purposes of processing this exception, let's mark this
// request as being able to wait, and neither write through nor on
// removable media if we aren't posting it.
//
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
if (FsRtlIsNtstatusExpected(ExceptionCode))
{
//
// If the exception is expected execute our handler
//
FFSPrint((DBG_ERROR, "FFSExceptionFilter: Catching exception %xh\n",
ExceptionCode));
Status = EXCEPTION_EXECUTE_HANDLER;
if (IrpContext)
{
IrpContext->ExceptionInProgress = TRUE;
IrpContext->ExceptionCode = ExceptionCode;
}
}
else
{
//
// Continue search for an higher level exception handler
//
FFSPrint((DBG_ERROR, "FFSExceptionFilter: Passing on exception %#x\n",
ExceptionCode));
Status = EXCEPTION_CONTINUE_SEARCH;
if (IrpContext)
{
FFSFreeIrpContext(IrpContext);
}
}
return Status;
}
NTSTATUS
FFSExceptionHandler(
IN PFFS_IRP_CONTEXT IrpContext)
{
NTSTATUS Status;
FFSBreakPoint();
if (IrpContext)
{
if ((IrpContext->Identifier.Type != FFSICX) ||
(IrpContext->Identifier.Size != sizeof(FFS_IRP_CONTEXT)))
{
FFSBreakPoint();
return STATUS_UNSUCCESSFUL;
}
Status = IrpContext->ExceptionCode;
if (IrpContext->Irp)
{
//
// Check if this error is a result of user actions
//
PIRP Irp = IrpContext->Irp;
if (IoIsErrorUserInduced(Status))
{
//
// Now we will generate a pop-up to user
//
PDEVICE_OBJECT RealDevice;
PVPB Vpb = NULL;
PETHREAD Thread;
if (IoGetCurrentIrpStackLocation(Irp)->FileObject != NULL)
{
Vpb = IoGetCurrentIrpStackLocation(Irp)->FileObject->Vpb;
}
//
// Get the initial thread
//
Thread = Irp->Tail.Overlay.Thread;
RealDevice = IoGetDeviceToVerify(Thread);
if (RealDevice == NULL)
{
//
// Get current thread
//
Thread = PsGetCurrentThread();
RealDevice = IoGetDeviceToVerify(Thread);
ASSERT(RealDevice != NULL);
}
if (RealDevice != NULL)
{
//
// Now we pop-up the error dialog ...
//
IoMarkIrpPending(Irp);
IoRaiseHardError(Irp, Vpb, RealDevice);
IoSetDeviceToVerify(Thread, NULL);
Status = STATUS_PENDING;
goto errorout;
}
}
IrpContext->Irp->IoStatus.Status = Status;
FFSCompleteRequest(IrpContext->Irp, FALSE, IO_NO_INCREMENT);
}
errorout:
FFSFreeIrpContext(IrpContext);
}
else
{
Status = STATUS_INSUFFICIENT_RESOURCES;
}
return Status;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,112 @@
//Microsoft Developer Studio generated resource script.
//
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
#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
#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,5,3,0
PRODUCTVERSION 0,5,3,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x9L
#else
FILEFLAGS 0x8L
#endif
FILEOS 0x40004L
FILETYPE 0x3L
FILESUBTYPE 0x8L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "000004b0"
BEGIN
VALUE "Comments", "\0"
VALUE "CompanyName", "PYRASIS.COM\0"
VALUE "FileDescription", "FFS File System Driver for Windows\0"
VALUE "FileVersion", "0, 5, 3, 0\0"
VALUE "InternalName", "ffs\0"
VALUE "LegalCopyright", "2004-2015 (C) Lee Jae-Hong. All rights reserved.\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "ffs.sys\0"
VALUE "PrivateBuild", "2015.10.2\0"
VALUE "ProductName", "FFS Driver\0"
VALUE "ProductVersion", "0, 5, 3, 0\0"
VALUE "SpecialBuild", "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0, 1200
END
END
#endif // !_MAC
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"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"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,312 @@
/*
* FFS File System Driver for Windows
*
* flush.c
*
* 2004.5.6 ~
*
* Lee Jae-Hong, http://www.pyrasis.com
*
* See License.txt
*
*/
#include "ntifs.h"
#include "ffsdrv.h"
/* Globals */
extern PFFS_GLOBAL FFSGlobal;
/* Definitions */
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSFlushFile)
#pragma alloc_text(PAGE, FFSFlushFiles)
#pragma alloc_text(PAGE, FFSFlushVolume)
#pragma alloc_text(PAGE, FFSFlush)
#endif
#ifdef _PREFAST_
IO_COMPLETION_ROUTINE FFSFlushCompletionRoutine;
#endif // _PREFAST_
NTSTATUS NTAPI
FFSFlushCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt)
{
if (Irp->PendingReturned)
IoMarkIrpPending(Irp);
if (Irp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST)
Irp->IoStatus.Status = STATUS_SUCCESS;
return STATUS_SUCCESS;
}
__drv_mustHoldCriticalRegion
NTSTATUS
FFSFlushFiles(
IN PFFS_VCB Vcb,
BOOLEAN bShutDown)
{
IO_STATUS_BLOCK IoStatus;
PFFS_FCB Fcb;
PLIST_ENTRY ListEntry;
PAGED_CODE();
if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
{
return STATUS_SUCCESS;
}
FFSPrint((DBG_INFO, "Flushing Files ...\n"));
// Flush all Fcbs in Vcb list queue.
{
for (ListEntry = Vcb->FcbList.Flink;
ListEntry != &Vcb->FcbList;
ListEntry = ListEntry->Flink)
{
Fcb = CONTAINING_RECORD(ListEntry, FFS_FCB, Next);
if (ExAcquireResourceExclusiveLite(
&Fcb->MainResource,
TRUE))
{
IoStatus.Status = FFSFlushFile(Fcb);
#if 0
/*
if (bShutDown)
IoStatus.Status = FFSPurgeFile(Fcb, TRUE);
else
IoStatus.Status = FFSFlushFile(Fcb);
*/
#endif
ExReleaseResourceForThreadLite(
&Fcb->MainResource,
ExGetCurrentResourceThread());
}
}
}
return IoStatus.Status;
}
__drv_mustHoldCriticalRegion
NTSTATUS
FFSFlushVolume(
IN PFFS_VCB Vcb,
BOOLEAN bShutDown)
{
IO_STATUS_BLOCK IoStatus;
PAGED_CODE();
if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
{
return STATUS_SUCCESS;
}
FFSPrint((DBG_INFO, "FFSFlushVolume: Flushing Vcb ...\n"));
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
ExReleaseResourceLite(&Vcb->PagingIoResource);
CcFlushCache(&(Vcb->SectionObject), NULL, 0, &IoStatus);
return IoStatus.Status;
}
NTSTATUS
FFSFlushFile(
IN PFFS_FCB Fcb)
{
IO_STATUS_BLOCK IoStatus;
PAGED_CODE();
ASSERT(Fcb != NULL);
ASSERT((Fcb->Identifier.Type == FFSFCB) &&
(Fcb->Identifier.Size == sizeof(FFS_FCB)));
if (IsDirectory(Fcb))
return STATUS_SUCCESS;
FFSPrint((DBG_INFO, "FFSFlushFile: Flushing File Inode=%xh %S ...\n",
Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer));
/*
{
ULONG ResShCnt, ResExCnt;
ResShCnt = ExIsResourceAcquiredSharedLite(&Fcb->PagingIoResource);
ResExCnt = ExIsResourceAcquiredExclusiveLite(&Fcb->PagingIoResource);
FFSPrint((DBG_INFO, "FFSFlushFile: PagingIoRes: %xh:%xh\n", ResShCnt, ResExCnt));
}
*/
CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus);
ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
return IoStatus.Status;
}
__drv_mustHoldCriticalRegion
NTSTATUS
FFSFlush(
IN PFFS_IRP_CONTEXT IrpContext)
{
NTSTATUS Status;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
PFFS_VCB Vcb = 0;
PFFS_FCBVCB FcbOrVcb = 0;
PFILE_OBJECT FileObject;
PDEVICE_OBJECT DeviceObject;
BOOLEAN MainResourceAcquired = FALSE;
PAGED_CODE();
_SEH2_TRY
{
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
//
// This request is not allowed on the main device object
//
if (DeviceObject == FFSGlobal->DeviceObject)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
_SEH2_LEAVE;
}
Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == FFSVCB) &&
(Vcb->Identifier.Size == sizeof(FFS_VCB)));
ASSERT(IsMounted(Vcb));
if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
{
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
Irp = IrpContext->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
FileObject = IrpContext->FileObject;
FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext;
ASSERT(FcbOrVcb != NULL);
#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
if (!ExAcquireResourceExclusiveLite(
&FcbOrVcb->MainResource,
IrpContext->IsSynchronous))
{
Status = STATUS_PENDING;
_SEH2_LEAVE;
}
MainResourceAcquired = TRUE;
if (FcbOrVcb->Identifier.Type == FFSVCB)
{
Status = FFSFlushFiles((PFFS_VCB)(FcbOrVcb), FALSE);
if (NT_SUCCESS(Status))
{
_SEH2_LEAVE;
}
Status = FFSFlushVolume((PFFS_VCB)(FcbOrVcb), FALSE);
if (NT_SUCCESS(Status) && IsFlagOn(Vcb->StreamObj->Flags, FO_FILE_MODIFIED))
{
ClearFlag(Vcb->StreamObj->Flags, FO_FILE_MODIFIED);
}
}
else if (FcbOrVcb->Identifier.Type == FFSFCB)
{
Status = FFSFlushFile((PFFS_FCB)(FcbOrVcb));
if (NT_SUCCESS(Status) && IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED))
{
ClearFlag(FileObject->Flags, FO_FILE_MODIFIED);
}
}
}
_SEH2_FINALLY
{
if (MainResourceAcquired)
{
ExReleaseResourceForThreadLite(
&FcbOrVcb->MainResource,
ExGetCurrentResourceThread());
}
if (!IrpContext->ExceptionInProgress)
{
if (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
{
// Call the disk driver to flush the physial media.
NTSTATUS DriverStatus;
PIO_STACK_LOCATION NextIrpSp;
IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);
NextIrpSp = IoGetNextIrpStackLocation(IrpContext->Irp);
*NextIrpSp = *IrpSp;
IoSetCompletionRoutine(IrpContext->Irp,
FFSFlushCompletionRoutine,
NULL,
TRUE,
TRUE,
TRUE);
DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, IrpContext->Irp);
Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ?
Status : DriverStatus;
IrpContext->Irp = NULL;
}
FFSCompleteIrpContext(IrpContext, Status);
}
} _SEH2_END;
return Status;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,453 @@
/*
* FFS File System Driver for Windows
*
* init.c
*
* 2004.5.6 ~
*
* Lee Jae-Hong, http://www.pyrasis.com
*
* See License.txt
*
*/
#include <ntifs.h>
#ifndef __REACTOS__
#include <wdmsec.h>
#endif
#include "ffsdrv.h"
/* Globals */
PFFS_GLOBAL FFSGlobal = NULL;
/* Definitions */
NTSTATUS NTAPI
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, FFSQueryParameters)
#pragma alloc_text(INIT, DriverEntry)
#if FFS_UNLOAD
#pragma alloc_text(PAGE, DriverUnload)
#endif
#endif
#if FFS_UNLOAD
/*
* FUNCTION: Called by the system to unload the driver
* ARGUMENTS:
* DriverObject = object describing this driver
* RETURNS: None
*/
VOID NTAPI
DriverUnload(
IN PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING DosDeviceName;
PAGED_CODE();
FFSPrint((DBG_FUNC, "ffsdrv: Unloading routine.\n"));
RtlInitUnicodeString(&DosDeviceName, DOS_DEVICE_NAME);
IoDeleteSymbolicLink(&DosDeviceName);
ExDeleteResourceLite(&FFSGlobal->LAResource);
ExDeleteResourceLite(&FFSGlobal->CountResource);
ExDeleteResourceLite(&FFSGlobal->Resource);
ExDeletePagedLookasideList(&(FFSGlobal->FFSMcbLookasideList));
ExDeleteNPagedLookasideList(&(FFSGlobal->FFSCcbLookasideList));
ExDeleteNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList));
ExDeleteNPagedLookasideList(&(FFSGlobal->FFSIrpContextLookasideList));
IoDeleteDevice(FFSGlobal->DeviceObject);
}
#endif
BOOLEAN
FFSQueryParameters(
IN PUNICODE_STRING RegistryPath)
{
NTSTATUS Status;
UNICODE_STRING ParameterPath;
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
ULONG WritingSupport;
ULONG CheckingBitmap;
ULONG PartitionNumber;
ParameterPath.Length = 0;
ParameterPath.MaximumLength =
RegistryPath->Length + sizeof(PARAMETERS_KEY) + sizeof(WCHAR);
ParameterPath.Buffer =
(PWSTR) ExAllocatePoolWithTag(PagedPool, ParameterPath.MaximumLength, FFS_POOL_TAG);
if (!ParameterPath.Buffer)
{
return FALSE;
}
WritingSupport = 0;
CheckingBitmap = 0;
PartitionNumber = 0;
RtlCopyUnicodeString(&ParameterPath, RegistryPath);
RtlAppendUnicodeToString(&ParameterPath, PARAMETERS_KEY);
RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[0].Name = WRITING_SUPPORT;
QueryTable[0].EntryContext = &WritingSupport;
Status = RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
ParameterPath.Buffer,
&QueryTable[0],
NULL,
NULL);
FFSPrint((DBG_USER, "FFSQueryParameters: WritingSupport=%xh\n", WritingSupport));
RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[0].Name = CHECKING_BITMAP;
QueryTable[0].EntryContext = &CheckingBitmap;
Status = RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
ParameterPath.Buffer,
&QueryTable[0],
NULL,
NULL);
FFSPrint((DBG_USER, "FFSQueryParameters: CheckingBitmap=%xh\n", CheckingBitmap));
RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[0].Name = PARTITION_NUMBER;
QueryTable[0].EntryContext = &PartitionNumber;
Status = RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
ParameterPath.Buffer,
&QueryTable[0],
NULL,
NULL);
FFSPrint((DBG_USER, "FFSQueryParameters: PartitionNumber=%xh\n", PartitionNumber));
{
if (WritingSupport)
{
SetFlag(FFSGlobal->Flags, FFS_SUPPORT_WRITING);
}
else
{
ClearFlag(FFSGlobal->Flags, FFS_SUPPORT_WRITING);
}
if (CheckingBitmap)
{
SetFlag(FFSGlobal->Flags, FFS_CHECKING_BITMAP);
}
else
{
ClearFlag(FFSGlobal->Flags, FFS_CHECKING_BITMAP);
}
if (PartitionNumber)
{
FFSGlobal->PartitionNumber = PartitionNumber;
}
}
ExFreePool(ParameterPath.Buffer);
return TRUE;
}
#define NLS_OEM_LEAD_BYTE_INFO (*NlsOemLeadByteInfo)
#ifndef __REACTOS__
#define FsRtlIsLeadDbcsCharacter(DBCS_CHAR) ( \
(BOOLEAN)((UCHAR)(DBCS_CHAR) < 0x80 ? FALSE : \
(NLS_MB_CODE_PAGE_TAG && \
(NLS_OEM_LEAD_BYTE_INFO[(UCHAR)(DBCS_CHAR)] != 0))) \
)
#endif
/*
* NAME: DriverEntry
* FUNCTION: Called by the system to initalize the driver
*
* ARGUMENTS:
* DriverObject = object describing this driver
* RegistryPath = path to our configuration entries
* RETURNS: Success or failure
*/
NTSTATUS NTAPI
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
PDEVICE_OBJECT DeviceObject;
PFAST_IO_DISPATCH FastIoDispatch;
PCACHE_MANAGER_CALLBACKS CacheManagerCallbacks;
PFFS_EXT DeviceExt;
UNICODE_STRING DeviceName;
#ifndef __REACTOS__
UNICODE_STRING Sddl;
#endif
NTSTATUS Status;
#if FFS_UNLOAD
UNICODE_STRING DosDeviceName;
#endif
DbgPrint(
"ffsdrv --"
" Version "
FFSDRV_VERSION
#if FFS_READ_ONLY
" (ReadOnly)"
#endif // FFS_READ_ONLY
#if DBG
" Checked"
#else
" Free"
#endif
" - Built at "
__DATE__" "
__TIME__".\n");
FFSPrint((DBG_FUNC, "FFS DriverEntry ...\n"));
RtlInitUnicodeString(&DeviceName, DEVICE_NAME);
#ifndef __REACTOS__
RtlInitUnicodeString(&Sddl, L"D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;BU)");
Status = IoCreateDeviceSecure(
DriverObject,
sizeof(FFS_EXT),
&DeviceName,
FILE_DEVICE_DISK_FILE_SYSTEM,
0,
FALSE,
&Sddl,
NULL,
&DeviceObject);
#else
Status = IoCreateDevice(
DriverObject,
sizeof(FFS_EXT),
&DeviceName,
FILE_DEVICE_DISK_FILE_SYSTEM,
0,
FALSE,
&DeviceObject);
#endif
if (!NT_SUCCESS(Status))
{
FFSPrint((DBG_ERROR, "IoCreateDevice fs object error.\n"));
return Status;
}
DeviceExt = (PFFS_EXT)DeviceObject->DeviceExtension;
RtlZeroMemory(DeviceExt, sizeof(FFS_EXT));
FFSGlobal = &(DeviceExt->FFSGlobal);
FFSGlobal->Identifier.Type = FFSFGD;
FFSGlobal->Identifier.Size = sizeof(FFS_GLOBAL);
FFSGlobal->DeviceObject = DeviceObject;
FFSGlobal->DriverObject = DriverObject;
FFSGlobal->PartitionNumber = 0;
FFSQueryParameters(RegistryPath);
DriverObject->MajorFunction[IRP_MJ_CREATE] = FFSBuildRequest;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FFSBuildRequest;
DriverObject->MajorFunction[IRP_MJ_READ] = FFSBuildRequest;
#if !FFS_READ_ONLY
DriverObject->MajorFunction[IRP_MJ_WRITE] = FFSBuildRequest;
#endif // !FFS_READ_ONLY
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = FFSBuildRequest;
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = FFSBuildRequest;
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = FFSBuildRequest;
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = FFSBuildRequest;
DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = FFSBuildRequest;
#if !FFS_READ_ONLY
DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = FFSBuildRequest;
#endif // !FFS_READ_ONLY
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = FFSBuildRequest;
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FFSBuildRequest;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FFSBuildRequest;
DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = FFSBuildRequest;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FFSBuildRequest;
#if (_WIN32_WINNT >= 0x0500)
DriverObject->MajorFunction[IRP_MJ_PNP] = FFSBuildRequest;
#endif //(_WIN32_WINNT >= 0x0500)
#if FFS_UNLOAD
#ifdef _MSC_VER
#pragma prefast( suppress: 28175, "allowed to unload" )
#endif
DriverObject->DriverUnload = DriverUnload;
#else
#ifdef _MSC_VER
#pragma prefast( suppress: 28175, "allowed to unload" )
#endif
DriverObject->DriverUnload = NULL;
#endif
//
// Initialize the fast I/O entry points
//
FastIoDispatch = &(FFSGlobal->FastIoDispatch);
FastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
FastIoDispatch->FastIoCheckIfPossible = FFSFastIoCheckIfPossible;
#if DBG
FastIoDispatch->FastIoRead = FFSFastIoRead;
#if !FFS_READ_ONLY
FastIoDispatch->FastIoWrite = FFSFastIoWrite;
#endif // !FFS_READ_ONLY
#else
#ifdef _MSC_VER
#pragma prefast( suppress: 28155, "allowed in file system drivers" )
#endif
FastIoDispatch->FastIoRead = FsRtlCopyRead;
#if !FFS_READ_ONLY
#ifdef _MSC_VER
#pragma prefast( suppress: 28155, "allowed in file system drivers" )
#endif
FastIoDispatch->FastIoWrite = FsRtlCopyWrite;
#endif // !FFS_READ_ONLY
#endif
FastIoDispatch->FastIoQueryBasicInfo = FFSFastIoQueryBasicInfo;
FastIoDispatch->FastIoQueryStandardInfo = FFSFastIoQueryStandardInfo;
FastIoDispatch->FastIoLock = FFSFastIoLock;
FastIoDispatch->FastIoUnlockSingle = FFSFastIoUnlockSingle;
FastIoDispatch->FastIoUnlockAll = FFSFastIoUnlockAll;
FastIoDispatch->FastIoUnlockAllByKey = FFSFastIoUnlockAllByKey;
FastIoDispatch->FastIoQueryNetworkOpenInfo = FFSFastIoQueryNetworkOpenInfo;
#ifdef _MSC_VER
#pragma prefast( suppress: 28175, "allowed in file system drivers" )
#endif
DriverObject->FastIoDispatch = FastIoDispatch;
switch (MmQuerySystemSize())
{
case MmSmallSystem:
FFSGlobal->MaxDepth = 16;
break;
case MmMediumSystem:
FFSGlobal->MaxDepth = 64;
break;
case MmLargeSystem:
FFSGlobal->MaxDepth = 256;
break;
}
//
// Initialize the Cache Manager callbacks
//
CacheManagerCallbacks = &(FFSGlobal->CacheManagerCallbacks);
CacheManagerCallbacks->AcquireForLazyWrite = FFSAcquireForLazyWrite;
CacheManagerCallbacks->ReleaseFromLazyWrite = FFSReleaseFromLazyWrite;
CacheManagerCallbacks->AcquireForReadAhead = FFSAcquireForReadAhead;
CacheManagerCallbacks->ReleaseFromReadAhead = FFSReleaseFromReadAhead;
FFSGlobal->CacheManagerNoOpCallbacks.AcquireForLazyWrite = FFSNoOpAcquire;
FFSGlobal->CacheManagerNoOpCallbacks.ReleaseFromLazyWrite = FFSNoOpRelease;
FFSGlobal->CacheManagerNoOpCallbacks.AcquireForReadAhead = FFSNoOpAcquire;
FFSGlobal->CacheManagerNoOpCallbacks.ReleaseFromReadAhead = FFSNoOpRelease;
//
// Initialize the global data
//
InitializeListHead(&(FFSGlobal->VcbList));
ExInitializeResourceLite(&(FFSGlobal->Resource));
ExInitializeResourceLite(&(FFSGlobal->CountResource));
ExInitializeResourceLite(&(FFSGlobal->LAResource));
ExInitializeNPagedLookasideList(&(FFSGlobal->FFSIrpContextLookasideList),
NULL,
NULL,
0,
sizeof(FFS_IRP_CONTEXT),
'SFF',
0);
ExInitializeNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList),
NULL,
NULL,
0,
sizeof(FFS_FCB),
'SFF',
0);
ExInitializeNPagedLookasideList(&(FFSGlobal->FFSCcbLookasideList),
NULL,
NULL,
0,
sizeof(FFS_CCB),
'SFF',
0);
ExInitializePagedLookasideList(&(FFSGlobal->FFSMcbLookasideList),
NULL,
NULL,
0,
sizeof(FFS_MCB),
'SFF',
0);
#if FFS_UNLOAD
RtlInitUnicodeString(&DosDeviceName, DOS_DEVICE_NAME);
IoCreateSymbolicLink(&DosDeviceName, &DeviceName);
#endif
#if DBG
ProcessNameOffset = FFSGetProcessNameOffset();
#endif
IoRegisterFileSystem(DeviceObject);
return Status;
}

View file

@ -0,0 +1,137 @@
/*
* FFS File System Driver for Windows
*
* lock.c
*
* 2004.5.6 ~
*
* Lee Jae-Hong, http://www.pyrasis.com
*
* See License.txt
*
*/
#include "ntifs.h"
#include "ffsdrv.h"
/* Globals */
extern PFFS_GLOBAL FFSGlobal;
/* Definitions */
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSLockControl)
#endif
__drv_mustHoldCriticalRegion
NTSTATUS
FFSLockControl(
IN PFFS_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT DeviceObject;
BOOLEAN CompleteRequest;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PFILE_OBJECT FileObject;
PFFS_FCB Fcb;
PIRP Irp;
PAGED_CODE();
_SEH2_TRY
{
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
if (DeviceObject == FFSGlobal->DeviceObject)
{
CompleteRequest = TRUE;
Status = STATUS_INVALID_DEVICE_REQUEST;
_SEH2_LEAVE;
}
FileObject = IrpContext->FileObject;
Fcb = (PFFS_FCB)FileObject->FsContext;
ASSERT(Fcb != NULL);
if (Fcb->Identifier.Type == FFSVCB)
{
CompleteRequest = TRUE;
Status = STATUS_INVALID_PARAMETER;
_SEH2_LEAVE;
}
ASSERT((Fcb->Identifier.Type == FFSFCB) &&
(Fcb->Identifier.Size == sizeof(FFS_FCB)));
if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
{
CompleteRequest = TRUE;
Status = STATUS_INVALID_PARAMETER;
_SEH2_LEAVE;
}
Irp = IrpContext->Irp;
//
// While the file has any byte range locks we set IsFastIoPossible to
// FastIoIsQuestionable so that the FastIoCheckIfPossible function is
// called to check the locks for any fast I/O read/write operation.
//
if (Fcb->Header.IsFastIoPossible != FastIoIsQuestionable)
{
FFSPrint((DBG_INFO,
"FFSLockControl: %-16.16s %-31s %s\n",
FFSGetCurrentProcessName(),
"FastIoIsQuestionable",
Fcb->AnsiFileName.Buffer));
Fcb->Header.IsFastIoPossible = FastIoIsQuestionable;
}
//
// FsRtlProcessFileLock acquires FileObject->FsContext->Resource while
// modifying the file locks and calls IoCompleteRequest when it's done.
//
CompleteRequest = FALSE;
Status = FsRtlProcessFileLock(
&Fcb->FileLockAnchor,
Irp,
NULL);
if (!NT_SUCCESS(Status))
{
FFSPrint((DBG_ERROR,
"FFSLockControl: %-16.16s %-31s *** Status: %s (%#x) ***\n",
FFSGetCurrentProcessName(),
"IRP_MJ_LOCK_CONTROL",
FFSNtStatusToString(Status),
Status));
}
}
_SEH2_FINALLY
{
if (!IrpContext->ExceptionInProgress)
{
if (!CompleteRequest)
{
IrpContext->Irp = NULL;
}
FFSCompleteIrpContext(IrpContext, Status);
}
} _SEH2_END;
return Status;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,128 @@
/*
* FFS File System Driver for Windows
*
* misc.c
*
* 2004.5.6 ~
*
* Lee Jae-Hong, http://www.pyrasis.com
*
* See License.txt
*
*/
#include "ntifs.h"
#include "ffsdrv.h"
/* Globals */
extern PFFS_GLOBAL FFSGlobal;
/* Definitions */
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSLog2)
#pragma alloc_text(PAGE, FFSSysTime)
#pragma alloc_text(PAGE, FFSInodeTime)
#pragma alloc_text(PAGE, FFSOEMToUnicode)
#pragma alloc_text(PAGE, FFSUnicodeToOEM)
#endif
ULONG
FFSLog2(
ULONG Value)
{
ULONG Order = 0;
PAGED_CODE();
ASSERT(Value > 0);
while (Value)
{
Order++;
Value >>= 1;
}
return (Order - 1);
}
LARGE_INTEGER
FFSSysTime(
IN ULONG i_time)
{
LARGE_INTEGER SysTime;
PAGED_CODE();
RtlSecondsSince1970ToTime(i_time, &SysTime);
return SysTime;
}
ULONG
FFSInodeTime(
IN LARGE_INTEGER SysTime)
{
ULONG FFSTime;
PAGED_CODE();
RtlTimeToSecondsSince1970(&SysTime, &FFSTime);
return FFSTime;
}
NTSTATUS
FFSOEMToUnicode(
IN OUT PUNICODE_STRING Unicode,
IN POEM_STRING Oem)
{
NTSTATUS Status;
PAGED_CODE();
Status = RtlOemStringToUnicodeString(
Unicode,
Oem,
FALSE);
if (!NT_SUCCESS(Status))
{
FFSBreakPoint();
goto errorout;
}
errorout:
return Status;
}
NTSTATUS
FFSUnicodeToOEM(
IN OUT POEM_STRING Oem,
IN PUNICODE_STRING Unicode)
{
NTSTATUS Status;
PAGED_CODE();
Status = RtlUnicodeStringToOemString(
Oem,
Unicode,
FALSE);
if (!NT_SUCCESS(Status))
{
FFSBreakPoint();
goto errorout;
}
errorout:
return Status;
}

View file

@ -0,0 +1,463 @@
/*
* FFS File System Driver for Windows
*
* misc.c
*
* 2004.5.6 ~
*
* Lee Jae-Hong, http://www.pyrasis.com
*
* See License.txt
*
*/
#include "ntifs.h"
#include "ffsdrv.h"
extern PFFS_GLOBAL FFSGlobal;
#if (_WIN32_WINNT >= 0x0500)
/* Globals */
extern PFFS_GLOBAL FFSGlobal;
/* Definitions */
#define DBG_PNP DBG_USER
#ifdef _PREFAST_
IO_COMPLETION_ROUTINE FFSPnpCompletionRoutine;
#endif // _PREFAST_
NTSTATUS NTAPI
FFSPnpCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSPnp)
#pragma alloc_text(PAGE, FFSPnpQueryRemove)
#pragma alloc_text(PAGE, FFSPnpRemove)
#pragma alloc_text(PAGE, FFSPnpCancelRemove)
#pragma alloc_text(PAGE, FFSPnpSurpriseRemove)
#endif
NTSTATUS NTAPI
FFSPnpCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt)
{
PKEVENT Event = (PKEVENT) Contxt;
KeSetEvent(Event, 0, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Contxt);
}
__drv_mustHoldCriticalRegion
NTSTATUS
FFSPnp(
IN PFFS_IRP_CONTEXT IrpContext)
{
NTSTATUS Status = STATUS_INVALID_PARAMETER;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
PFFS_VCB Vcb = 0;
PDEVICE_OBJECT DeviceObject;
PAGED_CODE();
_SEH2_TRY
{
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
if (!((Vcb->Identifier.Type == FFSVCB) &&
(Vcb->Identifier.Size == sizeof(FFS_VCB))))
{
_SEH2_LEAVE; // Status = STATUS_INVALID_PARAMETER
}
Irp = IrpContext->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
switch (IrpSp->MinorFunction)
{
case IRP_MN_QUERY_REMOVE_DEVICE:
FFSPrint((DBG_PNP, "FFSPnp: FFSPnpQueryRemove...\n"));
Status = FFSPnpQueryRemove(IrpContext, Vcb);
break;
case IRP_MN_REMOVE_DEVICE:
FFSPrint((DBG_PNP, "FFSPnp: FFSPnpRemove...\n"));
Status = FFSPnpRemove(IrpContext, Vcb);
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
FFSPrint((DBG_PNP, "FFSPnp: FFSPnpCancelRemove...\n"));
Status = FFSPnpCancelRemove(IrpContext, Vcb);
break;
case IRP_MN_SURPRISE_REMOVAL:
FFSPrint((DBG_PNP, "FFSPnp: FFSPnpSupriseRemove...\n"));
Status = FFSPnpSurpriseRemove(IrpContext, Vcb);
break;
default:
break;
}
}
_SEH2_FINALLY
{
if (!IrpContext->ExceptionInProgress)
{
Irp = IrpContext->Irp;
if (Irp)
{
//
// Here we need pass the IRP to the disk driver.
//
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
IrpContext->Irp = NULL;
}
FFSCompleteIrpContext(IrpContext, Status);
}
} _SEH2_END;
return Status;
}
__drv_mustHoldCriticalRegion
NTSTATUS
FFSPnpQueryRemove(
PFFS_IRP_CONTEXT IrpContext,
PFFS_VCB Vcb)
{
NTSTATUS Status;
KEVENT Event;
BOOLEAN bDeleted = FALSE;
BOOLEAN VcbAcquired = FALSE;
PAGED_CODE();
_SEH2_TRY {
FFSPrint((DBG_PNP, "FFSPnpQueryRemove by FFSPnp ...\n"));
FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSFlushVolume ...\n"));
#if (_WIN32_WINNT >= 0x0500)
CcWaitForCurrentLazyWriterActivity();
#endif
ExAcquireResourceExclusiveLite(
&Vcb->MainResource, TRUE);
VcbAcquired = TRUE;
FFSFlushFiles(Vcb, FALSE);
FFSFlushVolume(Vcb, FALSE);
FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSLockVcb: Vcb=%xh FileObject=%xh ...\n", Vcb, IrpContext->FileObject));
Status = FFSLockVcb(Vcb, IrpContext->FileObject);
FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSPurgeVolume ...\n"));
FFSPurgeVolume(Vcb, TRUE);
if (!NT_SUCCESS(Status))
{
_SEH2_LEAVE;
}
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread());
VcbAcquired = FALSE;
IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
KeInitializeEvent(&Event, NotificationEvent, FALSE);
IoSetCompletionRoutine(IrpContext->Irp,
FFSPnpCompletionRoutine,
&Event,
TRUE,
TRUE,
TRUE);
FFSPrint((DBG_PNP, "FFSPnpQueryRemove: Call lower level driver...\n"));
Status = IoCallDriver(Vcb->TargetDeviceObject,
IrpContext->Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event,
Executive,
KernelMode,
FALSE,
NULL);
Status = IrpContext->Irp->IoStatus.Status;
}
if (NT_SUCCESS(Status))
{
FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSCheckDismount ...\n"));
bDeleted = FFSCheckDismount(IrpContext, Vcb, TRUE);
FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSFlushVolume bDelted=%xh ...\n", bDeleted));
}
ASSERT(!(NT_SUCCESS(Status) && !bDeleted));
}
_SEH2_FINALLY
{
if (VcbAcquired)
{
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread());
}
FFSCompleteRequest(
IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status) ?
IO_DISK_INCREMENT : IO_NO_INCREMENT));
IrpContext->Irp = NULL;
} _SEH2_END;
return Status;
}
__drv_mustHoldCriticalRegion
NTSTATUS
FFSPnpRemove(
PFFS_IRP_CONTEXT IrpContext,
PFFS_VCB Vcb)
{
NTSTATUS Status;
KEVENT Event;
BOOLEAN bDeleted;
PAGED_CODE();
_SEH2_TRY
{
FFSPrint((DBG_PNP, "FFSPnpRemove by FFSPnp ...\n"));
#if (_WIN32_WINNT >= 0x0500)
CcWaitForCurrentLazyWriterActivity();
#endif
ExAcquireResourceExclusiveLite(
&Vcb->MainResource, TRUE);
Status = FFSLockVcb(Vcb, IrpContext->FileObject);
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread());
//
// Setup the Irp. We'll send it to the lower disk driver.
//
IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
KeInitializeEvent(&Event, NotificationEvent, FALSE);
IoSetCompletionRoutine(IrpContext->Irp,
FFSPnpCompletionRoutine,
&Event,
TRUE,
TRUE,
TRUE);
Status = IoCallDriver(Vcb->TargetDeviceObject,
IrpContext->Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event,
Executive,
KernelMode,
FALSE,
NULL);
Status = IrpContext->Irp->IoStatus.Status;
}
ExAcquireResourceExclusiveLite(
&Vcb->MainResource, TRUE);
FFSPurgeVolume(Vcb, FALSE);
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread());
bDeleted = FFSCheckDismount(IrpContext, Vcb, TRUE);
}
_SEH2_FINALLY
{
FFSCompleteRequest(
IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
IO_DISK_INCREMENT : IO_NO_INCREMENT));
IrpContext->Irp = NULL;
} _SEH2_END;
return Status;
}
__drv_mustHoldCriticalRegion
NTSTATUS
FFSPnpSurpriseRemove(
PFFS_IRP_CONTEXT IrpContext,
PFFS_VCB Vcb)
{
NTSTATUS Status;
KEVENT Event;
BOOLEAN bDeleted;
PAGED_CODE();
_SEH2_TRY
{
FFSPrint((DBG_PNP, "FFSPnpSupriseRemove by FFSPnp ...\n"));
#if (_WIN32_WINNT >= 0x0500)
CcWaitForCurrentLazyWriterActivity();
#endif
ExAcquireResourceExclusiveLite(
&Vcb->MainResource, TRUE);
Status = FFSLockVcb(Vcb, IrpContext->FileObject);
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread());
//
// Setup the Irp. We'll send it to the lower disk driver.
//
IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
KeInitializeEvent(&Event, NotificationEvent, FALSE);
IoSetCompletionRoutine(IrpContext->Irp,
FFSPnpCompletionRoutine,
&Event,
TRUE,
TRUE,
TRUE);
Status = IoCallDriver(Vcb->TargetDeviceObject,
IrpContext->Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event,
Executive,
KernelMode,
FALSE,
NULL);
Status = IrpContext->Irp->IoStatus.Status;
}
ExAcquireResourceExclusiveLite(
&Vcb->MainResource, TRUE);
FFSPurgeVolume(Vcb, FALSE);
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread());
bDeleted = FFSCheckDismount(IrpContext, Vcb, TRUE);
}
_SEH2_FINALLY
{
FFSCompleteRequest(
IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
IO_DISK_INCREMENT : IO_NO_INCREMENT));
IrpContext->Irp = NULL;
} _SEH2_END;
return Status;
}
__drv_mustHoldCriticalRegion
NTSTATUS
FFSPnpCancelRemove(
PFFS_IRP_CONTEXT IrpContext,
PFFS_VCB Vcb)
{
NTSTATUS Status;
PAGED_CODE();
FFSPrint((DBG_PNP, "FFSPnpCancelRemove by FFSPnp ...\n"));
ExAcquireResourceExclusiveLite(
&Vcb->MainResource, TRUE);
Status = FFSUnlockVcb(Vcb, IrpContext->FileObject);
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread());
IoSkipCurrentIrpStackLocation(IrpContext->Irp);
Status = IoCallDriver(Vcb->TargetDeviceObject, IrpContext->Irp);
IrpContext->Irp = NULL;
return Status;
}
#endif //(_WIN32_WINNT >= 0x0500)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,136 @@
/*
* FFS File System Driver for Windows
*
* read.c
*
* 2004.5.6 ~
*
* Lee Jae-Hong, http://www.pyrasis.com
*
* See License.txt
*
*/
#include "ntifs.h"
#include "ffsdrv.h"
/* Globals */
extern PFFS_GLOBAL FFSGlobal;
/* Definitions */
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSShutDown)
#endif
__drv_mustHoldCriticalRegion
NTSTATUS
FFSShutDown(
IN PFFS_IRP_CONTEXT IrpContext)
{
NTSTATUS Status;
PKEVENT Event;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
PFFS_VCB Vcb;
PLIST_ENTRY ListEntry;
BOOLEAN GlobalResourceAcquired = FALSE;
PAGED_CODE();
_SEH2_TRY
{
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
Status = STATUS_SUCCESS;
Irp = IrpContext->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
if (!ExAcquireResourceExclusiveLite(
&FFSGlobal->Resource,
IrpContext->IsSynchronous))
{
Status = STATUS_PENDING;
_SEH2_LEAVE;
}
GlobalResourceAcquired = TRUE;
Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), FFS_POOL_TAG);
KeInitializeEvent(Event, NotificationEvent, FALSE);
for (ListEntry = FFSGlobal->VcbList.Flink;
ListEntry != &(FFSGlobal->VcbList);
ListEntry = ListEntry->Flink)
{
Vcb = CONTAINING_RECORD(ListEntry, FFS_VCB, Next);
if (ExAcquireResourceExclusiveLite(
&Vcb->MainResource,
TRUE))
{
Status = FFSFlushFiles(Vcb, TRUE);
if(!NT_SUCCESS(Status))
{
FFSBreakPoint();
}
Status = FFSFlushVolume(Vcb, TRUE);
if(!NT_SUCCESS(Status))
{
FFSBreakPoint();
}
FFSDiskShutDown(Vcb);
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread());
}
}
/*
IoUnregisterFileSystem(FFSGlobal->DeviceObject);
*/
}
_SEH2_FINALLY
{
if (GlobalResourceAcquired)
{
ExReleaseResourceForThreadLite(
&FFSGlobal->Resource,
ExGetCurrentResourceThread());
}
if (!IrpContext->ExceptionInProgress)
{
if (Status == STATUS_PENDING)
{
FFSQueueRequest(IrpContext);
}
else
{
FFSCompleteIrpContext(IrpContext, Status);
}
}
} _SEH2_END;
return Status;
}

View file

@ -0,0 +1,478 @@
/*
* FFS File System Driver for Windows
*
* volinfo.c
*
* 2004.5.6 ~
*
* Lee Jae-Hong, http://www.pyrasis.com
*
* See License.txt
*
*/
#include "ntifs.h"
#include "ffsdrv.h"
/* Globals */
extern PFFS_GLOBAL FFSGlobal;
/* Definitions */
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSQueryVolumeInformation)
#pragma alloc_text(PAGE, FFSSetVolumeInformation)
#endif
__drv_mustHoldCriticalRegion
NTSTATUS
FFSQueryVolumeInformation(
IN PFFS_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PFFS_VCB Vcb = 0;
PIRP Irp;
PIO_STACK_LOCATION IoStackLocation;
FS_INFORMATION_CLASS FsInformationClass;
ULONG Length;
PVOID Buffer;
BOOLEAN VcbResourceAcquired = FALSE;
PAGED_CODE();
_SEH2_TRY
{
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
//
// This request is not allowed on the main device object
//
if (DeviceObject == FFSGlobal->DeviceObject)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
_SEH2_LEAVE;
}
Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == FFSVCB) &&
(Vcb->Identifier.Size == sizeof(FFS_VCB)));
ASSERT(IsMounted(Vcb));
if (!ExAcquireResourceSharedLite(
&Vcb->MainResource,
IrpContext->IsSynchronous))
{
Status = STATUS_PENDING;
_SEH2_LEAVE;
}
VcbResourceAcquired = TRUE;
Irp = IrpContext->Irp;
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
FsInformationClass =
IoStackLocation->Parameters.QueryVolume.FsInformationClass;
Length = IoStackLocation->Parameters.QueryVolume.Length;
Buffer = Irp->AssociatedIrp.SystemBuffer;
RtlZeroMemory(Buffer, Length);
switch (FsInformationClass)
{
case FileFsVolumeInformation:
{
PFILE_FS_VOLUME_INFORMATION FsVolInfo;
ULONG VolumeLabelLength;
ULONG RequiredLength;
if (Length < sizeof(FILE_FS_VOLUME_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
_SEH2_LEAVE;
}
FsVolInfo = (PFILE_FS_VOLUME_INFORMATION)Buffer;
FsVolInfo->VolumeCreationTime.QuadPart = 0;
FsVolInfo->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
VolumeLabelLength = Vcb->Vpb->VolumeLabelLength;
FsVolInfo->VolumeLabelLength = VolumeLabelLength;
// I don't know what this means
FsVolInfo->SupportsObjects = FALSE;
RequiredLength = sizeof(FILE_FS_VOLUME_INFORMATION)
+ VolumeLabelLength - sizeof(WCHAR);
if (Length < RequiredLength)
{
Irp->IoStatus.Information =
sizeof(FILE_FS_VOLUME_INFORMATION);
Status = STATUS_BUFFER_OVERFLOW;
_SEH2_LEAVE;
}
RtlCopyMemory(FsVolInfo->VolumeLabel, Vcb->Vpb->VolumeLabel, Vcb->Vpb->VolumeLabelLength);
Irp->IoStatus.Information = RequiredLength;
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
case FileFsSizeInformation:
{
PFILE_FS_SIZE_INFORMATION FsSizeInfo;
if (Length < sizeof(FILE_FS_SIZE_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
_SEH2_LEAVE;
}
FsSizeInfo = (PFILE_FS_SIZE_INFORMATION)Buffer;
{
if (FS_VERSION == 1)
{
FsSizeInfo->TotalAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_old_size / 8);
FsSizeInfo->AvailableAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_old_cstotal.cs_nbfree / 8);
}
else
{
FsSizeInfo->TotalAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_size / 8);
FsSizeInfo->AvailableAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_cstotal.cs_nbfree / 8);
}
}
FsSizeInfo->SectorsPerAllocationUnit =
Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector;
FsSizeInfo->BytesPerSector =
Vcb->DiskGeometry.BytesPerSector;
Irp->IoStatus.Information = sizeof(FILE_FS_SIZE_INFORMATION);
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
case FileFsDeviceInformation:
{
PFILE_FS_DEVICE_INFORMATION FsDevInfo;
if (Length < sizeof(FILE_FS_DEVICE_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
_SEH2_LEAVE;
}
FsDevInfo = (PFILE_FS_DEVICE_INFORMATION)Buffer;
FsDevInfo->DeviceType =
Vcb->TargetDeviceObject->DeviceType;
FsDevInfo->Characteristics =
Vcb->TargetDeviceObject->Characteristics;
if (FlagOn(Vcb->Flags, VCB_READ_ONLY))
{
SetFlag(FsDevInfo->Characteristics,
FILE_READ_ONLY_DEVICE);
}
Irp->IoStatus.Information = sizeof(FILE_FS_DEVICE_INFORMATION);
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
case FileFsAttributeInformation:
{
PFILE_FS_ATTRIBUTE_INFORMATION FsAttrInfo;
ULONG RequiredLength;
if (Length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
_SEH2_LEAVE;
}
FsAttrInfo =
(PFILE_FS_ATTRIBUTE_INFORMATION)Buffer;
FsAttrInfo->FileSystemAttributes =
FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
FsAttrInfo->MaximumComponentNameLength = FFS_NAME_LEN;
FsAttrInfo->FileSystemNameLength = 10;
RequiredLength = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) +
10 - sizeof(WCHAR);
if (Length < RequiredLength)
{
Irp->IoStatus.Information =
sizeof(FILE_FS_ATTRIBUTE_INFORMATION);
Status = STATUS_BUFFER_OVERFLOW;
_SEH2_LEAVE;
}
RtlCopyMemory(
FsAttrInfo->FileSystemName,
L"FFS\0", 8);
Irp->IoStatus.Information = RequiredLength;
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
#if (_WIN32_WINNT >= 0x0500)
case FileFsFullSizeInformation:
{
PFILE_FS_FULL_SIZE_INFORMATION PFFFSI;
if (Length < sizeof(FILE_FS_FULL_SIZE_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
_SEH2_LEAVE;
}
PFFFSI = (PFILE_FS_FULL_SIZE_INFORMATION)Buffer;
/*
typedef struct _FILE_FS_FULL_SIZE_INFORMATION {
LARGE_INTEGER TotalAllocationUnits;
LARGE_INTEGER CallerAvailableAllocationUnits;
LARGE_INTEGER ActualAvailableAllocationUnits;
ULONG SectorsPerAllocationUnit;
ULONG BytesPerSector;
} FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION;
*/
{
if (FS_VERSION == 1)
{
PFFFSI->TotalAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_old_size / 8);
PFFFSI->CallerAvailableAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_old_cstotal.cs_nbfree / 8);
PFFFSI->ActualAvailableAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_old_cstotal.cs_nbfree / 8);
}
else
{
PFFFSI->TotalAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_size / 8);
PFFFSI->CallerAvailableAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_cstotal.cs_nbfree / 8);
PFFFSI->ActualAvailableAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_cstotal.cs_nbfree / 8);
}
}
PFFFSI->SectorsPerAllocationUnit =
Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector;
PFFFSI->BytesPerSector = Vcb->DiskGeometry.BytesPerSector;
Irp->IoStatus.Information = sizeof(FILE_FS_FULL_SIZE_INFORMATION);
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
#endif // (_WIN32_WINNT >= 0x0500)
default:
Status = STATUS_INVALID_INFO_CLASS;
}
}
_SEH2_FINALLY
{
if (VcbResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread());
}
if (!IrpContext->ExceptionInProgress)
{
if (Status == STATUS_PENDING)
{
FFSQueueRequest(IrpContext);
}
else
{
FFSCompleteIrpContext(IrpContext, Status);
}
}
} _SEH2_END;
return Status;
}
#if !FFS_READ_ONLY
__drv_mustHoldCriticalRegion
NTSTATUS
FFSSetVolumeInformation(
IN PFFS_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PFFS_VCB Vcb;
PIRP Irp;
PIO_STACK_LOCATION IoStackLocation;
FS_INFORMATION_CLASS FsInformationClass;
PAGED_CODE();
_SEH2_TRY
{
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
//
// This request is not allowed on the main device object
//
if (DeviceObject == FFSGlobal->DeviceObject)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
_SEH2_LEAVE;
}
Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == FFSVCB) &&
(Vcb->Identifier.Size == sizeof(FFS_VCB)));
ASSERT(IsMounted(Vcb));
if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
{
Status = STATUS_MEDIA_WRITE_PROTECTED;
_SEH2_LEAVE;
}
Irp = IrpContext->Irp;
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
//Notes: SetVolume is not defined in ntddk.h of win2k ddk,
// But it's same to QueryVolume ....
FsInformationClass =
IoStackLocation->Parameters./*SetVolume*/QueryVolume.FsInformationClass;
switch (FsInformationClass)
{
case FileFsLabelInformation:
{
PFILE_FS_LABEL_INFORMATION VolLabelInfo = NULL;
ULONG VolLabelLen;
UNICODE_STRING LabelName ;
OEM_STRING OemName;
VolLabelInfo = (PFILE_FS_LABEL_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
VolLabelLen = VolLabelInfo->VolumeLabelLength;
if(VolLabelLen > (16 * sizeof(WCHAR)))
{
Status = STATUS_INVALID_VOLUME_LABEL;
_SEH2_LEAVE;
}
RtlCopyMemory(Vcb->Vpb->VolumeLabel,
VolLabelInfo->VolumeLabel,
VolLabelLen);
RtlZeroMemory(Vcb->ffs_super_block->fs_volname, 16);
LabelName.Buffer = VolLabelInfo->VolumeLabel;
LabelName.MaximumLength = (USHORT)16 * sizeof(WCHAR);
LabelName.Length = (USHORT)VolLabelLen;
OemName.Buffer = SUPER_BLOCK->fs_volname;
OemName.Length = 0;
OemName.MaximumLength = 16;
FFSUnicodeToOEM(&OemName,
&LabelName);
Vcb->Vpb->VolumeLabelLength =
(USHORT)VolLabelLen;
if (FFSSaveSuper(IrpContext, Vcb))
{
Status = STATUS_SUCCESS;
}
Irp->IoStatus.Information = 0;
}
break;
default:
Status = STATUS_INVALID_INFO_CLASS;
}
}
_SEH2_FINALLY
{
if (!IrpContext->ExceptionInProgress)
{
if (Status == STATUS_PENDING)
{
FFSQueueRequest(IrpContext);
}
else
{
FFSCompleteIrpContext(IrpContext, Status);
}
}
} _SEH2_END;
return Status;
}
#endif // !FFS_READ_ONLY

File diff suppressed because it is too large Load diff