ReactOS 0.4.15-dev-7924-g5949c20
create.c File Reference
#include <sys/stat.h>
#include "btrfs_drv.h"
#include "crc32c.h"
#include <ntddstor.h>
Include dependency graph for create.c:

Go to the source code of this file.

Classes

struct  _FILE_TIMESTAMPS
 
struct  _ATOMIC_CREATE_ECP_CONTEXT
 
struct  oplock_context
 

Macros

#define ATOMIC_CREATE_ECP_IN_FLAG_REPARSE_POINT_SPECIFIED   0x0002
 
#define ATOMIC_CREATE_ECP_IN_FLAG_OP_FLAGS_SPECIFIED   0x0080
 
#define ATOMIC_CREATE_ECP_IN_FLAG_BEST_EFFORT   0x0100
 
#define ATOMIC_CREATE_ECP_OUT_FLAG_REPARSE_POINT_SET   0x0002
 
#define ATOMIC_CREATE_ECP_OUT_FLAG_OP_FLAGS_HONORED   0x0080
 
#define ATOMIC_CREATE_ECP_IN_OP_FLAG_CASE_SENSITIVE_FLAGS_SPECIFIED   1
 
#define ATOMIC_CREATE_ECP_OUT_OP_FLAG_CASE_SENSITIVE_FLAGS_SET   1
 
#define SL_IGNORE_READONLY_ATTRIBUTE   0x40
 
#define called_from_lxss()   false
 

Typedefs

typedef struct _FILE_TIMESTAMPS FILE_TIMESTAMPS
 
typedef struct _FILE_TIMESTAMPSPFILE_TIMESTAMPS
 
typedef struct _ATOMIC_CREATE_ECP_CONTEXT ATOMIC_CREATE_ECP_CONTEXT
 
typedef struct _ATOMIC_CREATE_ECP_CONTEXTPATOMIC_CREATE_ECP_CONTEXT
 

Functions

fcbcreate_fcb (device_extension *Vcb, POOL_TYPE pool_type)
 
file_refcreate_fileref (device_extension *Vcb)
 
NTSTATUS find_file_in_dir (PUNICODE_STRING filename, fcb *fcb, root **subvol, uint64_t *inode, dir_child **pdc, bool case_sensitive)
 
static NTSTATUS split_path (device_extension *Vcb, PUNICODE_STRING path, LIST_ENTRY *parts, bool *stream)
 
NTSTATUS load_csum (_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, void *csum, uint64_t start, uint64_t length, PIRP Irp)
 
NTSTATUS load_dir_children (_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, fcb *fcb, bool ignore_size, PIRP Irp)
 
NTSTATUS open_fcb (_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, root *subvol, uint64_t inode, uint8_t type, PANSI_STRING utf8, bool always_add_hl, fcb *parent, fcb **pfcb, POOL_TYPE pooltype, PIRP Irp)
 
static NTSTATUS open_fcb_stream (_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, dir_child *dc, fcb *parent, fcb **pfcb, PIRP Irp)
 
NTSTATUS open_fileref_child (_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension *Vcb, _In_ file_ref *sf, _In_ PUNICODE_STRING name, _In_ bool case_sensitive, _In_ bool lastpart, _In_ bool streampart, _In_ POOL_TYPE pooltype, _Out_ file_ref **psf2, _In_opt_ PIRP Irp)
 
NTSTATUS open_fileref (_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension *Vcb, _Out_ file_ref **pfr, _In_ PUNICODE_STRING fnus, _In_opt_ file_ref *related, _In_ bool parent, _Out_opt_ USHORT *parsed, _Out_opt_ ULONG *fn_offset, _In_ POOL_TYPE pooltype, _In_ bool case_sensitive, _In_opt_ PIRP Irp)
 
NTSTATUS add_dir_child (fcb *fcb, uint64_t inode, bool subvol, PANSI_STRING utf8, PUNICODE_STRING name, uint8_t type, dir_child **pdc)
 
uint32_t inherit_mode (fcb *parfcb, bool is_dir)
 
static NTSTATUS file_create_parse_ea (fcb *fcb, FILE_FULL_EA_INFORMATION *ea)
 
static NTSTATUS file_create2 (_In_ PIRP Irp, _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension *Vcb, _In_ PUNICODE_STRING fpus, _In_ file_ref *parfileref, _In_ ULONG options, _In_reads_bytes_opt_(ealen) FILE_FULL_EA_INFORMATION *ea, _In_ ULONG ealen, _Out_ file_ref **pfr, bool case_sensitive, _In_ LIST_ENTRY *rollback)
 
static NTSTATUS create_stream (_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, file_ref **pfileref, file_ref **pparfileref, PUNICODE_STRING fpus, PUNICODE_STRING stream, PIRP Irp, ULONG options, POOL_TYPE pool_type, bool case_sensitive, LIST_ENTRY *rollback)
 
static NTSTATUS file_create (PIRP Irp, _Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, PFILE_OBJECT FileObject, file_ref *related, bool loaded_related, PUNICODE_STRING fnus, ULONG disposition, ULONG options, file_ref **existing_fileref, LIST_ENTRY *rollback)
 
static __inline void debug_create_options (ULONG RequestedOptions)
 
static NTSTATUS get_reparse_block (fcb *fcb, uint8_t **data)
 
static void fcb_load_csums (_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, fcb *fcb, PIRP Irp)
 
static NTSTATUS open_file3 (device_extension *Vcb, PIRP Irp, ACCESS_MASK granted_access, file_ref *fileref, LIST_ENTRY *rollback)
 
static void __stdcall oplock_complete (PVOID Context, PIRP Irp)
 
static NTSTATUS open_file2 (device_extension *Vcb, ULONG RequestedDisposition, file_ref *fileref, ACCESS_MASK *granted_access, PFILE_OBJECT FileObject, UNICODE_STRING *fn, ULONG options, PIRP Irp, LIST_ENTRY *rollback, oplock_context **opctx)
 
NTSTATUS open_fileref_by_inode (_Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, root *subvol, uint64_t inode, file_ref **pfr, PIRP Irp)
 
static NTSTATUS open_file (PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback, oplock_context **opctx)
 
static NTSTATUS verify_vcb (device_extension *Vcb, PIRP Irp)
 
static bool has_manage_volume_privilege (ACCESS_STATE *access_state, KPROCESSOR_MODE processor_mode)
 
 _Dispatch_type_ (IRP_MJ_CREATE)
 

Variables

PDEVICE_OBJECT master_devobj
 
tFsRtlGetEcpListFromIrp fFsRtlGetEcpListFromIrp
 
tFsRtlGetNextExtraCreateParameter fFsRtlGetNextExtraCreateParameter
 
tFsRtlValidateReparsePointBuffer fFsRtlValidateReparsePointBuffer
 
static const WCHAR datastring [] = L"::$DATA"
 
static const char root_dir [] = "$Root"
 
static const WCHAR root_dir_utf16 [] = L"$Root"
 
static const GUID GUID_ECP_ATOMIC_CREATE = { 0x4720bd83, 0x52ac, 0x4104, { 0xa1, 0x30, 0xd1, 0xec, 0x6a, 0x8c, 0xc8, 0xe5 } }
 
static const GUID GUID_ECP_QUERY_ON_CREATE = { 0x1aca62e9, 0xabb4, 0x4ff2, { 0xbb, 0x5c, 0x1c, 0x79, 0x02, 0x5e, 0x41, 0x7f } }
 
static const GUID GUID_ECP_CREATE_REDIRECTION = { 0x188d6bd6, 0xa126, 0x4fa8, { 0xbd, 0xf2, 0x1c, 0xcd, 0xf8, 0x96, 0xf3, 0xe0 } }
 

Macro Definition Documentation

◆ ATOMIC_CREATE_ECP_IN_FLAG_BEST_EFFORT

#define ATOMIC_CREATE_ECP_IN_FLAG_BEST_EFFORT   0x0100

Definition at line 38 of file create.c.

◆ ATOMIC_CREATE_ECP_IN_FLAG_OP_FLAGS_SPECIFIED

#define ATOMIC_CREATE_ECP_IN_FLAG_OP_FLAGS_SPECIFIED   0x0080

Definition at line 37 of file create.c.

◆ ATOMIC_CREATE_ECP_IN_FLAG_REPARSE_POINT_SPECIFIED

#define ATOMIC_CREATE_ECP_IN_FLAG_REPARSE_POINT_SPECIFIED   0x0002

Definition at line 36 of file create.c.

◆ ATOMIC_CREATE_ECP_IN_OP_FLAG_CASE_SENSITIVE_FLAGS_SPECIFIED

#define ATOMIC_CREATE_ECP_IN_OP_FLAG_CASE_SENSITIVE_FLAGS_SPECIFIED   1

Definition at line 43 of file create.c.

◆ ATOMIC_CREATE_ECP_OUT_FLAG_OP_FLAGS_HONORED

#define ATOMIC_CREATE_ECP_OUT_FLAG_OP_FLAGS_HONORED   0x0080

Definition at line 41 of file create.c.

◆ ATOMIC_CREATE_ECP_OUT_FLAG_REPARSE_POINT_SET

#define ATOMIC_CREATE_ECP_OUT_FLAG_REPARSE_POINT_SET   0x0002

Definition at line 40 of file create.c.

◆ ATOMIC_CREATE_ECP_OUT_OP_FLAG_CASE_SENSITIVE_FLAGS_SET

#define ATOMIC_CREATE_ECP_OUT_OP_FLAG_CASE_SENSITIVE_FLAGS_SET   1

Definition at line 44 of file create.c.

◆ called_from_lxss

#define called_from_lxss ( )    false

Definition at line 3004 of file create.c.

◆ SL_IGNORE_READONLY_ATTRIBUTE

#define SL_IGNORE_READONLY_ATTRIBUTE   0x40

Definition at line 47 of file create.c.

Typedef Documentation

◆ ATOMIC_CREATE_ECP_CONTEXT

◆ FILE_TIMESTAMPS

◆ PATOMIC_CREATE_ECP_CONTEXT

◆ PFILE_TIMESTAMPS

Function Documentation

◆ _Dispatch_type_()

_Dispatch_type_ ( IRP_MJ_CREATE  )

Definition at line 4826 of file create.c.

4828 {
4831 device_extension* Vcb = DeviceObject->DeviceExtension;
4832 bool top_level, locked = false;
4833 oplock_context* opctx = NULL;
4834
4836
4837 TRACE("create (flags = %lx)\n", Irp->Flags);
4838
4839 top_level = is_top_level(Irp);
4840
4841 /* return success if just called for FS device object */
4842 if (DeviceObject == master_devobj) {
4843 TRACE("create called for FS device object\n");
4844
4845 Irp->IoStatus.Information = FILE_OPENED;
4847
4848 goto exit;
4849 } else if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
4851 goto exit;
4852 } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
4854 goto exit;
4855 }
4856
4857 if (!(Vcb->Vpb->Flags & VPB_MOUNTED)) {
4859 goto exit;
4860 }
4861
4862 if (Vcb->removing) {
4864 goto exit;
4865 }
4866
4868 if (!NT_SUCCESS(Status)) {
4869 ERR("verify_vcb returned %08lx\n", Status);
4870 goto exit;
4871 }
4872
4873 ExAcquireResourceSharedLite(&Vcb->load_lock, true);
4874 locked = true;
4875
4877
4878 if (IrpSp->Flags != 0) {
4880
4881 TRACE("flags:\n");
4882
4883 if (flags & SL_CASE_SENSITIVE) {
4884 TRACE("SL_CASE_SENSITIVE\n");
4885 flags &= ~SL_CASE_SENSITIVE;
4886 }
4887
4889 TRACE("SL_FORCE_ACCESS_CHECK\n");
4890 flags &= ~SL_FORCE_ACCESS_CHECK;
4891 }
4892
4893 if (flags & SL_OPEN_PAGING_FILE) {
4894 TRACE("SL_OPEN_PAGING_FILE\n");
4895 flags &= ~SL_OPEN_PAGING_FILE;
4896 }
4897
4899 TRACE("SL_OPEN_TARGET_DIRECTORY\n");
4900 flags &= ~SL_OPEN_TARGET_DIRECTORY;
4901 }
4902
4903 if (flags & SL_STOP_ON_SYMLINK) {
4904 TRACE("SL_STOP_ON_SYMLINK\n");
4905 flags &= ~SL_STOP_ON_SYMLINK;
4906 }
4907
4909 TRACE("SL_IGNORE_READONLY_ATTRIBUTE\n");
4910 flags &= ~SL_IGNORE_READONLY_ATTRIBUTE;
4911 }
4912
4913 if (flags)
4914 WARN("unknown flags: %x\n", flags);
4915 } else {
4916 TRACE("flags: (none)\n");
4917 }
4918
4919 if (!IrpSp->FileObject) {
4920 ERR("FileObject was NULL\n");
4922 goto exit;
4923 }
4924
4925 if (IrpSp->FileObject->RelatedFileObject) {
4926 fcb* relatedfcb = IrpSp->FileObject->RelatedFileObject->FsContext;
4927
4928 if (relatedfcb && relatedfcb->Vcb != Vcb) {
4929 WARN("RelatedFileObject was for different device\n");
4931 goto exit;
4932 }
4933 }
4934
4935 // opening volume
4936 if (IrpSp->FileObject->FileName.Length == 0 && !IrpSp->FileObject->RelatedFileObject) {
4937 ULONG RequestedDisposition = ((IrpSp->Parameters.Create.Options >> 24) & 0xff);
4938 ULONG RequestedOptions = IrpSp->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
4939#ifdef DEBUG_FCB_REFCOUNTS
4940 LONG rc;
4941#endif
4942 ccb* ccb;
4943
4944 TRACE("open operation for volume\n");
4945
4946 if (RequestedDisposition != FILE_OPEN && RequestedDisposition != FILE_OPEN_IF) {
4948 goto exit;
4949 }
4950
4951 if (RequestedOptions & FILE_DIRECTORY_FILE) {
4953 goto exit;
4954 }
4955
4957 if (!ccb) {
4958 ERR("out of memory\n");
4960 goto exit;
4961 }
4962
4963 RtlZeroMemory(ccb, sizeof(*ccb));
4964
4966 ccb->NodeSize = sizeof(*ccb);
4967 ccb->disposition = RequestedDisposition;
4968 ccb->options = RequestedOptions;
4969 ccb->access = IrpSp->Parameters.Create.SecurityContext->AccessState->PreviouslyGrantedAccess;
4971 IrpSp->Flags & SL_FORCE_ACCESS_CHECK ? UserMode : Irp->RequestorMode);
4972 ccb->reserving = false;
4974
4975#ifdef DEBUG_FCB_REFCOUNTS
4976 rc = InterlockedIncrement(&Vcb->volume_fcb->refcount);
4977 WARN("fcb %p: refcount now %i (volume)\n", Vcb->volume_fcb, rc);
4978#else
4979 InterlockedIncrement(&Vcb->volume_fcb->refcount);
4980#endif
4981 IrpSp->FileObject->FsContext = Vcb->volume_fcb;
4982 IrpSp->FileObject->FsContext2 = ccb;
4983
4984 IrpSp->FileObject->SectionObjectPointer = &Vcb->volume_fcb->nonpaged->segment_object;
4985
4986 if (!IrpSp->FileObject->Vpb)
4987 IrpSp->FileObject->Vpb = DeviceObject->Vpb;
4988
4989 InterlockedIncrement(&Vcb->open_files);
4990
4991 Irp->IoStatus.Information = FILE_OPENED;
4993 } else {
4995 bool skip_lock;
4996
4998
4999 TRACE("file name: %.*S\n", (int)(IrpSp->FileObject->FileName.Length / sizeof(WCHAR)), IrpSp->FileObject->FileName.Buffer);
5000
5001 if (IrpSp->FileObject->RelatedFileObject)
5002 TRACE("related file = %p\n", IrpSp->FileObject->RelatedFileObject);
5003
5004 // Don't lock again if we're being called from within CcCopyRead etc.
5005 skip_lock = ExIsResourceAcquiredExclusiveLite(&Vcb->tree_lock);
5006
5007 if (!skip_lock)
5008 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
5009
5010 ExAcquireResourceSharedLite(&Vcb->fileref_lock, true);
5011
5013
5014 if (!NT_SUCCESS(Status))
5016 else
5018
5019 ExReleaseResourceLite(&Vcb->fileref_lock);
5020
5021 if (!skip_lock)
5022 ExReleaseResourceLite(&Vcb->tree_lock);
5023 }
5024
5025exit:
5026 if (Status != STATUS_PENDING) {
5027 Irp->IoStatus.Status = Status;
5029 }
5030
5031 if (locked)
5032 ExReleaseResourceLite(&Vcb->load_lock);
5033
5034 if (Status == STATUS_PENDING) {
5036 Status = opctx->Status;
5037 ExFreePool(opctx);
5038 }
5039
5040 TRACE("create returning %08lx\n", Status);
5041
5042 if (top_level)
5044
5046
5047 return Status;
5048}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define InterlockedIncrement
Definition: armddk.h:53
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
#define VCB_TYPE_VOLUME
Definition: btrfs_drv.h:689
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1365
#define VCB_TYPE_FS
Definition: btrfs_drv.h:687
#define ALLOC_TAG
Definition: btrfs_drv.h:87
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback) __attribute__((nonnull(1
struct _ccb ccb
NTSTATUS NTSTATUS void clear_rollback(LIST_ENTRY *rollback) __attribute__((nonnull(1)))
NTSTATUS vol_create(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: volume.c:36
#define BTRFS_NODE_TYPE_CCB
Definition: btrfs_drv.h:84
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
UINT32 uint32_t
Definition: types.h:75
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
bool is_top_level(_In_ PIRP Irp)
Definition: btrfs.c:278
#define SL_IGNORE_READONLY_ATTRIBUTE
Definition: create.c:47
static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback, oplock_context **opctx)
Definition: create.c:4466
#define called_from_lxss()
Definition: create.c:3004
static NTSTATUS verify_vcb(device_extension *Vcb, PIRP Irp)
Definition: create.c:4753
PDEVICE_OBJECT master_devobj
Definition: btrfs.c:66
static bool has_manage_volume_privilege(ACCESS_STATE *access_state, KPROCESSOR_MODE processor_mode)
Definition: create.c:4815
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define ExAcquireResourceSharedLite(res, wait)
Definition: env_spec_w32.h:621
#define FILE_OPEN
Definition: from_kernel.h:54
#define FILE_OPEN_IF
Definition: from_kernel.h:56
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
Status
Definition: gdiplustypes.h:25
GLbitfield flags
Definition: glext.h:7161
#define KernelMode
Definition: asm.h:34
#define UserMode
Definition: asm.h:35
#define FILE_VALID_OPTION_FLAGS
Definition: nt_native.h:759
#define FILE_OPENED
Definition: nt_native.h:769
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
BOOLEAN NTAPI ExIsResourceAcquiredExclusiveLite(IN PERESOURCE Resource)
Definition: resource.c:1624
#define IoCompleteRequest
Definition: irp.c:1240
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
#define STATUS_PENDING
Definition: ntstatus.h:82
long LONG
Definition: pedump.c:60
#define Vcb
Definition: cdprocs.h:1415
#define exit(n)
Definition: config.h:202
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE(s)
Definition: solgame.cpp:4
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
union _IO_STACK_LOCATION::@1564 Parameters
struct _IO_STACK_LOCATION::@3978::@3979 Create
Definition: typedefs.h:120
CSHORT NodeSize
Definition: btrfs_drv.h:372
bool reserving
Definition: btrfs_drv.h:381
bool lxss
Definition: btrfs_drv.h:391
ULONG disposition
Definition: btrfs_drv.h:373
bool manage_volume_privilege
Definition: btrfs_drv.h:379
ACCESS_MASK access
Definition: btrfs_drv.h:382
USHORT NodeType
Definition: btrfs_drv.h:371
ULONG options
Definition: btrfs_drv.h:374
struct _device_extension * Vcb
Definition: btrfs_drv.h:287
NTSTATUS Status
Definition: create.c:87
KEVENT event
Definition: create.c:88
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_NOT_A_DIRECTORY
Definition: udferr_usr.h:169
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
#define SL_OPEN_PAGING_FILE
Definition: iotypes.h:1817
#define VPB_MOUNTED
Definition: iotypes.h:1807
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define SL_FORCE_ACCESS_CHECK
Definition: iotypes.h:1816
#define SL_STOP_ON_SYMLINK
Definition: iotypes.h:1819
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define SL_OPEN_TARGET_DIRECTORY
Definition: iotypes.h:1818
#define SL_CASE_SENSITIVE
Definition: iotypes.h:1820
@ Executive
Definition: ketypes.h:415
__wchar_t WCHAR
Definition: xmlstorage.h:180

◆ add_dir_child()

NTSTATUS add_dir_child ( fcb fcb,
uint64_t  inode,
bool  subvol,
PANSI_STRING  utf8,
PUNICODE_STRING  name,
uint8_t  type,
dir_child **  pdc 
)

Definition at line 1871 of file create.c.

1871 {
1873 dir_child* dc;
1874 bool locked;
1875
1877 if (!dc) {
1878 ERR("out of memory\n");
1880 }
1881
1882 RtlZeroMemory(dc, sizeof(dir_child));
1883
1884 dc->utf8.Buffer = ExAllocatePoolWithTag(PagedPool, utf8->Length, ALLOC_TAG);
1885 if (!dc->utf8.Buffer) {
1886 ERR("out of memory\n");
1887 ExFreePool(dc);
1889 }
1890
1891 dc->name.Buffer = ExAllocatePoolWithTag(PagedPool, name->Length, ALLOC_TAG);
1892 if (!dc->name.Buffer) {
1893 ERR("out of memory\n");
1894 ExFreePool(dc->utf8.Buffer);
1895 ExFreePool(dc);
1897 }
1898
1899 dc->key.obj_id = inode;
1900 dc->key.obj_type = subvol ? TYPE_ROOT_ITEM : TYPE_INODE_ITEM;
1901 dc->key.offset = subvol ? 0xffffffffffffffff : 0;
1902 dc->type = type;
1903 dc->fileref = NULL;
1904
1905 dc->utf8.Length = dc->utf8.MaximumLength = utf8->Length;
1906 RtlCopyMemory(dc->utf8.Buffer, utf8->Buffer, utf8->Length);
1907
1908 dc->name.Length = dc->name.MaximumLength = name->Length;
1909 RtlCopyMemory(dc->name.Buffer, name->Buffer, name->Length);
1910
1911 Status = RtlUpcaseUnicodeString(&dc->name_uc, name, true);
1912 if (!NT_SUCCESS(Status)) {
1913 ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
1914 ExFreePool(dc->utf8.Buffer);
1915 ExFreePool(dc->name.Buffer);
1916 ExFreePool(dc);
1917 return Status;
1918 }
1919
1920 dc->hash = calc_crc32c(0xffffffff, (uint8_t*)dc->name.Buffer, dc->name.Length);
1921 dc->hash_uc = calc_crc32c(0xffffffff, (uint8_t*)dc->name_uc.Buffer, dc->name_uc.Length);
1922
1923 locked = ExIsResourceAcquiredExclusive(&fcb->nonpaged->dir_children_lock);
1924
1925 if (!locked)
1926 ExAcquireResourceExclusiveLite(&fcb->nonpaged->dir_children_lock, true);
1927
1929 dc->index = 2;
1930 else {
1932
1933 dc->index = max(2, dc2->index + 1);
1934 }
1935
1936 InsertTailList(&fcb->dir_children_index, &dc->list_entry_index);
1937
1939
1940 if (!locked)
1941 ExReleaseResourceLite(&fcb->nonpaged->dir_children_lock);
1942
1943 *pdc = dc;
1944
1945 return STATUS_SUCCESS;
1946}
void insert_dir_child_into_hash_lists(fcb *fcb, dir_child *dc)
Definition: fileinfo.c:1470
crc_func calc_crc32c
Definition: crc32c.c:23
#define TYPE_ROOT_ITEM
Definition: btrfs.h:32
#define TYPE_INODE_ITEM
Definition: btrfs.h:23
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define PagedPool
Definition: env_spec_w32.h:308
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
static const WCHAR dc[]
BYTE uint8_t
Definition: msvideo1.c:66
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
LIST_ENTRY dir_children_index
Definition: btrfs_drv.h:314
struct _fcb_nonpaged * nonpaged
Definition: btrfs_drv.h:284
uint64_t index
Definition: btrfs_drv.h:252
Definition: fs.h:78
Definition: name.c:39
#define max(a, b)
Definition: svc.c:63
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
#define ExIsResourceAcquiredExclusive
Definition: exfuncs.h:347

Referenced by create_subvol(), do_create_snapshot(), file_create2(), mknod(), and set_link_information().

◆ create_fcb()

fcb * create_fcb ( device_extension Vcb,
POOL_TYPE  pool_type 
)

Definition at line 91 of file create.c.

91 {
92 fcb* fcb;
93
94 if (pool_type == NonPagedPool) {
95 fcb = ExAllocatePoolWithTag(pool_type, sizeof(struct _fcb), ALLOC_TAG);
96 if (!fcb) {
97 ERR("out of memory\n");
98 return NULL;
99 }
100 } else {
101 fcb = ExAllocateFromPagedLookasideList(&Vcb->fcb_lookaside);
102 if (!fcb) {
103 ERR("out of memory\n");
104 return NULL;
105 }
106 }
107
108#ifdef DEBUG_FCB_REFCOUNTS
109 WARN("allocating fcb %p\n", fcb);
110#endif
111 RtlZeroMemory(fcb, sizeof(struct _fcb));
112 fcb->pool_type = pool_type;
113
114 fcb->Header.NodeTypeCode = BTRFS_NODE_TYPE_FCB;
115 fcb->Header.NodeByteSize = sizeof(struct _fcb);
116
117 fcb->nonpaged = ExAllocateFromNPagedLookasideList(&Vcb->fcb_np_lookaside);
118 if (!fcb->nonpaged) {
119 ERR("out of memory\n");
120
121 if (pool_type == NonPagedPool)
123 else
124 ExFreeToPagedLookasideList(&Vcb->fcb_lookaside, fcb);
125
126 return NULL;
127 }
128 RtlZeroMemory(fcb->nonpaged, sizeof(struct _fcb_nonpaged));
129
130 ExInitializeResourceLite(&fcb->nonpaged->paging_resource);
131 fcb->Header.PagingIoResource = &fcb->nonpaged->paging_resource;
132
133 ExInitializeFastMutex(&fcb->nonpaged->HeaderMutex);
134 FsRtlSetupAdvancedHeader(&fcb->Header, &fcb->nonpaged->HeaderMutex);
135
136 fcb->refcount = 1;
137#ifdef DEBUG_FCB_REFCOUNTS
138 WARN("fcb %p: refcount now %i\n", fcb, fcb->refcount);
139#endif
140
142 fcb->Header.Resource = &fcb->nonpaged->resource;
143
144 ExInitializeResourceLite(&fcb->nonpaged->dir_children_lock);
145
148
152
156
157 return fcb;
158}
#define BTRFS_NODE_TYPE_FCB
Definition: btrfs_drv.h:85
struct _fcb fcb
Definition: btrfs_drv.h:1364
static __inline POPLOCK fcb_oplock(fcb *fcb)
Definition: btrfs_drv.h:1677
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
VOID NTAPI FsRtlInitializeFileLock(IN PFILE_LOCK FileLock, IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
Definition: filelock.c:1262
VOID NTAPI FsRtlInitializeOplock(IN OUT POPLOCK Oplock)
Definition: oplock.c:1400
LIST_ENTRY xattrs
Definition: btrfs_drv.h:308
LIST_ENTRY hardlinks
Definition: btrfs_drv.h:304
FILE_LOCK lock
Definition: btrfs_drv.h:294
POOL_TYPE pool_type
Definition: btrfs_drv.h:286
LIST_ENTRY extents
Definition: btrfs_drv.h:300
LIST_ENTRY dir_children_hash
Definition: btrfs_drv.h:315
LIST_ENTRY dir_children_hash_uc
Definition: btrfs_drv.h:316
LONG refcount
Definition: btrfs_drv.h:285
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:283
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274

Referenced by allocate_cache_chunk(), create_directory_fcb(), create_stream(), create_subvol(), duplicate_fcb(), file_create2(), mknod(), mount_vol(), open_fcb(), open_fcb_stream(), rename_stream(), and rename_stream_to_file().

◆ create_fileref()

file_ref * create_fileref ( device_extension Vcb)

Definition at line 160 of file create.c.

160 {
161 file_ref* fr;
162
163 fr = ExAllocateFromPagedLookasideList(&Vcb->fileref_lookaside);
164 if (!fr) {
165 ERR("out of memory\n");
166 return NULL;
167 }
168
169 RtlZeroMemory(fr, sizeof(file_ref));
170
171 fr->refcount = 1;
172
173#ifdef DEBUG_FCB_REFCOUNTS
174 WARN("fileref %p: refcount now 1\n", fr);
175#endif
176
178
179 return fr;
180}
LONG refcount
Definition: btrfs_drv.h:350
LIST_ENTRY children
Definition: btrfs_drv.h:349

Referenced by create_stream(), create_subvol(), do_create_snapshot(), file_create2(), mknod(), mount_vol(), move_across_subvols(), open_fileref_child(), rename_file_to_stream(), set_link_information(), and set_rename_information().

◆ create_stream()

static NTSTATUS create_stream ( _Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension Vcb,
file_ref **  pfileref,
file_ref **  pparfileref,
PUNICODE_STRING  fpus,
PUNICODE_STRING  stream,
PIRP  Irp,
ULONG  options,
POOL_TYPE  pool_type,
bool  case_sensitive,
LIST_ENTRY rollback 
)
static

Definition at line 2640 of file create.c.

2642 {
2644 file_ref *fileref, *newpar, *parfileref;
2645 fcb* fcb;
2646 static const char xapref[] = "user.";
2647 static const WCHAR DOSATTRIB[] = L"DOSATTRIB";
2648 static const WCHAR EA[] = L"EA";
2649 static const WCHAR reparse[] = L"reparse";
2650 static const WCHAR casesensitive_str[] = L"casesensitive";
2653 ULONG utf8len, overhead;
2655 KEY searchkey;
2657 dir_child* dc;
2658 dir_child* existing_dc = NULL;
2659 ACCESS_MASK granted_access;
2660#ifdef DEBUG_FCB_REFCOUNTS
2661 LONG rc;
2662#endif
2663
2664 TRACE("fpus = %.*S\n", (int)(fpus->Length / sizeof(WCHAR)), fpus->Buffer);
2665 TRACE("stream = %.*S\n", (int)(stream->Length / sizeof(WCHAR)), stream->Buffer);
2666
2667 parfileref = *pparfileref;
2668
2669 if (parfileref->fcb == Vcb->dummy_fcb)
2670 return STATUS_ACCESS_DENIED;
2671
2672 Status = check_file_name_valid(stream, false, true);
2673 if (!NT_SUCCESS(Status))
2674 return Status;
2675
2676 Status = open_fileref(Vcb, &newpar, fpus, parfileref, false, NULL, NULL, PagedPool, case_sensitive, Irp);
2677
2679 UNICODE_STRING fpus2;
2680
2681 Status = check_file_name_valid(fpus, false, false);
2682 if (!NT_SUCCESS(Status))
2683 return Status;
2684
2685 fpus2.Length = fpus2.MaximumLength = fpus->Length;
2686 fpus2.Buffer = ExAllocatePoolWithTag(pool_type, fpus2.MaximumLength, ALLOC_TAG);
2687
2688 if (!fpus2.Buffer) {
2689 ERR("out of memory\n");
2691 }
2692
2693 RtlCopyMemory(fpus2.Buffer, fpus->Buffer, fpus2.Length);
2694
2695 SeLockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext);
2696
2697 if (!SeAccessCheck(parfileref->fcb->sd, &IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext,
2700 &granted_access, &Status)) {
2701 SeUnlockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext);
2702 return Status;
2703 }
2704
2705 SeUnlockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext);
2706
2707 Status = file_create2(Irp, Vcb, &fpus2, parfileref, options, NULL, 0, &newpar, case_sensitive, rollback);
2708
2709 if (!NT_SUCCESS(Status)) {
2710 ERR("file_create2 returned %08lx\n", Status);
2711 ExFreePool(fpus2.Buffer);
2712 return Status;
2713 } else if (Status != STATUS_OBJECT_NAME_COLLISION) {
2716 }
2717
2718 ExFreePool(fpus2.Buffer);
2719 } else if (!NT_SUCCESS(Status)) {
2720 ERR("open_fileref returned %08lx\n", Status);
2721 return Status;
2722 }
2723
2724 parfileref = newpar;
2725 *pparfileref = parfileref;
2726
2727 if (parfileref->fcb->type != BTRFS_TYPE_FILE && parfileref->fcb->type != BTRFS_TYPE_SYMLINK && parfileref->fcb->type != BTRFS_TYPE_DIRECTORY) {
2728 WARN("parent not file, directory, or symlink\n");
2729 free_fileref(parfileref);
2731 }
2732
2734 WARN("tried to create directory as stream\n");
2735 free_fileref(parfileref);
2737 }
2738
2740 free_fileref(parfileref);
2741 return STATUS_ACCESS_DENIED;
2742 }
2743
2744 SeLockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext);
2745
2746 if (!SeAccessCheck(parfileref->fcb->sd, &IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext,
2748 &granted_access, &Status)) {
2749 SeUnlockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext);
2750 free_fileref(parfileref);
2751 return Status;
2752 }
2753
2754 SeUnlockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext);
2755
2756 if ((stream->Length == sizeof(DOSATTRIB) - sizeof(WCHAR) && RtlCompareMemory(stream->Buffer, DOSATTRIB, stream->Length) == stream->Length) ||
2757 (stream->Length == sizeof(EA) - sizeof(WCHAR) && RtlCompareMemory(stream->Buffer, EA, stream->Length) == stream->Length) ||
2758 (stream->Length == sizeof(reparse) - sizeof(WCHAR) && RtlCompareMemory(stream->Buffer, reparse, stream->Length) == stream->Length) ||
2759 (stream->Length == sizeof(casesensitive_str) - sizeof(WCHAR) && RtlCompareMemory(stream->Buffer, casesensitive_str, stream->Length) == stream->Length)) {
2760 free_fileref(parfileref);
2762 }
2763
2764 fcb = create_fcb(Vcb, pool_type);
2765 if (!fcb) {
2766 ERR("out of memory\n");
2767 free_fileref(parfileref);
2769 }
2770
2771 fcb->Vcb = Vcb;
2772
2773 fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
2774 fcb->Header.AllocationSize.QuadPart = 0;
2775 fcb->Header.FileSize.QuadPart = 0;
2776 fcb->Header.ValidDataLength.QuadPart = 0;
2777
2778#ifdef DEBUG_FCB_REFCOUNTS
2779 rc = InterlockedIncrement(&parfileref->fcb->refcount);
2780 WARN("fcb %p: refcount now %i\n", parfileref->fcb, rc);
2781#else
2782 InterlockedIncrement(&parfileref->fcb->refcount);
2783#endif
2784 fcb->subvol = parfileref->fcb->subvol;
2785 fcb->inode = parfileref->fcb->inode;
2786 fcb->hash = parfileref->fcb->hash;
2787 fcb->type = parfileref->fcb->type;
2788
2789 fcb->ads = true;
2790
2791 Status = utf16_to_utf8(NULL, 0, &utf8len, stream->Buffer, stream->Length);
2792 if (!NT_SUCCESS(Status)) {
2793 ERR("utf16_to_utf8 1 returned %08lx\n", Status);
2794 reap_fcb(fcb);
2795 free_fileref(parfileref);
2796 return Status;
2797 }
2798
2799 fcb->adsxattr.Length = (uint16_t)utf8len + sizeof(xapref) - 1;
2802 if (!fcb->adsxattr.Buffer) {
2803 ERR("out of memory\n");
2804 reap_fcb(fcb);
2805 free_fileref(parfileref);
2807 }
2808
2809 RtlCopyMemory(fcb->adsxattr.Buffer, xapref, sizeof(xapref) - 1);
2810
2811 Status = utf16_to_utf8(&fcb->adsxattr.Buffer[sizeof(xapref) - 1], utf8len, &utf8len, stream->Buffer, stream->Length);
2812 if (!NT_SUCCESS(Status)) {
2813 ERR("utf16_to_utf8 2 returned %08lx\n", Status);
2814 reap_fcb(fcb);
2815 free_fileref(parfileref);
2816 return Status;
2817 }
2818
2820
2821 TRACE("adsxattr = %s\n", fcb->adsxattr.Buffer);
2822
2824 TRACE("adshash = %08x\n", fcb->adshash);
2825
2826 searchkey.obj_id = parfileref->fcb->inode;
2827 searchkey.obj_type = TYPE_XATTR_ITEM;
2828 searchkey.offset = fcb->adshash;
2829
2830 Status = find_item(Vcb, parfileref->fcb->subvol, &tp, &searchkey, false, Irp);
2831 if (!NT_SUCCESS(Status)) {
2832 ERR("find_item returned %08lx\n", Status);
2833 reap_fcb(fcb);
2834 free_fileref(parfileref);
2835 return Status;
2836 }
2837
2838 if (!keycmp(tp.item->key, searchkey))
2839 overhead = tp.item->size;
2840 else
2841 overhead = 0;
2842
2843 fcb->adsmaxlen = Vcb->superblock.node_size - sizeof(tree_header) - sizeof(leaf_node) - (sizeof(DIR_ITEM) - 1);
2844
2845 if (utf8len + sizeof(xapref) - 1 + overhead > fcb->adsmaxlen) {
2846 WARN("not enough room for new DIR_ITEM (%Iu + %lu > %lu)\n", utf8len + sizeof(xapref) - 1, overhead, fcb->adsmaxlen);
2847 reap_fcb(fcb);
2848 free_fileref(parfileref);
2849 return STATUS_DISK_FULL;
2850 } else
2851 fcb->adsmaxlen -= overhead + utf8len + sizeof(xapref) - 1;
2852
2853 fcb->created = true;
2854 fcb->deleted = true;
2855
2856 acquire_fcb_lock_exclusive(Vcb);
2857 InsertHeadList(&parfileref->fcb->list_entry, &fcb->list_entry); // insert in list after parent fcb
2858 InsertTailList(&Vcb->all_fcbs, &fcb->list_entry_all);
2859 parfileref->fcb->subvol->fcbs_version++;
2860 release_fcb_lock(Vcb);
2861
2863
2864 fileref = create_fileref(Vcb);
2865 if (!fileref) {
2866 ERR("out of memory\n");
2867 free_fcb(fcb);
2868 free_fileref(parfileref);
2870 }
2871
2872 fileref->fcb = fcb;
2873
2875 if (!dc) {
2876 ERR("out of memory\n");
2877 reap_fileref(Vcb, fileref);
2878 free_fileref(parfileref);
2880 }
2881
2882 RtlZeroMemory(dc, sizeof(dir_child));
2883
2884 dc->utf8.MaximumLength = dc->utf8.Length = fcb->adsxattr.Length + 1 - sizeof(xapref);
2885 dc->utf8.Buffer = ExAllocatePoolWithTag(PagedPool, dc->utf8.MaximumLength, ALLOC_TAG);
2886 if (!dc->utf8.Buffer) {
2887 ERR("out of memory\n");
2888 ExFreePool(dc);
2889 reap_fileref(Vcb, fileref);
2890 free_fileref(parfileref);
2892 }
2893
2894 RtlCopyMemory(dc->utf8.Buffer, &fcb->adsxattr.Buffer[sizeof(xapref) - 1], fcb->adsxattr.Length + 1 - sizeof(xapref));
2895
2896 dc->name.MaximumLength = dc->name.Length = stream->Length;
2897 dc->name.Buffer = ExAllocatePoolWithTag(pool_type, dc->name.MaximumLength, ALLOC_TAG);
2898 if (!dc->name.Buffer) {
2899 ERR("out of memory\n");
2900 ExFreePool(dc->utf8.Buffer);
2901 ExFreePool(dc);
2902 reap_fileref(Vcb, fileref);
2903 free_fileref(parfileref);
2905 }
2906
2907 RtlCopyMemory(dc->name.Buffer, stream->Buffer, stream->Length);
2908
2909 Status = RtlUpcaseUnicodeString(&dc->name_uc, &dc->name, true);
2910 if (!NT_SUCCESS(Status)) {
2911 ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
2912 ExFreePool(dc->utf8.Buffer);
2913 ExFreePool(dc->name.Buffer);
2914 ExFreePool(dc);
2915 reap_fileref(Vcb, fileref);
2916 free_fileref(parfileref);
2917 return Status;
2918 }
2919
2922
2923 ExAcquireResourceExclusiveLite(&parfileref->fcb->nonpaged->dir_children_lock, true);
2924
2925 LIST_ENTRY* le = parfileref->fcb->dir_children_index.Flink;
2926 while (le != &parfileref->fcb->dir_children_index) {
2927 dir_child* dc2 = CONTAINING_RECORD(le, dir_child, list_entry_index);
2928
2929 if (dc2->index == 0) {
2930 if ((case_sensitive && dc2->name.Length == dc->name.Length && RtlCompareMemory(dc2->name.Buffer, dc->name.Buffer, dc2->name.Length) == dc2->name.Length) ||
2931 (!case_sensitive && dc2->name_uc.Length == dc->name_uc.Length && RtlCompareMemory(dc2->name_uc.Buffer, dc->name_uc.Buffer, dc2->name_uc.Length) == dc2->name_uc.Length)
2932 ) {
2933 existing_dc = dc2;
2934 break;
2935 }
2936 } else
2937 break;
2938
2939 le = le->Flink;
2940 }
2941
2942 if (existing_dc) {
2943 ExFreePool(dc->utf8.Buffer);
2944 ExFreePool(dc->name.Buffer);
2945 ExFreePool(dc);
2946 reap_fileref(Vcb, fileref);
2947 free_fileref(parfileref);
2948
2949 increase_fileref_refcount(existing_dc->fileref);
2950 *pfileref = existing_dc->fileref;
2951
2953 }
2954
2955 dc->fileref = fileref;
2956 fileref->dc = dc;
2957 fileref->parent = (struct _file_ref*)parfileref;
2958 fcb->deleted = false;
2959
2960 InsertHeadList(&parfileref->fcb->dir_children_index, &dc->list_entry_index);
2961
2962 InsertTailList(&parfileref->children, &fileref->list_entry);
2963
2964 ExReleaseResourceLite(&parfileref->fcb->nonpaged->dir_children_lock);
2965
2966 mark_fileref_dirty(fileref);
2967
2968 parfileref->fcb->inode_item.transid = Vcb->superblock.generation;
2969 parfileref->fcb->inode_item.sequence++;
2970 parfileref->fcb->inode_item.st_ctime = now;
2971 parfileref->fcb->inode_item_changed = true;
2972
2973 mark_fcb_dirty(parfileref->fcb);
2974
2975 parfileref->fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
2976 parfileref->fcb->subvol->root_item.ctime = now;
2977
2978 increase_fileref_refcount(parfileref);
2979
2980 *pfileref = fileref;
2981
2983
2984 return STATUS_SUCCESS;
2985}
BOOLEAN NTAPI SeAccessCheck(_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext, _In_ BOOLEAN SubjectContextLocked, _In_ ACCESS_MASK DesiredAccess, _In_ ACCESS_MASK PreviouslyGrantedAccess, _Out_ PPRIVILEGE_SET *Privileges, _In_ PGENERIC_MAPPING GenericMapping, _In_ KPROCESSOR_MODE AccessMode, _Out_ PACCESS_MASK GrantedAccess, _Out_ PNTSTATUS AccessStatus)
Determines whether security access rights can be given to an object depending on the security descrip...
Definition: accesschk.c:1994
#define increase_fileref_refcount(fileref)
Definition: btrfs_drv.h:1739
static __inline FAST_IO_POSSIBLE fast_io_possible(fcb *fcb)
Definition: btrfs_drv.h:1684
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1016
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:989
static string utf16_to_utf8(const wstring_view &utf16)
Definition: main.cpp:670
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1695
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2996
void free_fileref(_Inout_ file_ref *fr)
Definition: btrfs.c:1856
void reap_fileref(device_extension *Vcb, file_ref *fr)
Definition: btrfs.c:1875
void free_fcb(_Inout_ fcb *fcb)
Definition: btrfs.c:1734
void mark_fileref_dirty(_In_ file_ref *fileref)
Definition: btrfs.c:1717
void queue_notification_fcb(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1667
NTSTATUS check_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream)
Definition: btrfs.c:5797
void send_notification_fileref(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1517
void reap_fcb(fcb *fcb)
Definition: btrfs.c:1743
#define TYPE_XATTR_ITEM
Definition: btrfs.h:26
static NTSTATUS file_create2(_In_ PIRP Irp, _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension *Vcb, _In_ PUNICODE_STRING fpus, _In_ file_ref *parfileref, _In_ ULONG options, _In_reads_bytes_opt_(ealen) FILE_FULL_EA_INFORMATION *ea, _In_ ULONG ealen, _Out_ file_ref **pfr, bool case_sensitive, _In_ LIST_ENTRY *rollback)
Definition: create.c:2182
NTSTATUS open_fileref(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension *Vcb, _Out_ file_ref **pfr, _In_ PUNICODE_STRING fnus, _In_opt_ file_ref *related, _In_ bool parent, _Out_opt_ USHORT *parsed, _Out_opt_ ULONG *fn_offset, _In_ POOL_TYPE pooltype, _In_ bool case_sensitive, _In_opt_ PIRP Irp)
Definition: create.c:1690
fcb * create_fcb(device_extension *Vcb, POOL_TYPE pool_type)
Definition: create.c:91
file_ref * create_fileref(device_extension *Vcb)
Definition: create.c:160
#define InsertHeadList(ListHead, Entry)
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
time_t now
Definition: finger.c:65
__u16 time
Definition: mkdosfs.c:8
#define uint16_t
Definition: nsiface.idl:60
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define FILE_ADD_SUBDIRECTORY
Definition: nt_native.h:635
#define FILE_ADD_FILE
Definition: nt_native.h:632
PGENERIC_MAPPING NTAPI IoGetFileObjectGenericMapping(VOID)
Definition: file.c:3267
#define L(x)
Definition: ntvdm.h:50
#define BTRFS_TYPE_FILE
Definition: shellext.h:85
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:91
uint64_t sequence
Definition: btrfs.h:299
BTRFS_TIME st_ctime
Definition: btrfs.h:302
uint64_t transid
Definition: btrfs.h:288
Definition: btrfs.h:143
uint8_t obj_type
Definition: btrfs.h:145
uint64_t obj_id
Definition: btrfs.h:144
uint64_t offset
Definition: btrfs.h:146
USHORT MaximumLength
Definition: env_spec_w32.h:377
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
USHORT MaximumLength
Definition: env_spec_w32.h:370
bool ads
Definition: btrfs_drv.h:330
LIST_ENTRY list_entry_all
Definition: btrfs_drv.h:337
ULONG atts
Definition: btrfs_drv.h:297
bool deleted
Definition: btrfs_drv.h:295
uint64_t inode
Definition: btrfs_drv.h:289
SECURITY_DESCRIPTOR * sd
Definition: btrfs_drv.h:293
ANSI_STRING adsxattr
Definition: btrfs_drv.h:333
INODE_ITEM inode_item
Definition: btrfs_drv.h:292
bool created
Definition: btrfs_drv.h:328
uint8_t type
Definition: btrfs_drv.h:291
struct _root * subvol
Definition: btrfs_drv.h:288
ULONG adsmaxlen
Definition: btrfs_drv.h:332
LIST_ENTRY list_entry
Definition: btrfs_drv.h:336
uint32_t hash
Definition: btrfs_drv.h:290
uint32_t adshash
Definition: btrfs_drv.h:331
bool inode_item_changed
Definition: btrfs_drv.h:306
struct _file_ref * parent
Definition: btrfs_drv.h:352
fcb * fcb
Definition: btrfs_drv.h:342
dir_child * dc
Definition: btrfs_drv.h:353
LIST_ENTRY list_entry
Definition: btrfs_drv.h:357
uint16_t size
Definition: btrfs_drv.h:414
UNICODE_STRING name
Definition: btrfs_drv.h:256
UNICODE_STRING name_uc
Definition: btrfs_drv.h:258
struct _file_ref * fileref
Definition: btrfs_drv.h:260
Definition: parse.h:23
tree_data * item
Definition: btrfs_drv.h:509
VOID NTAPI SeLockSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Locks both the referenced primary and client access tokens of a security subject context.
Definition: subject.c:107
VOID NTAPI SeUnlockSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Unlocks both the referenced primary and client access tokens of a security subject context.
Definition: subject.c:138
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
#define FILE_ACTION_MODIFIED
#define FILE_NOTIFY_CHANGE_STREAM_NAME
#define FILE_NOTIFY_CHANGE_FILE_NAME
#define FILE_ACTION_ADDED_STREAM
#define FILE_NOTIFY_CHANGE_LAST_WRITE
#define FILE_ACTION_ADDED
#define FILE_NOTIFY_CHANGE_DIR_NAME

Referenced by file_create().

◆ debug_create_options()

static __inline void debug_create_options ( ULONG  RequestedOptions)
static

Definition at line 3300 of file create.c.

3300 {
3301 if (RequestedOptions != 0) {
3302 ULONG options = RequestedOptions;
3303
3304 TRACE("requested options:\n");
3305
3307 TRACE(" FILE_DIRECTORY_FILE\n");
3308 options &= ~FILE_DIRECTORY_FILE;
3309 }
3310
3312 TRACE(" FILE_WRITE_THROUGH\n");
3313 options &= ~FILE_WRITE_THROUGH;
3314 }
3315
3317 TRACE(" FILE_SEQUENTIAL_ONLY\n");
3318 options &= ~FILE_SEQUENTIAL_ONLY;
3319 }
3320
3322 TRACE(" FILE_NO_INTERMEDIATE_BUFFERING\n");
3323 options &= ~FILE_NO_INTERMEDIATE_BUFFERING;
3324 }
3325
3327 TRACE(" FILE_SYNCHRONOUS_IO_ALERT\n");
3328 options &= ~FILE_SYNCHRONOUS_IO_ALERT;
3329 }
3330
3332 TRACE(" FILE_SYNCHRONOUS_IO_NONALERT\n");
3333 options &= ~FILE_SYNCHRONOUS_IO_NONALERT;
3334 }
3335
3337 TRACE(" FILE_NON_DIRECTORY_FILE\n");
3338 options &= ~FILE_NON_DIRECTORY_FILE;
3339 }
3340
3342 TRACE(" FILE_CREATE_TREE_CONNECTION\n");
3343 options &= ~FILE_CREATE_TREE_CONNECTION;
3344 }
3345
3347 TRACE(" FILE_COMPLETE_IF_OPLOCKED\n");
3348 options &= ~FILE_COMPLETE_IF_OPLOCKED;
3349 }
3350
3352 TRACE(" FILE_NO_EA_KNOWLEDGE\n");
3353 options &= ~FILE_NO_EA_KNOWLEDGE;
3354 }
3355
3357 TRACE(" FILE_OPEN_REMOTE_INSTANCE\n");
3358 options &= ~FILE_OPEN_REMOTE_INSTANCE;
3359 }
3360
3362 TRACE(" FILE_RANDOM_ACCESS\n");
3363 options &= ~FILE_RANDOM_ACCESS;
3364 }
3365
3367 TRACE(" FILE_DELETE_ON_CLOSE\n");
3368 options &= ~FILE_DELETE_ON_CLOSE;
3369 }
3370
3372 TRACE(" FILE_OPEN_BY_FILE_ID\n");
3373 options &= ~FILE_OPEN_BY_FILE_ID;
3374 }
3375
3377 TRACE(" FILE_OPEN_FOR_BACKUP_INTENT\n");
3378 options &= ~FILE_OPEN_FOR_BACKUP_INTENT;
3379 }
3380
3382 TRACE(" FILE_NO_COMPRESSION\n");
3383 options &= ~FILE_NO_COMPRESSION;
3384 }
3385
3386#if NTDDI_VERSION >= NTDDI_WIN7
3388 TRACE(" FILE_OPEN_REQUIRING_OPLOCK\n");
3389 options &= ~FILE_OPEN_REQUIRING_OPLOCK;
3390 }
3391
3393 TRACE(" FILE_DISALLOW_EXCLUSIVE\n");
3394 options &= ~FILE_DISALLOW_EXCLUSIVE;
3395 }
3396#endif
3397
3399 TRACE(" FILE_RESERVE_OPFILTER\n");
3400 options &= ~FILE_RESERVE_OPFILTER;
3401 }
3402
3404 TRACE(" FILE_OPEN_REPARSE_POINT\n");
3405 options &= ~FILE_OPEN_REPARSE_POINT;
3406 }
3407
3409 TRACE(" FILE_OPEN_NO_RECALL\n");
3410 options &= ~FILE_OPEN_NO_RECALL;
3411 }
3412
3414 TRACE(" FILE_OPEN_FOR_FREE_SPACE_QUERY\n");
3415 options &= ~FILE_OPEN_FOR_FREE_SPACE_QUERY;
3416 }
3417
3418 if (options)
3419 TRACE(" unknown options: %lx\n", options);
3420 } else {
3421 TRACE("requested options: (none)\n");
3422 }
3423}
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
#define FILE_OPEN_FOR_FREE_SPACE_QUERY
Definition: constants.h:495
#define FILE_COMPLETE_IF_OPLOCKED
Definition: constants.h:493
#define FILE_DELETE_ON_CLOSE
Definition: constants.h:494
#define FILE_OPEN_BY_FILE_ID
Definition: from_kernel.h:41
#define FILE_NO_COMPRESSION
Definition: from_kernel.h:43
#define FILE_OPEN_REPARSE_POINT
Definition: from_kernel.h:46
#define FILE_NO_EA_KNOWLEDGE
Definition: from_kernel.h:36
#define FILE_RESERVE_OPFILTER
Definition: from_kernel.h:45
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
#define FILE_NO_INTERMEDIATE_BUFFERING
Definition: from_kernel.h:28
#define FILE_RANDOM_ACCESS
Definition: from_kernel.h:38
#define FILE_WRITE_THROUGH
Definition: from_kernel.h:26
#define FILE_OPEN_NO_RECALL
Definition: from_kernel.h:47
#define FILE_SEQUENTIAL_ONLY
Definition: from_kernel.h:27
#define FILE_SYNCHRONOUS_IO_ALERT
Definition: from_kernel.h:30
#define FILE_OPEN_REMOTE_INSTANCE
Definition: from_kernel.h:37
#define FILE_CREATE_TREE_CONNECTION
Definition: from_kernel.h:33
#define FILE_OPEN_FOR_BACKUP_INTENT
Definition: from_kernel.h:42
#define FILE_OPEN_REQUIRING_OPLOCK
Definition: winternl.h:186
#define FILE_DISALLOW_EXCLUSIVE

Referenced by open_file().

◆ fcb_load_csums()

static void fcb_load_csums ( _Requires_lock_held_(_Curr_->tree_lock) device_extension Vcb,
fcb fcb,
PIRP  Irp 
)
static

Definition at line 3547 of file create.c.

3547 {
3548 LIST_ENTRY* le;
3550
3551 if (fcb->csum_loaded)
3552 return;
3553
3555 goto end;
3556
3557 le = fcb->extents.Flink;
3558 while (le != &fcb->extents) {
3560
3561 if (!ext->ignore && ext->extent_data.type == EXTENT_TYPE_REGULAR) {
3562 EXTENT_DATA2* ed2 = (EXTENT_DATA2*)&ext->extent_data.data[0];
3563 uint64_t len;
3564
3565 len = (ext->extent_data.compression == BTRFS_COMPRESSION_NONE ? ed2->num_bytes : ed2->size) >> Vcb->sector_shift;
3566
3567 ext->csum = ExAllocatePoolWithTag(NonPagedPool, (ULONG)(len * Vcb->csum_size), ALLOC_TAG);
3568 if (!ext->csum) {
3569 ERR("out of memory\n");
3570 goto end;
3571 }
3572
3573 Status = load_csum(Vcb, ext->csum, ed2->address + (ext->extent_data.compression == BTRFS_COMPRESSION_NONE ? ed2->offset : 0), len, Irp);
3574
3575 if (!NT_SUCCESS(Status)) {
3576 ERR("load_csum returned %08lx\n", Status);
3577 goto end;
3578 }
3579 }
3580
3581 le = le->Flink;
3582 }
3583
3584end:
3585 fcb->csum_loaded = true;
3586}
UINT64 uint64_t
Definition: types.h:77
static const WCHAR *const ext[]
Definition: module.c:53
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:75
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:65
NTSTATUS load_csum(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, void *csum, uint64_t start, uint64_t length, PIRP Irp)
Definition: create.c:453
GLuint GLuint end
Definition: gl.h:1545
GLenum GLsizei len
Definition: glext.h:6722
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
uint64_t num_bytes
Definition: btrfs.h:371
uint64_t address
Definition: btrfs.h:368
uint64_t size
Definition: btrfs.h:369
uint64_t offset
Definition: btrfs.h:370
uint32_t flags
Definition: btrfs.h:297
bool csum_loaded
Definition: btrfs_drv.h:299
Definition: list.h:27

Referenced by open_file(), and oplock_complete().

◆ file_create()

static NTSTATUS file_create ( PIRP  Irp,
_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension Vcb,
PFILE_OBJECT  FileObject,
file_ref related,
bool  loaded_related,
PUNICODE_STRING  fnus,
ULONG  disposition,
ULONG  options,
file_ref **  existing_fileref,
LIST_ENTRY rollback 
)
static

Definition at line 3007 of file create.c.

3009 {
3011 file_ref *fileref, *parfileref = NULL;
3012 ULONG i, j;
3013 ccb* ccb;
3014 static const WCHAR datasuf[] = {':','$','D','A','T','A',0};
3015 UNICODE_STRING dsus, fpus, stream;
3018 ECP_LIST* ecp_list;
3020#ifdef DEBUG_FCB_REFCOUNTS
3021 LONG oc;
3022#endif
3023
3024 TRACE("(%p, %p, %p, %.*S, %lx, %lx)\n", Irp, Vcb, FileObject, (int)(fnus->Length / sizeof(WCHAR)), fnus->Buffer, disposition, options);
3025
3026 if (Vcb->readonly)
3028
3031 return STATUS_CANNOT_DELETE;
3032 }
3033
3035 if (NT_SUCCESS(fFsRtlGetEcpListFromIrp(Irp, &ecp_list)) && ecp_list) {
3036 void* ctx = NULL;
3037 GUID type;
3038 ULONG ctxsize;
3039
3040 do {
3041 Status = fFsRtlGetNextExtraCreateParameter(ecp_list, ctx, &type, &ctx, &ctxsize);
3042
3043 if (NT_SUCCESS(Status)) {
3044 if (RtlCompareMemory(&type, &GUID_ECP_ATOMIC_CREATE, sizeof(GUID)) == sizeof(GUID)) {
3045 if (ctxsize >= sizeof(ATOMIC_CREATE_ECP_CONTEXT))
3046 acec = ctx;
3047 else {
3048 ERR("GUID_ECP_ATOMIC_CREATE context was too short: %lu bytes, expected %Iu\n", ctxsize,
3050 }
3051 } else if (RtlCompareMemory(&type, &GUID_ECP_QUERY_ON_CREATE, sizeof(GUID)) == sizeof(GUID))
3052 WARN("unhandled ECP GUID_ECP_QUERY_ON_CREATE\n");
3053 else if (RtlCompareMemory(&type, &GUID_ECP_CREATE_REDIRECTION, sizeof(GUID)) == sizeof(GUID))
3054 WARN("unhandled ECP GUID_ECP_CREATE_REDIRECTION\n");
3055 else {
3056 WARN("unhandled ECP {%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n", type.Data1, type.Data2,
3057 type.Data3, type.Data4[0], type.Data4[1], type.Data4[2], type.Data4[3], type.Data4[4], type.Data4[5],
3058 type.Data4[6], type.Data4[7]);
3059 }
3060 }
3061 } while (NT_SUCCESS(Status));
3062 }
3063 }
3064
3065 dsus.Buffer = (WCHAR*)datasuf;
3066 dsus.Length = dsus.MaximumLength = sizeof(datasuf) - sizeof(WCHAR);
3067 fpus.Buffer = NULL;
3068
3069 if (!loaded_related) {
3070 Status = open_fileref(Vcb, &parfileref, fnus, related, true, NULL, NULL, pool_type, IrpSp->Flags & SL_CASE_SENSITIVE, Irp);
3071
3072 if (!NT_SUCCESS(Status))
3073 goto end;
3074 } else
3075 parfileref = related;
3076
3077 if (parfileref->fcb->type != BTRFS_TYPE_DIRECTORY && (fnus->Length < sizeof(WCHAR) || fnus->Buffer[0] != ':')) {
3079 goto end;
3080 }
3081
3082 if (is_subvol_readonly(parfileref->fcb->subvol, Irp)) {
3084 goto end;
3085 }
3086
3087 i = (fnus->Length / sizeof(WCHAR))-1;
3088 while ((fnus->Buffer[i] == '\\' || fnus->Buffer[i] == '/') && i > 0) { i--; }
3089
3090 j = i;
3091
3092 while (i > 0 && fnus->Buffer[i-1] != '\\' && fnus->Buffer[i-1] != '/') { i--; }
3093
3094 fpus.MaximumLength = (USHORT)((j - i + 2) * sizeof(WCHAR));
3095 fpus.Buffer = ExAllocatePoolWithTag(pool_type, fpus.MaximumLength, ALLOC_TAG);
3096 if (!fpus.Buffer) {
3097 ERR("out of memory\n");
3099 goto end;
3100 }
3101
3102 fpus.Length = (USHORT)((j - i + 1) * sizeof(WCHAR));
3103
3104 RtlCopyMemory(fpus.Buffer, &fnus->Buffer[i], (j - i + 1) * sizeof(WCHAR));
3105 fpus.Buffer[j - i + 1] = 0;
3106
3107 if (fpus.Length > dsus.Length) { // check for :$DATA suffix
3108 UNICODE_STRING lb;
3109
3110 lb.Buffer = &fpus.Buffer[(fpus.Length - dsus.Length)/sizeof(WCHAR)];
3111 lb.Length = lb.MaximumLength = dsus.Length;
3112
3113 TRACE("lb = %.*S\n", (int)(lb.Length/sizeof(WCHAR)), lb.Buffer);
3114
3115 if (FsRtlAreNamesEqual(&dsus, &lb, true, NULL)) {
3116 TRACE("ignoring :$DATA suffix\n");
3117
3118 fpus.Length -= lb.Length;
3119
3120 if (fpus.Length > sizeof(WCHAR) && fpus.Buffer[(fpus.Length-1)/sizeof(WCHAR)] == ':')
3121 fpus.Length -= sizeof(WCHAR);
3122
3123 TRACE("fpus = %.*S\n", (int)(fpus.Length / sizeof(WCHAR)), fpus.Buffer);
3124 }
3125 }
3126
3127 stream.Length = 0;
3128
3129 for (i = 0; i < fpus.Length / sizeof(WCHAR); i++) {
3130 if (fpus.Buffer[i] == ':') {
3131 stream.Length = (USHORT)(fpus.Length - (i * sizeof(WCHAR)) - sizeof(WCHAR));
3132 stream.Buffer = &fpus.Buffer[i+1];
3133 fpus.Buffer[i] = 0;
3134 fpus.Length = (USHORT)(i * sizeof(WCHAR));
3135 break;
3136 }
3137 }
3138
3139 if (stream.Length > 0) {
3140 Status = create_stream(Vcb, &fileref, &parfileref, &fpus, &stream, Irp, options, pool_type, IrpSp->Flags & SL_CASE_SENSITIVE, rollback);
3141 if (!NT_SUCCESS(Status)) {
3142 ERR("create_stream returned %08lx\n", Status);
3143 goto end;
3144 }
3145
3146 IoSetShareAccess(IrpSp->Parameters.Create.SecurityContext->DesiredAccess, IrpSp->Parameters.Create.ShareAccess,
3147 FileObject, &fileref->fcb->share_access);
3148 } else {
3149 ACCESS_MASK granted_access;
3150
3151 Status = check_file_name_valid(&fpus, false, false);
3152 if (!NT_SUCCESS(Status))
3153 goto end;
3154
3155 SeLockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext);
3156
3157 if (!SeAccessCheck(parfileref->fcb->sd, &IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext,
3160 &granted_access, &Status)) {
3161 SeUnlockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext);
3162 goto end;
3163 }
3164
3165 SeUnlockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext);
3166
3167 if (Irp->AssociatedIrp.SystemBuffer && IrpSp->Parameters.Create.EaLength > 0) {
3168 ULONG offset;
3169
3170 Status = IoCheckEaBufferValidity(Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.Create.EaLength, &offset);
3171 if (!NT_SUCCESS(Status)) {
3172 ERR("IoCheckEaBufferValidity returned %08lx (error at offset %lu)\n", Status, offset);
3173 goto end;
3174 }
3175 }
3176
3177 Status = file_create2(Irp, Vcb, &fpus, parfileref, options, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.Create.EaLength,
3178 &fileref, IrpSp->Flags & SL_CASE_SENSITIVE, rollback);
3179
3181 *existing_fileref = fileref;
3182 goto end;
3183 } else if (!NT_SUCCESS(Status)) {
3184 ERR("file_create2 returned %08lx\n", Status);
3185 goto end;
3186 }
3187
3188 IoSetShareAccess(IrpSp->Parameters.Create.SecurityContext->DesiredAccess, IrpSp->Parameters.Create.ShareAccess, FileObject, &fileref->fcb->share_access);
3189
3192 }
3193
3194 FileObject->FsContext = fileref->fcb;
3195
3197 if (!ccb) {
3198 ERR("out of memory\n");
3200 fileref->deleted = true;
3201 fileref->fcb->deleted = true;
3202
3203 if (stream.Length == 0) {
3204 ExAcquireResourceExclusiveLite(parfileref->fcb->Header.Resource, true);
3205 parfileref->fcb->inode_item.st_size -= fileref->dc->utf8.Length * 2;
3206 ExReleaseResourceLite(parfileref->fcb->Header.Resource);
3207 }
3208
3209 free_fileref(fileref);
3210 goto end;
3211 }
3212
3213 RtlZeroMemory(ccb, sizeof(*ccb));
3214
3215 ccb->fileref = fileref;
3216
3218 ccb->NodeSize = sizeof(*ccb);
3219 ccb->disposition = disposition;
3220 ccb->options = options;
3221 ccb->query_dir_offset = 0;
3223 ccb->has_wildcard = false;
3224 ccb->specific_file = false;
3225 ccb->access = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
3227 ccb->reserving = false;
3229
3230#ifdef DEBUG_FCB_REFCOUNTS
3231 oc = InterlockedIncrement(&fileref->open_count);
3232 ERR("fileref %p: open_count now %i\n", fileref, oc);
3233#else
3235#endif
3236 InterlockedIncrement(&Vcb->open_files);
3237
3238 FileObject->FsContext2 = ccb;
3239
3240 FileObject->SectionObjectPointer = &fileref->fcb->nonpaged->segment_object;
3241
3242 // FIXME - ATOMIC_CREATE_ECP_IN_FLAG_BEST_EFFORT
3244 if (acec->ReparseBufferLength > sizeof(uint32_t) && *(uint32_t*)acec->ReparseBuffer == IO_REPARSE_TAG_SYMLINK) {
3246 fileref->fcb->type = BTRFS_TYPE_FILE;
3247 fileref->fcb->atts &= ~FILE_ATTRIBUTE_DIRECTORY;
3248 }
3249
3250 if (fileref->fcb->type == BTRFS_TYPE_SOCKET || fileref->fcb->type == BTRFS_TYPE_FIFO ||
3251 fileref->fcb->type == BTRFS_TYPE_CHARDEV || fileref->fcb->type == BTRFS_TYPE_BLOCKDEV) {
3252 // NOP. If called from LXSS, humour it - we hardcode the values elsewhere.
3253 } else {
3255 if (!NT_SUCCESS(Status)) {
3256 ERR("set_reparse_point2 returned %08lx\n", Status);
3257 fileref->deleted = true;
3258 fileref->fcb->deleted = true;
3259
3260 if (stream.Length == 0) {
3261 ExAcquireResourceExclusiveLite(parfileref->fcb->Header.Resource, true);
3262 parfileref->fcb->inode_item.st_size -= fileref->dc->utf8.Length * 2;
3263 ExReleaseResourceLite(parfileref->fcb->Header.Resource);
3264 }
3265
3266 free_fileref(fileref);
3267 return Status;
3268 }
3269 }
3270
3272 }
3273
3278 fileref->fcb->case_sensitive = true;
3279 ccb->case_sensitive = true;
3280 }
3281
3283 }
3284
3286 }
3287
3288 fileref->dc->type = fileref->fcb->type;
3289
3290end:
3291 if (fpus.Buffer)
3292 ExFreePool(fpus.Buffer);
3293
3294 if (parfileref && !loaded_related)
3295 free_fileref(parfileref);
3296
3297 return Status;
3298}
#define FILE_CS_FLAG_CASE_SENSITIVE_DIR
Definition: btrfs_drv.h:165
#define __S_IFSOCK
Definition: btrfs_drv.h:1760
NTSTATUS set_reparse_point2(fcb *fcb, REPARSE_DATA_BUFFER *rdb, ULONG buflen, ccb *ccb, file_ref *fileref, PIRP Irp, LIST_ENTRY *rollback)
Definition: reparse.c:307
#define __S_IFIFO
Definition: btrfs_drv.h:1758
#define __S_IFBLK
Definition: btrfs_drv.h:1756
static __inline bool is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:1033
#define __S_IFCHR
Definition: btrfs_drv.h:1755
#define ATOMIC_CREATE_ECP_OUT_FLAG_OP_FLAGS_HONORED
Definition: create.c:41
static const GUID GUID_ECP_ATOMIC_CREATE
Definition: create.c:79
#define ATOMIC_CREATE_ECP_IN_OP_FLAG_CASE_SENSITIVE_FLAGS_SPECIFIED
Definition: create.c:43
#define ATOMIC_CREATE_ECP_OUT_OP_FLAG_CASE_SENSITIVE_FLAGS_SET
Definition: create.c:44
#define ATOMIC_CREATE_ECP_IN_FLAG_REPARSE_POINT_SPECIFIED
Definition: create.c:36
static NTSTATUS create_stream(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, file_ref **pfileref, file_ref **pparfileref, PUNICODE_STRING fpus, PUNICODE_STRING stream, PIRP Irp, ULONG options, POOL_TYPE pool_type, bool case_sensitive, LIST_ENTRY *rollback)
Definition: create.c:2640
static const GUID GUID_ECP_QUERY_ON_CREATE
Definition: create.c:80
tFsRtlGetEcpListFromIrp fFsRtlGetEcpListFromIrp
Definition: btrfs.c:96
#define ATOMIC_CREATE_ECP_IN_FLAG_OP_FLAGS_SPECIFIED
Definition: create.c:37
tFsRtlGetNextExtraCreateParameter fFsRtlGetNextExtraCreateParameter
Definition: btrfs.c:97
#define ATOMIC_CREATE_ECP_OUT_FLAG_REPARSE_POINT_SET
Definition: create.c:40
static const GUID GUID_ECP_CREATE_REDIRECTION
Definition: create.c:81
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
BOOLEAN NTAPI FsRtlAreNamesEqual(IN PCUNICODE_STRING Name1, IN PCUNICODE_STRING Name2, IN BOOLEAN IgnoreCase, IN PCWCH UpcaseTable OPTIONAL)
Definition: name.c:296
VOID NTAPI IoSetShareAccess(IN ACCESS_MASK DesiredAccess, IN ULONG DesiredShareAccess, IN PFILE_OBJECT FileObject, OUT PSHARE_ACCESS ShareAccess)
Definition: file.c:3517
NTSTATUS NTAPI IoCheckEaBufferValidity(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: util.c:191
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_CANNOT_DELETE
Definition: shellext.h:71
#define BTRFS_TYPE_SOCKET
Definition: shellext.h:90
#define BTRFS_TYPE_FIFO
Definition: shellext.h:89
#define BTRFS_TYPE_CHARDEV
Definition: shellext.h:87
#define BTRFS_TYPE_BLOCKDEV
Definition: shellext.h:88
uint32_t st_mode
Definition: btrfs.h:295
uint64_t st_size
Definition: btrfs.h:289
PREPARSE_DATA_BUFFER ReparseBuffer
Definition: create.c:62
uint64_t query_dir_offset
Definition: btrfs_drv.h:375
UNICODE_STRING query_string
Definition: btrfs_drv.h:376
bool specific_file
Definition: btrfs_drv.h:378
file_ref * fileref
Definition: btrfs_drv.h:383
bool case_sensitive
Definition: btrfs_drv.h:386
bool has_wildcard
Definition: btrfs_drv.h:377
bool case_sensitive
Definition: btrfs_drv.h:310
SHARE_ACCESS share_access
Definition: btrfs_drv.h:298
bool deleted
Definition: btrfs_drv.h:347
LONG open_count
Definition: btrfs_drv.h:351
ANSI_STRING utf8
Definition: btrfs_drv.h:254
uint8_t type
Definition: btrfs_drv.h:253
INT POOL_TYPE
Definition: typedefs.h:78
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define STATUS_OBJECT_PATH_NOT_FOUND
Definition: udferr_usr.h:151
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
#define IO_REPARSE_TAG_SYMLINK
Definition: iotypes.h:7240

Referenced by open_file().

◆ file_create2()

static NTSTATUS file_create2 ( _In_ PIRP  Irp,
_Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension Vcb,
_In_ PUNICODE_STRING  fpus,
_In_ file_ref parfileref,
_In_ ULONG  options,
_In_reads_bytes_opt_(ealen) FILE_FULL_EA_INFORMATION ea,
_In_ ULONG  ealen,
_Out_ file_ref **  pfr,
bool  case_sensitive,
_In_ LIST_ENTRY rollback 
)
static

Definition at line 2182 of file create.c.

2184 {
2186 fcb* fcb;
2187 ULONG utf8len;
2188 char* utf8 = NULL;
2190 uint8_t type;
2195 USHORT defda;
2196 file_ref* fileref;
2197 dir_child* dc;
2198 ANSI_STRING utf8as;
2199 LIST_ENTRY* lastle = NULL;
2200 file_ref* existing_fileref = NULL;
2201#ifdef DEBUG_FCB_REFCOUNTS
2202 LONG rc;
2203#endif
2204
2205 if (parfileref->fcb == Vcb->dummy_fcb)
2206 return STATUS_ACCESS_DENIED;
2207
2210
2211 Status = utf16_to_utf8(NULL, 0, &utf8len, fpus->Buffer, fpus->Length);
2212 if (!NT_SUCCESS(Status)) {
2213 ERR("utf16_to_utf8 returned %08lx\n", Status);
2214 return Status;
2215 }
2216
2217 utf8 = ExAllocatePoolWithTag(pool_type, utf8len + 1, ALLOC_TAG);
2218 if (!utf8) {
2219 ERR("out of memory\n");
2221 }
2222
2223 Status = utf16_to_utf8(utf8, utf8len, &utf8len, fpus->Buffer, fpus->Length);
2224 if (!NT_SUCCESS(Status)) {
2225 ERR("utf16_to_utf8 returned %08lx\n", Status);
2226 ExFreePool(utf8);
2227 return Status;
2228 }
2229
2230 utf8[utf8len] = 0;
2231
2234
2235 TRACE("create file %.*S\n", (int)(fpus->Length / sizeof(WCHAR)), fpus->Buffer);
2236 ExAcquireResourceExclusiveLite(parfileref->fcb->Header.Resource, true);
2237 TRACE("parfileref->fcb->inode_item.st_size (inode %I64x) was %I64x\n", parfileref->fcb->inode, parfileref->fcb->inode_item.st_size);
2238 parfileref->fcb->inode_item.st_size += utf8len * 2;
2239 TRACE("parfileref->fcb->inode_item.st_size (inode %I64x) now %I64x\n", parfileref->fcb->inode, parfileref->fcb->inode_item.st_size);
2240 parfileref->fcb->inode_item.transid = Vcb->superblock.generation;
2241 parfileref->fcb->inode_item.sequence++;
2242 parfileref->fcb->inode_item.st_ctime = now;
2243 parfileref->fcb->inode_item.st_mtime = now;
2244 ExReleaseResourceLite(parfileref->fcb->Header.Resource);
2245
2246 parfileref->fcb->inode_item_changed = true;
2247 mark_fcb_dirty(parfileref->fcb);
2248
2249 inode = InterlockedIncrement64(&parfileref->fcb->subvol->lastinode);
2250
2252
2253 // FIXME - link FILE_ATTRIBUTE_READONLY to st_mode
2254
2255 TRACE("requested attributes = %x\n", IrpSp->Parameters.Create.FileAttributes);
2256
2257 defda = 0;
2258
2259 if (utf8[0] == '.')
2260 defda |= FILE_ATTRIBUTE_HIDDEN;
2261
2263 defda |= FILE_ATTRIBUTE_DIRECTORY;
2265 } else
2266 IrpSp->Parameters.Create.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
2267
2268 if (!(IrpSp->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
2269 IrpSp->Parameters.Create.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
2270 defda |= FILE_ATTRIBUTE_ARCHIVE;
2271 }
2272
2273 TRACE("defda = %x\n", defda);
2274
2275 if (IrpSp->Parameters.Create.FileAttributes == FILE_ATTRIBUTE_NORMAL)
2276 IrpSp->Parameters.Create.FileAttributes = defda;
2277
2278 fcb = create_fcb(Vcb, pool_type);
2279 if (!fcb) {
2280 ERR("out of memory\n");
2281 ExFreePool(utf8);
2282
2283 ExAcquireResourceExclusiveLite(parfileref->fcb->Header.Resource, true);
2284 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2285 ExReleaseResourceLite(parfileref->fcb->Header.Resource);
2286
2288 }
2289
2290 fcb->Vcb = Vcb;
2291
2294
2295 fcb->inode_item.generation = Vcb->superblock.generation;
2296 fcb->inode_item.transid = Vcb->superblock.generation;
2297 fcb->inode_item.st_size = 0;
2300 fcb->inode_item.st_nlink = 1;
2301 fcb->inode_item.st_gid = GID_NOBODY; // FIXME?
2302 fcb->inode_item.st_mode = inherit_mode(parfileref->fcb, type == BTRFS_TYPE_DIRECTORY); // use parent's permissions by default
2303 fcb->inode_item.st_rdev = 0;
2304 fcb->inode_item.flags = 0;
2305 fcb->inode_item.sequence = 1;
2310
2313 else {
2315 fcb->inode_item.st_mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH); // remove executable bit if not directory
2316 }
2317
2320 } else {
2321 // inherit nodatacow flag from parent directory
2322 if (parfileref->fcb->inode_item.flags & BTRFS_INODE_NODATACOW || Vcb->options.nodatacow) {
2324
2327 }
2328
2329 if (parfileref->fcb->inode_item.flags & BTRFS_INODE_COMPRESS &&
2332 }
2333 }
2334
2336 fcb->prop_compression = parfileref->fcb->prop_compression;
2338 } else
2340
2341 fcb->inode_item_changed = true;
2342
2343 fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
2344 fcb->Header.AllocationSize.QuadPart = 0;
2345 fcb->Header.FileSize.QuadPart = 0;
2346 fcb->Header.ValidDataLength.QuadPart = 0;
2347
2348 fcb->atts = IrpSp->Parameters.Create.FileAttributes & ~FILE_ATTRIBUTE_NORMAL;
2349 fcb->atts_changed = fcb->atts != defda;
2350
2351#ifdef DEBUG_FCB_REFCOUNTS
2352 rc = InterlockedIncrement(&parfileref->fcb->refcount);
2353 WARN("fcb %p: refcount now %i\n", parfileref->fcb, rc);
2354#else
2355 InterlockedIncrement(&parfileref->fcb->refcount);
2356#endif
2357 fcb->subvol = parfileref->fcb->subvol;
2358 fcb->inode = inode;
2359 fcb->type = type;
2360 fcb->created = true;
2361 fcb->deleted = true;
2362
2363 fcb->hash = calc_crc32c(0xffffffff, (uint8_t*)&inode, sizeof(uint64_t));
2364
2365 acquire_fcb_lock_exclusive(Vcb);
2366
2367 if (fcb->subvol->fcbs_ptrs[fcb->hash >> 24]) {
2368 LIST_ENTRY* le = fcb->subvol->fcbs_ptrs[fcb->hash >> 24];
2369
2370 while (le != &fcb->subvol->fcbs) {
2371 struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
2372
2373 if (fcb2->hash > fcb->hash) {
2374 lastle = le->Blink;
2375 break;
2376 }
2377
2378 le = le->Flink;
2379 }
2380 }
2381
2382 if (!lastle) {
2383 uint8_t c = fcb->hash >> 24;
2384
2385 if (c != 0xff) {
2386 uint8_t d = c + 1;
2387
2388 do {
2389 if (fcb->subvol->fcbs_ptrs[d]) {
2390 lastle = fcb->subvol->fcbs_ptrs[d]->Blink;
2391 break;
2392 }
2393
2394 d++;
2395 } while (d != 0);
2396 }
2397 }
2398
2399 if (lastle) {
2400 InsertHeadList(lastle, &fcb->list_entry);
2401
2402 if (lastle == &fcb->subvol->fcbs || (CONTAINING_RECORD(lastle, struct _fcb, list_entry)->hash >> 24) != (fcb->hash >> 24))
2403 fcb->subvol->fcbs_ptrs[fcb->hash >> 24] = &fcb->list_entry;
2404 } else {
2406
2407 if (fcb->list_entry.Blink == &fcb->subvol->fcbs || (CONTAINING_RECORD(fcb->list_entry.Blink, struct _fcb, list_entry)->hash >> 24) != (fcb->hash >> 24))
2408 fcb->subvol->fcbs_ptrs[fcb->hash >> 24] = &fcb->list_entry;
2409 }
2410
2411 InsertTailList(&Vcb->all_fcbs, &fcb->list_entry_all);
2412
2413 fcb->subvol->fcbs_version++;
2414
2415 release_fcb_lock(Vcb);
2416
2418
2419 Status = fcb_get_new_sd(fcb, parfileref, IrpSp->Parameters.Create.SecurityContext->AccessState);
2420
2421 if (!NT_SUCCESS(Status)) {
2422 ERR("fcb_get_new_sd returned %08lx\n", Status);
2423 free_fcb(fcb);
2424
2425 ExAcquireResourceExclusiveLite(parfileref->fcb->Header.Resource, true);
2426 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2427 ExReleaseResourceLite(parfileref->fcb->Header.Resource);
2428
2429 ExFreePool(utf8);
2430
2431 return Status;
2432 }
2433
2434 fcb->sd_dirty = true;
2435
2436 if (ea && ealen > 0) {
2438 if (!NT_SUCCESS(Status)) {
2439 ERR("file_create_parse_ea returned %08lx\n", Status);
2440 free_fcb(fcb);
2441
2442 ExAcquireResourceExclusiveLite(parfileref->fcb->Header.Resource, true);
2443 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2444 ExReleaseResourceLite(parfileref->fcb->Header.Resource);
2445
2446 ExFreePool(utf8);
2447
2448 return Status;
2449 }
2450 }
2451
2453 if (!fileref) {
2454 ERR("out of memory\n");
2455 free_fcb(fcb);
2456
2457 ExAcquireResourceExclusiveLite(parfileref->fcb->Header.Resource, true);
2458 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2459 ExReleaseResourceLite(parfileref->fcb->Header.Resource);
2460
2461 ExFreePool(utf8);
2462
2464 }
2465
2466 fileref->fcb = fcb;
2467
2468 if (Irp->Overlay.AllocationSize.QuadPart > 0 && !write_fcb_compressed(fcb) && fcb->type != BTRFS_TYPE_DIRECTORY) {
2469 Status = extend_file(fcb, fileref, Irp->Overlay.AllocationSize.QuadPart, true, NULL, rollback);
2470
2471 if (!NT_SUCCESS(Status)) {
2472 ERR("extend_file returned %08lx\n", Status);
2474
2475 ExAcquireResourceExclusiveLite(parfileref->fcb->Header.Resource, true);
2476 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2477 ExReleaseResourceLite(parfileref->fcb->Header.Resource);
2478
2479 ExFreePool(utf8);
2480
2481 return Status;
2482 }
2483 }
2484
2485 if (fcb->type == BTRFS_TYPE_DIRECTORY) {
2487 if (!fcb->hash_ptrs) {
2488 ERR("out of memory\n");
2490
2491 ExAcquireResourceExclusiveLite(parfileref->fcb->Header.Resource, true);
2492 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2493 ExReleaseResourceLite(parfileref->fcb->Header.Resource);
2494
2495 ExFreePool(utf8);
2496
2498 }
2499
2500 RtlZeroMemory(fcb->hash_ptrs, sizeof(LIST_ENTRY*) * 256);
2501
2503 if (!fcb->hash_ptrs_uc) {
2504 ERR("out of memory\n");
2506
2507 ExAcquireResourceExclusiveLite(parfileref->fcb->Header.Resource, true);
2508 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2509 ExReleaseResourceLite(parfileref->fcb->Header.Resource);
2510
2511 ExFreePool(utf8);
2512
2514 }
2515
2516 RtlZeroMemory(fcb->hash_ptrs_uc, sizeof(LIST_ENTRY*) * 256);
2517 }
2518
2519 fcb->deleted = false;
2520
2521 fileref->created = true;
2522
2523 fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
2524 fcb->subvol->root_item.ctime = now;
2525
2526 utf8as.Buffer = utf8;
2527 utf8as.Length = utf8as.MaximumLength = (uint16_t)utf8len;
2528
2529 ExAcquireResourceExclusiveLite(&parfileref->fcb->nonpaged->dir_children_lock, true);
2530
2531 // check again doesn't already exist
2532 if (case_sensitive) {
2533 uint32_t dc_hash = calc_crc32c(0xffffffff, (uint8_t*)fpus->Buffer, fpus->Length);
2534
2535 if (parfileref->fcb->hash_ptrs[dc_hash >> 24]) {
2536 LIST_ENTRY* le = parfileref->fcb->hash_ptrs[dc_hash >> 24];
2537 while (le != &parfileref->fcb->dir_children_hash) {
2538 dc = CONTAINING_RECORD(le, dir_child, list_entry_hash);
2539
2540 if (dc->hash == dc_hash && dc->name.Length == fpus->Length && RtlCompareMemory(dc->name.Buffer, fpus->Buffer, fpus->Length) == fpus->Length) {
2541 existing_fileref = dc->fileref;
2542 break;
2543 } else if (dc->hash > dc_hash)
2544 break;
2545
2546 le = le->Flink;
2547 }
2548 }
2549 } else {
2550 UNICODE_STRING fpusuc;
2551
2552 Status = RtlUpcaseUnicodeString(&fpusuc, fpus, true);
2553 if (!NT_SUCCESS(Status)) {
2554 ExReleaseResourceLite(&parfileref->fcb->nonpaged->dir_children_lock);
2555 ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
2557
2558 ExAcquireResourceExclusiveLite(parfileref->fcb->Header.Resource, true);
2559 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2560 ExReleaseResourceLite(parfileref->fcb->Header.Resource);
2561
2562 ExFreePool(utf8);
2563
2564 return Status;
2565 }
2566
2567 uint32_t dc_hash = calc_crc32c(0xffffffff, (uint8_t*)fpusuc.Buffer, fpusuc.Length);
2568
2569 if (parfileref->fcb->hash_ptrs_uc[dc_hash >> 24]) {
2570 LIST_ENTRY* le = parfileref->fcb->hash_ptrs_uc[dc_hash >> 24];
2571 while (le != &parfileref->fcb->dir_children_hash_uc) {
2572 dc = CONTAINING_RECORD(le, dir_child, list_entry_hash_uc);
2573
2574 if (dc->hash_uc == dc_hash && dc->name.Length == fpusuc.Length && RtlCompareMemory(dc->name.Buffer, fpusuc.Buffer, fpusuc.Length) == fpusuc.Length) {
2575 existing_fileref = dc->fileref;
2576 break;
2577 } else if (dc->hash_uc > dc_hash)
2578 break;
2579
2580 le = le->Flink;
2581 }
2582 }
2583
2584 ExFreePool(fpusuc.Buffer);
2585 }
2586
2587 if (existing_fileref) {
2588 ExReleaseResourceLite(&parfileref->fcb->nonpaged->dir_children_lock);
2590
2591 ExAcquireResourceExclusiveLite(parfileref->fcb->Header.Resource, true);
2592 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2593 ExReleaseResourceLite(parfileref->fcb->Header.Resource);
2594
2595 ExFreePool(utf8);
2596
2597 increase_fileref_refcount(existing_fileref);
2598 *pfr = existing_fileref;
2599
2601 }
2602
2603 Status = add_dir_child(parfileref->fcb, fcb->inode, false, &utf8as, fpus, fcb->type, &dc);
2604 if (!NT_SUCCESS(Status)) {
2605 ExReleaseResourceLite(&parfileref->fcb->nonpaged->dir_children_lock);
2606 ERR("add_dir_child returned %08lx\n", Status);
2608
2609 ExAcquireResourceExclusiveLite(parfileref->fcb->Header.Resource, true);
2610 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2611 ExReleaseResourceLite(parfileref->fcb->Header.Resource);
2612
2613 ExFreePool(utf8);
2614
2615 return Status;
2616 }
2617
2618 fileref->parent = parfileref;
2619 fileref->dc = dc;
2620 dc->fileref = fileref;
2621
2623 fileref->fcb->fileref = fileref;
2624
2625 InsertTailList(&parfileref->children, &fileref->list_entry);
2626 ExReleaseResourceLite(&parfileref->fcb->nonpaged->dir_children_lock);
2627
2628 ExFreePool(utf8);
2629
2631 increase_fileref_refcount(parfileref);
2632
2633 *pfr = fileref;
2634
2635 TRACE("created new file in subvol %I64x, inode %I64x\n", fcb->subvol->id, fcb->inode);
2636
2637 return STATUS_SUCCESS;
2638}
#define S_IFDIR
Definition: acwin.h:115
#define GID_NOBODY
Definition: btrfs_drv.h:91
#define InterlockedIncrement64(a)
Definition: btrfs_drv.h:143
NTSTATUS NTSTATUS NTSTATUS NTSTATUS extend_file(fcb *fcb, file_ref *fileref, uint64_t end, bool prealloc, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
NTSTATUS fcb_get_new_sd(fcb *fcb, file_ref *parfileref, ACCESS_STATE *as)
Definition: security.c:988
@ PropCompression_None
Definition: btrfs_drv.h:268
static __inline bool write_fcb_compressed(fcb *fcb)
Definition: btrfs_drv.h:1706
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
uint32_t inherit_mode(fcb *parfcb, bool is_dir)
Definition: create.c:1948
static NTSTATUS file_create_parse_ea(fcb *fcb, FILE_FULL_EA_INFORMATION *ea)
Definition: create.c:1964
NTSTATUS add_dir_child(fcb *fcb, uint64_t inode, bool subvol, PANSI_STRING utf8, PUNICODE_STRING name, uint8_t type, dir_child **pdc)
Definition: create.c:1871
#define S_IFREG
Definition: ext2fs.h:361
#define FSRTL_FLAG2_IS_PAGING_FILE
Definition: fsrtltypes.h:57
const GLubyte * c
Definition: glext.h:8905
#define d
Definition: ke_i.h:81
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
#define FILE_ATTRIBUTE_ARCHIVE
Definition: nt_native.h:706
#define FILE_ATTRIBUTE_TEMPORARY
Definition: nt_native.h:708
#define S_IXGRP
Definition: propsheet.h:49
#define BTRFS_INODE_NOCOMPRESS
Definition: propsheet.h:79
#define BTRFS_INODE_COMPRESS
Definition: propsheet.h:87
#define S_IXOTH
Definition: propsheet.h:61
#define BTRFS_INODE_NODATACOW
Definition: propsheet.h:77
#define S_IXUSR
Definition: propsheet.h:37
uint64_t st_rdev
Definition: btrfs.h:296
uint32_t st_nlink
Definition: btrfs.h:292
uint64_t block_group
Definition: btrfs.h:291
BTRFS_TIME otime
Definition: btrfs.h:304
BTRFS_TIME st_mtime
Definition: btrfs.h:303
BTRFS_TIME st_atime
Definition: btrfs.h:301
uint64_t st_blocks
Definition: btrfs.h:290
uint32_t st_gid
Definition: btrfs.h:294
uint64_t generation
Definition: btrfs.h:287
ULONG ealen
Definition: btrfs_drv.h:303
bool sd_dirty
Definition: btrfs_drv.h:321
struct _file_ref * fileref
Definition: btrfs_drv.h:305
LIST_ENTRY ** hash_ptrs_uc
Definition: btrfs_drv.h:318
LIST_ENTRY ** hash_ptrs
Definition: btrfs_drv.h:317
bool atts_changed
Definition: btrfs_drv.h:322
enum prop_compression_type prop_compression
Definition: btrfs_drv.h:307
bool prop_compression_changed
Definition: btrfs_drv.h:326
Definition: _hash_fun.h:40

Referenced by create_stream(), and file_create().

◆ file_create_parse_ea()

static NTSTATUS file_create_parse_ea ( fcb fcb,
FILE_FULL_EA_INFORMATION ea 
)
static

Definition at line 1964 of file create.c.

1964 {
1966 LIST_ENTRY ealist, *le;
1967 uint16_t size = 0;
1968 char* buf;
1969
1970 InitializeListHead(&ealist);
1971
1972 do {
1973 STRING s;
1974 bool found = false;
1975
1976 s.Length = s.MaximumLength = ea->EaNameLength;
1977 s.Buffer = ea->EaName;
1978
1979 RtlUpperString(&s, &s);
1980
1981 le = ealist.Flink;
1982 while (le != &ealist) {
1984
1985 if (item->name.Length == s.Length && RtlCompareMemory(item->name.Buffer, s.Buffer, s.Length) == s.Length) {
1986 item->flags = ea->Flags;
1987 item->value.Length = item->value.MaximumLength = ea->EaValueLength;
1988 item->value.Buffer = &ea->EaName[ea->EaNameLength + 1];
1989 found = true;
1990 break;
1991 }
1992
1993 le = le->Flink;
1994 }
1995
1996 if (!found) {
1998 if (!item) {
1999 ERR("out of memory\n");
2001 goto end;
2002 }
2003
2004 item->name.Length = item->name.MaximumLength = ea->EaNameLength;
2005 item->name.Buffer = ea->EaName;
2006
2007 item->value.Length = item->value.MaximumLength = ea->EaValueLength;
2008 item->value.Buffer = &ea->EaName[ea->EaNameLength + 1];
2009
2010 item->flags = ea->Flags;
2011
2012 InsertTailList(&ealist, &item->list_entry);
2013 }
2014
2015 if (ea->NextEntryOffset == 0)
2016 break;
2017
2018 ea = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)ea) + ea->NextEntryOffset);
2019 } while (true);
2020
2021 // handle LXSS values
2022 le = ealist.Flink;
2023 while (le != &ealist) {
2024 LIST_ENTRY* le2 = le->Flink;
2026
2027 if (item->name.Length == sizeof(lxuid) - 1 && RtlCompareMemory(item->name.Buffer, lxuid, item->name.Length) == item->name.Length) {
2028 if (item->value.Length < sizeof(uint32_t)) {
2029 ERR("uid value was shorter than expected\n");
2031 goto end;
2032 }
2033
2034 RtlCopyMemory(&fcb->inode_item.st_uid, item->value.Buffer, sizeof(uint32_t));
2035 fcb->sd_dirty = true;
2036 fcb->sd_deleted = false;
2037
2038 RemoveEntryList(&item->list_entry);
2040 } else if (item->name.Length == sizeof(lxgid) - 1 && RtlCompareMemory(item->name.Buffer, lxgid, item->name.Length) == item->name.Length) {
2041 if (item->value.Length < sizeof(uint32_t)) {
2042 ERR("gid value was shorter than expected\n");
2044 goto end;
2045 }
2046
2047 RtlCopyMemory(&fcb->inode_item.st_gid, item->value.Buffer, sizeof(uint32_t));
2048
2049 RemoveEntryList(&item->list_entry);
2051 } else if (item->name.Length == sizeof(lxmod) - 1 && RtlCompareMemory(item->name.Buffer, lxmod, item->name.Length) == item->name.Length) {
2053 uint32_t val;
2054
2055 if (item->value.Length < sizeof(uint32_t)) {
2056 ERR("mode value was shorter than expected\n");
2058 goto end;
2059 }
2060
2061 val = *(uint32_t*)item->value.Buffer;
2062
2063 fcb->inode_item.st_mode &= ~allowed;
2064 fcb->inode_item.st_mode |= val & allowed;
2065
2067 if (__S_ISTYPE(val, __S_IFCHR)) {
2069 fcb->inode_item.st_mode &= ~__S_IFMT;
2071 } else if (__S_ISTYPE(val, __S_IFBLK)) {
2073 fcb->inode_item.st_mode &= ~__S_IFMT;
2075 } else if (__S_ISTYPE(val, __S_IFIFO)) {
2077 fcb->inode_item.st_mode &= ~__S_IFMT;
2079 } else if (__S_ISTYPE(val, __S_IFSOCK)) {
2081 fcb->inode_item.st_mode &= ~__S_IFMT;
2083 }
2084 }
2085
2086 RemoveEntryList(&item->list_entry);
2088 } else if (item->name.Length == sizeof(lxdev) - 1 && RtlCompareMemory(item->name.Buffer, lxdev, item->name.Length) == item->name.Length) {
2090
2091 if (item->value.Length < sizeof(uint64_t)) {
2092 ERR("dev value was shorter than expected\n");
2094 goto end;
2095 }
2096
2097 major = *(uint32_t*)item->value.Buffer;
2098 minor = *(uint32_t*)&item->value.Buffer[sizeof(uint32_t)];
2099
2100 fcb->inode_item.st_rdev = (minor & 0xFFFFF) | ((major & 0xFFFFFFFFFFF) << 20);
2101
2102 RemoveEntryList(&item->list_entry);
2104 }
2105
2106 le = le2;
2107 }
2108
2110 fcb->inode_item.st_rdev = 0;
2111
2112 if (IsListEmpty(&ealist))
2113 return STATUS_SUCCESS;
2114
2115 le = ealist.Flink;
2116 while (le != &ealist) {
2118
2119 if (size % 4 > 0)
2120 size += 4 - (size % 4);
2121
2122 size += (uint16_t)offsetof(FILE_FULL_EA_INFORMATION, EaName[0]) + item->name.Length + 1 + item->value.Length;
2123
2124 le = le->Flink;
2125 }
2126
2128 if (!buf) {
2129 ERR("out of memory\n");
2131 goto end;
2132 }
2133
2136
2137 fcb->ealen = 4;
2138 ea = NULL;
2139
2140 le = ealist.Flink;
2141 while (le != &ealist) {
2143
2144 if (ea) {
2146
2147 if (ea->NextEntryOffset % 4 > 0)
2148 ea->NextEntryOffset += 4 - (ea->NextEntryOffset % 4);
2149
2150 ea = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)ea) + ea->NextEntryOffset);
2151 } else
2153
2154 ea->NextEntryOffset = 0;
2155 ea->Flags = item->flags;
2156 ea->EaNameLength = (UCHAR)item->name.Length;
2157 ea->EaValueLength = item->value.Length;
2158
2159 RtlCopyMemory(ea->EaName, item->name.Buffer, item->name.Length);
2160 ea->EaName[item->name.Length] = 0;
2161 RtlCopyMemory(&ea->EaName[item->name.Length + 1], item->value.Buffer, item->value.Length);
2162
2163 fcb->ealen += 5 + item->name.Length + item->value.Length;
2164
2165 le = le->Flink;
2166 }
2167
2168 fcb->ea_changed = true;
2169
2171
2172end:
2173 while (!IsListEmpty(&ealist)) {
2175
2177 }
2178
2179 return Status;
2180}
unsigned short int uint16_t
Definition: acefiex.h:54
static const char lxgid[]
Definition: btrfs_drv.h:1288
static const char lxdev[]
Definition: btrfs_drv.h:1290
static const char lxmod[]
Definition: btrfs_drv.h:1289
static const char lxuid[]
Definition: btrfs_drv.h:1287
#define __S_ISTYPE(mode, mask)
Definition: btrfs_drv.h:1761
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
std::wstring STRING
Definition: fontsub.cpp:33
GLdouble s
Definition: gl.h:2039
GLsizeiptr size
Definition: glext.h:5919
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint GLfloat * val
Definition: glext.h:7180
if(dx< 0)
Definition: linetemp.h:194
static ATOM item
Definition: dde.c:856
#define uint32_t
Definition: nsiface.idl:61
NTSYSAPI VOID NTAPI RtlUpperString(PSTRING DestinationString, PSTRING SourceString)
#define minor(rdev)
Definition: propsheet.cpp:929
#define major(rdev)
Definition: propsheet.cpp:928
#define S_IROTH
Definition: propsheet.h:53
#define S_ISUID
Definition: propsheet.h:65
#define S_IRGRP
Definition: propsheet.h:41
#define S_IWOTH
Definition: propsheet.h:57
#define S_IRUSR
Definition: propsheet.h:29
#define S_ISVTX
Definition: propsheet.h:73
#define S_ISGID
Definition: propsheet.h:69
#define S_IWUSR
Definition: propsheet.h:33
#define S_IWGRP
Definition: propsheet.h:45
#define offsetof(TYPE, MEMBER)
uint32_t st_uid
Definition: btrfs.h:293
bool sd_deleted
Definition: btrfs_drv.h:321
bool ea_changed
Definition: btrfs_drv.h:325
ANSI_STRING ea_xattr
Definition: btrfs_drv.h:302
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by file_create2().

◆ find_file_in_dir()

NTSTATUS find_file_in_dir ( PUNICODE_STRING  filename,
fcb fcb,
root **  subvol,
uint64_t inode,
dir_child **  pdc,
bool  case_sensitive 
)

Definition at line 182 of file create.c.

182 {
184 UNICODE_STRING fnus;
186 LIST_ENTRY* le;
187 uint8_t c;
188 bool locked = false;
189
190 if (!case_sensitive) {
191 Status = RtlUpcaseUnicodeString(&fnus, filename, true);
192
193 if (!NT_SUCCESS(Status)) {
194 ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
195 return Status;
196 }
197 } else
198 fnus = *filename;
199
200 Status = check_file_name_valid(filename, false, false);
201 if (!NT_SUCCESS(Status))
202 return Status;
203
204 hash = calc_crc32c(0xffffffff, (uint8_t*)fnus.Buffer, fnus.Length);
205
206 c = hash >> 24;
207
208 if (!ExIsResourceAcquiredSharedLite(&fcb->nonpaged->dir_children_lock)) {
209 ExAcquireResourceSharedLite(&fcb->nonpaged->dir_children_lock, true);
210 locked = true;
211 }
212
213 if (case_sensitive) {
214 if (!fcb->hash_ptrs[c]) {
216 goto end;
217 }
218
219 le = fcb->hash_ptrs[c];
220 while (le != &fcb->dir_children_hash) {
221 dir_child* dc = CONTAINING_RECORD(le, dir_child, list_entry_hash);
222
223 if (dc->hash == hash) {
224 if (dc->name.Length == fnus.Length && RtlCompareMemory(dc->name.Buffer, fnus.Buffer, fnus.Length) == fnus.Length) {
225 if (dc->key.obj_type == TYPE_ROOT_ITEM) {
226 LIST_ENTRY* le2;
227
228 *subvol = NULL;
229
230 le2 = fcb->Vcb->roots.Flink;
231 while (le2 != &fcb->Vcb->roots) {
233
234 if (r2->id == dc->key.obj_id) {
235 *subvol = r2;
236 break;
237 }
238
239 le2 = le2->Flink;
240 }
241
243 } else {
244 *subvol = fcb->subvol;
245 *inode = dc->key.obj_id;
246 }
247
248 *pdc = dc;
249
251 goto end;
252 }
253 } else if (dc->hash > hash) {
255 goto end;
256 }
257
258 le = le->Flink;
259 }
260 } else {
261 if (!fcb->hash_ptrs_uc[c]) {
263 goto end;
264 }
265
266 le = fcb->hash_ptrs_uc[c];
267 while (le != &fcb->dir_children_hash_uc) {
268 dir_child* dc = CONTAINING_RECORD(le, dir_child, list_entry_hash_uc);
269
270 if (dc->hash_uc == hash) {
271 if (dc->name_uc.Length == fnus.Length && RtlCompareMemory(dc->name_uc.Buffer, fnus.Buffer, fnus.Length) == fnus.Length) {
272 if (dc->key.obj_type == TYPE_ROOT_ITEM) {
273 LIST_ENTRY* le2;
274
275 *subvol = NULL;
276
277 le2 = fcb->Vcb->roots.Flink;
278 while (le2 != &fcb->Vcb->roots) {
280
281 if (r2->id == dc->key.obj_id) {
282 *subvol = r2;
283 break;
284 }
285
286 le2 = le2->Flink;
287 }
288
290 } else {
291 *subvol = fcb->subvol;
292 *inode = dc->key.obj_id;
293 }
294
295 *pdc = dc;
296
298 goto end;
299 }
300 } else if (dc->hash_uc > hash) {
302 goto end;
303 }
304
305 le = le->Flink;
306 }
307 }
308
310
311end:
312 if (locked)
313 ExReleaseResourceLite(&fcb->nonpaged->dir_children_lock);
314
315 if (!case_sensitive)
316 ExFreePool(fnus.Buffer);
317
318 return Status;
319}
const char * filename
Definition: ioapi.h:137
#define c
Definition: ke_i.h:80
static DNS_RECORDW r2
Definition: record.c:38
ULONG NTAPI ExIsResourceAcquiredSharedLite(IN PERESOURCE Resource)
Definition: resource.c:1663
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42

Referenced by mknod(), and open_fileref_child().

◆ get_reparse_block()

static NTSTATUS get_reparse_block ( fcb fcb,
uint8_t **  data 
)
static

Definition at line 3425 of file create.c.

3425 {
3427
3429 ULONG size, bytes_read, i;
3430
3431 if (fcb->type == BTRFS_TYPE_FILE && fcb->inode_item.st_size < sizeof(ULONG)) {
3432 WARN("file was too short to be a reparse point\n");
3434 }
3435
3436 // 0x10007 = 0xffff (maximum length of data buffer) + 8 bytes header
3437 size = (ULONG)min(0x10007, fcb->inode_item.st_size);
3438
3439 if (size == 0)
3441
3443 if (!*data) {
3444 ERR("out of memory\n");
3446 }
3447
3448 Status = read_file(fcb, *data, 0, size, &bytes_read, NULL);
3449 if (!NT_SUCCESS(Status)) {
3450 ERR("read_file_fcb returned %08lx\n", Status);
3451 ExFreePool(*data);
3452 return Status;
3453 }
3454
3455 if (fcb->type == BTRFS_TYPE_SYMLINK) {
3456 ULONG stringlen, reqlen;
3457 uint16_t subnamelen, printnamelen;
3459
3460 Status = utf8_to_utf16(NULL, 0, &stringlen, (char*)*data, bytes_read);
3461 if (!NT_SUCCESS(Status)) {
3462 ERR("utf8_to_utf16 1 returned %08lx\n", Status);
3463 ExFreePool(*data);
3464 return Status;
3465 }
3466
3467 subnamelen = printnamelen = (USHORT)stringlen;
3468
3469 reqlen = offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + subnamelen + printnamelen;
3470
3472
3473 if (!rdb) {
3474 ERR("out of memory\n");
3475 ExFreePool(*data);
3477 }
3478
3480 rdb->ReparseDataLength = (USHORT)(reqlen - offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer));
3481 rdb->Reserved = 0;
3482
3483 rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
3484 rdb->SymbolicLinkReparseBuffer.SubstituteNameLength = subnamelen;
3485 rdb->SymbolicLinkReparseBuffer.PrintNameOffset = subnamelen;
3486 rdb->SymbolicLinkReparseBuffer.PrintNameLength = printnamelen;
3488
3489 Status = utf8_to_utf16(&rdb->SymbolicLinkReparseBuffer.PathBuffer[rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)],
3490 stringlen, &stringlen, (char*)*data, size);
3491
3492 if (!NT_SUCCESS(Status)) {
3493 ERR("utf8_to_utf16 2 returned %08lx\n", Status);
3494 ExFreePool(rdb);
3495 ExFreePool(*data);
3496 return Status;
3497 }
3498
3499 for (i = 0; i < stringlen / sizeof(WCHAR); i++) {
3500 if (rdb->SymbolicLinkReparseBuffer.PathBuffer[(rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)) + i] == '/')
3501 rdb->SymbolicLinkReparseBuffer.PathBuffer[(rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)) + i] = '\\';
3502 }
3503
3504 RtlCopyMemory(&rdb->SymbolicLinkReparseBuffer.PathBuffer[rdb->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(WCHAR)],
3505 &rdb->SymbolicLinkReparseBuffer.PathBuffer[rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)],
3506 rdb->SymbolicLinkReparseBuffer.SubstituteNameLength);
3507
3508 ExFreePool(*data);
3509
3510 *data = (uint8_t*)rdb;
3511 } else {
3513 if (!NT_SUCCESS(Status)) {
3514 ERR("FsRtlValidateReparsePointBuffer returned %08lx\n", Status);
3515 ExFreePool(*data);
3516 return Status;
3517 }
3518 }
3519 } else if (fcb->type == BTRFS_TYPE_DIRECTORY) {
3521 return STATUS_INTERNAL_ERROR;
3522
3523 if (fcb->reparse_xattr.Length < sizeof(ULONG)) {
3524 WARN("xattr was too short to be a reparse point\n");
3525 return STATUS_INTERNAL_ERROR;
3526 }
3527
3529 if (!NT_SUCCESS(Status)) {
3530 ERR("FsRtlValidateReparsePointBuffer returned %08lx\n", Status);
3531 return Status;
3532 }
3533
3535 if (!*data) {
3536 ERR("out of memory\n");
3538 }
3539
3541 } else
3543
3544 return STATUS_SUCCESS;
3545}
NTSTATUS read_file(fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp) __attribute__((nonnull(1
wstring utf8_to_utf16(const string_view &utf8)
Definition: main.cpp:734
tFsRtlValidateReparsePointBuffer fFsRtlValidateReparsePointBuffer
Definition: btrfs.c:98
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint const GLchar GLint stringlen
Definition: glext.h:7232
#define min(a, b)
Definition: monoChain.cc:55
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define SYMLINK_FLAG_RELATIVE
Definition: shellext.h:193
WCHAR PathBuffer[1]
Definition: shellext.h:176
struct _REPARSE_DATA_BUFFER::@318::@320 SymbolicLinkReparseBuffer
USHORT ReparseDataLength
Definition: shellext.h:166
ANSI_STRING reparse_xattr
Definition: btrfs_drv.h:301

Referenced by open_file(), and open_file2().

◆ has_manage_volume_privilege()

static bool has_manage_volume_privilege ( ACCESS_STATE access_state,
KPROCESSOR_MODE  processor_mode 
)
static

Definition at line 4815 of file create.c.

4815 {
4816 PRIVILEGE_SET privset;
4817
4818 privset.PrivilegeCount = 1;
4820 privset.Privilege[0].Luid = RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE);
4821 privset.Privilege[0].Attributes = 0;
4822
4823 return SePrivilegeCheck(&privset, &access_state->SubjectSecurityContext, processor_mode) ? true : false;
4824}
#define SE_MANAGE_VOLUME_PRIVILEGE
Definition: security.c:682
BOOLEAN NTAPI SePrivilegeCheck(_In_ PPRIVILEGE_SET Privileges, _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a set of privileges exist and match within a security subject context.
Definition: priv.c:698
#define true
Definition: stdbool.h:36
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext
Definition: setypes.h:234
LUID_AND_ATTRIBUTES Privilege[ANYSIZE_ARRAY]
Definition: setypes.h:88
$ULONG Control
Definition: setypes.h:87
$ULONG PrivilegeCount
Definition: setypes.h:86
#define PRIVILEGE_SET_ALL_NECESSARY
Definition: setypes.h:83

Referenced by _Dispatch_type_().

◆ inherit_mode()

uint32_t inherit_mode ( fcb parfcb,
bool  is_dir 
)

Definition at line 1948 of file create.c.

1948 {
1949 uint32_t mode;
1950
1951 if (!parfcb)
1952 return 0755;
1953
1954 mode = parfcb->inode_item.st_mode & ~S_IFDIR;
1955 mode &= ~S_ISVTX; // clear sticky bit
1956 mode &= ~S_ISUID; // clear setuid bit
1957
1958 if (!is_dir)
1959 mode &= ~S_ISGID; // if not directory, clear setgid bit
1960
1961 return mode;
1962}
GLenum mode
Definition: glext.h:6217

Referenced by create_directory_fcb(), create_subvol(), file_create2(), and mknod().

◆ load_csum()

NTSTATUS load_csum ( _Requires_lock_held_(_Curr_->tree_lock) device_extension Vcb,
void csum,
uint64_t  start,
uint64_t  length,
PIRP  Irp 
)

Definition at line 453 of file create.c.

453 {
455 KEY searchkey;
456 traverse_ptr tp, next_tp;
457 uint64_t i, j;
458 bool b;
459 void* ptr = csum;
460
461 searchkey.obj_id = EXTENT_CSUM_ID;
462 searchkey.obj_type = TYPE_EXTENT_CSUM;
463 searchkey.offset = start;
464
465 Status = find_item(Vcb, Vcb->checksum_root, &tp, &searchkey, false, Irp);
466 if (!NT_SUCCESS(Status)) {
467 ERR("error - find_item returned %08lx\n", Status);
468 return Status;
469 }
470
471 i = 0;
472 do {
473 if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
474 ULONG readlen;
475
476 if (start < tp.item->key.offset)
477 j = 0;
478 else
479 j = ((start - tp.item->key.offset) >> Vcb->sector_shift) + i;
480
481 if (j * Vcb->csum_size > tp.item->size || tp.item->key.offset > start + (i << Vcb->sector_shift)) {
482 ERR("checksum not found for %I64x\n", start + (i << Vcb->sector_shift));
484 }
485
486 readlen = (ULONG)min((tp.item->size / Vcb->csum_size) - j, length - i);
487 RtlCopyMemory(ptr, tp.item->data + (j * Vcb->csum_size), readlen * Vcb->csum_size);
488
489 ptr = (uint8_t*)ptr + (readlen * Vcb->csum_size);
490 i += readlen;
491
492 if (i == length)
493 break;
494 }
495
496 b = find_next_item(Vcb, &tp, &next_tp, false, Irp);
497
498 if (b)
499 tp = next_tp;
500 } while (b);
501
502 if (i < length) {
503 ERR("could not read checksums: offset %I64x, length %I64x sectors\n", start, length);
505 }
506
507 return STATUS_SUCCESS;
508}
NTSTATUS NTSTATUS bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp) __attribute__((nonnull(1
#define EXTENT_CSUM_ID
Definition: btrfs.h:91
#define TYPE_EXTENT_CSUM
Definition: btrfs.h:31
GLuint start
Definition: gl.h:1545
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
#define b
Definition: ke_i.h:79
static PVOID ptr
Definition: dispmode.c:27
uint8_t * data
Definition: btrfs_drv.h:415
Definition: ffs.h:52
Definition: copy.c:22

Referenced by fcb_load_csums(), and flush_extents().

◆ load_dir_children()

NTSTATUS load_dir_children ( _Requires_lock_held_(_Curr_->tree_lock) device_extension Vcb,
fcb fcb,
bool  ignore_size,
PIRP  Irp 
)

Definition at line 510 of file create.c.

510 {
511 KEY searchkey;
512 traverse_ptr tp, next_tp;
514 ULONG num_children = 0;
515 uint64_t max_index = 2;
516
518 if (!fcb->hash_ptrs) {
519 ERR("out of memory\n");
521 }
522
523 RtlZeroMemory(fcb->hash_ptrs, sizeof(LIST_ENTRY*) * 256);
524
526 if (!fcb->hash_ptrs_uc) {
527 ERR("out of memory\n");
529 }
530
531 RtlZeroMemory(fcb->hash_ptrs_uc, sizeof(LIST_ENTRY*) * 256);
532
533 if (!ignore_size && fcb->inode_item.st_size == 0)
534 return STATUS_SUCCESS;
535
536 searchkey.obj_id = fcb->inode;
537 searchkey.obj_type = TYPE_DIR_INDEX;
538 searchkey.offset = 2;
539
540 Status = find_item(Vcb, fcb->subvol, &tp, &searchkey, false, Irp);
541 if (!NT_SUCCESS(Status)) {
542 ERR("find_item returned %08lx\n", Status);
543 return Status;
544 }
545
546 if (keycmp(tp.item->key, searchkey) == -1) {
547 if (find_next_item(Vcb, &tp, &next_tp, false, Irp)) {
548 tp = next_tp;
549 TRACE("moving on to %I64x,%x,%I64x\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
550 }
551 }
552
553 while (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
554 DIR_ITEM* di = (DIR_ITEM*)tp.item->data;
555 dir_child* dc;
556 ULONG utf16len;
557
558 if (tp.item->size < sizeof(DIR_ITEM)) {
559 WARN("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(DIR_ITEM));
560 goto cont;
561 }
562
563 if (di->n == 0) {
564 WARN("(%I64x,%x,%I64x): DIR_ITEM name length is zero\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
565 goto cont;
566 }
567
568 Status = utf8_to_utf16(NULL, 0, &utf16len, di->name, di->n);
569 if (!NT_SUCCESS(Status)) {
570 ERR("utf8_to_utf16 1 returned %08lx\n", Status);
571 goto cont;
572 }
573
575 if (!dc) {
576 ERR("out of memory\n");
578 }
579
580 dc->key = di->key;
581 dc->index = tp.item->key.offset;
582 dc->type = di->type;
583 dc->fileref = NULL;
584 dc->root_dir = false;
585
586 max_index = dc->index;
587
588 dc->utf8.MaximumLength = dc->utf8.Length = di->n;
589 dc->utf8.Buffer = ExAllocatePoolWithTag(PagedPool, di->n, ALLOC_TAG);
590 if (!dc->utf8.Buffer) {
591 ERR("out of memory\n");
592 ExFreePool(dc);
594 }
595
596 RtlCopyMemory(dc->utf8.Buffer, di->name, di->n);
597
598 dc->name.MaximumLength = dc->name.Length = (uint16_t)utf16len;
599 dc->name.Buffer = ExAllocatePoolWithTag(PagedPool, dc->name.MaximumLength, ALLOC_TAG);
600 if (!dc->name.Buffer) {
601 ERR("out of memory\n");
602 ExFreePool(dc->utf8.Buffer);
603 ExFreePool(dc);
605 }
606
607 Status = utf8_to_utf16(dc->name.Buffer, utf16len, &utf16len, di->name, di->n);
608 if (!NT_SUCCESS(Status)) {
609 ERR("utf8_to_utf16 2 returned %08lx\n", Status);
610 ExFreePool(dc->utf8.Buffer);
611 ExFreePool(dc->name.Buffer);
612 ExFreePool(dc);
613 goto cont;
614 }
615
616 Status = RtlUpcaseUnicodeString(&dc->name_uc, &dc->name, true);
617 if (!NT_SUCCESS(Status)) {
618 ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
619 ExFreePool(dc->utf8.Buffer);
620 ExFreePool(dc->name.Buffer);
621 ExFreePool(dc);
622 goto cont;
623 }
624
625 dc->hash = calc_crc32c(0xffffffff, (uint8_t*)dc->name.Buffer, dc->name.Length);
626 dc->hash_uc = calc_crc32c(0xffffffff, (uint8_t*)dc->name_uc.Buffer, dc->name_uc.Length);
627
628 InsertTailList(&fcb->dir_children_index, &dc->list_entry_index);
629
631
632 num_children++;
633
634cont:
635 if (find_next_item(Vcb, &tp, &next_tp, false, Irp))
636 tp = next_tp;
637 else
638 break;
639 }
640
641 if (!Vcb->options.no_root_dir && fcb->inode == SUBVOL_ROOT_INODE) {
642 root* top_subvol;
643
644 if (Vcb->root_fileref && Vcb->root_fileref->fcb)
645 top_subvol = Vcb->root_fileref->fcb->subvol;
646 else
647 top_subvol = find_default_subvol(Vcb, NULL);
648
649 if (fcb->subvol == top_subvol && top_subvol->id != BTRFS_ROOT_FSTREE) {
651 if (!dc) {
652 ERR("out of memory\n");
654 }
655
656 dc->key.obj_id = BTRFS_ROOT_FSTREE;
657 dc->key.obj_type = TYPE_ROOT_ITEM;
658 dc->key.offset = 0;
659 dc->index = max_index + 1;
660 dc->type = BTRFS_TYPE_DIRECTORY;
661 dc->fileref = NULL;
662 dc->root_dir = true;
663
664 dc->utf8.MaximumLength = dc->utf8.Length = sizeof(root_dir) - sizeof(char);
665 dc->utf8.Buffer = ExAllocatePoolWithTag(PagedPool, sizeof(root_dir) - sizeof(char), ALLOC_TAG);
666 if (!dc->utf8.Buffer) {
667 ERR("out of memory\n");
668 ExFreePool(dc);
670 }
671
672 RtlCopyMemory(dc->utf8.Buffer, root_dir, sizeof(root_dir) - sizeof(char));
673
674 dc->name.MaximumLength = dc->name.Length = sizeof(root_dir_utf16) - sizeof(WCHAR);
675 dc->name.Buffer = ExAllocatePoolWithTag(PagedPool, sizeof(root_dir_utf16) - sizeof(WCHAR), ALLOC_TAG);
676 if (!dc->name.Buffer) {
677 ERR("out of memory\n");
678 ExFreePool(dc->utf8.Buffer);
679 ExFreePool(dc);
681 }
682
683 RtlCopyMemory(dc->name.Buffer, root_dir_utf16, sizeof(root_dir_utf16) - sizeof(WCHAR));
684
685 Status = RtlUpcaseUnicodeString(&dc->name_uc, &dc->name, true);
686 if (!NT_SUCCESS(Status)) {
687 ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
688 ExFreePool(dc->utf8.Buffer);
689 ExFreePool(dc->name.Buffer);
690 ExFreePool(dc);
691 goto cont;
692 }
693
694 dc->hash = calc_crc32c(0xffffffff, (uint8_t*)dc->name.Buffer, dc->name.Length);
695 dc->hash_uc = calc_crc32c(0xffffffff, (uint8_t*)dc->name_uc.Buffer, dc->name_uc.Length);
696
697 InsertTailList(&fcb->dir_children_index, &dc->list_entry_index);
698
700 }
701 }
702
703 return STATUS_SUCCESS;
704}
_Ret_maybenull_ root * find_default_subvol(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_opt_ PIRP Irp)
Definition: btrfs.c:3981
#define TYPE_DIR_INDEX
Definition: btrfs.h:29
#define BTRFS_ROOT_FSTREE
Definition: btrfs.h:58
static const char root_dir[]
Definition: create.c:32
static const WCHAR root_dir_utf16[]
Definition: create.c:33
uint8_t type
Definition: btrfs.h:277
char name[1]
Definition: btrfs.h:278
uint16_t n
Definition: btrfs.h:276
KEY key
Definition: btrfs.h:273
uint64_t id
Definition: btrfs_drv.h:451

Referenced by mount_vol().

◆ open_fcb()

NTSTATUS open_fcb ( _Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension Vcb,
root subvol,
uint64_t  inode,
uint8_t  type,
PANSI_STRING  utf8,
bool  always_add_hl,
fcb parent,
fcb **  pfcb,
POOL_TYPE  pooltype,
PIRP  Irp 
)

Definition at line 706 of file create.c.

707 {
708 KEY searchkey;
709 traverse_ptr tp, next_tp;
711 fcb *fcb, *deleted_fcb = NULL;
712 bool atts_set = false, sd_set = false, no_data;
713 LIST_ENTRY* lastle = NULL;
714 EXTENT_DATA* ed = NULL;
717
718 hash = calc_crc32c(0xffffffff, (uint8_t*)&inode, sizeof(uint64_t));
719
720 acquire_fcb_lock_shared(Vcb);
721
722 if (subvol->fcbs_ptrs[hash >> 24]) {
723 LIST_ENTRY* le = subvol->fcbs_ptrs[hash >> 24];
724
725 while (le != &subvol->fcbs) {
726 fcb = CONTAINING_RECORD(le, struct _fcb, list_entry);
727
728 if (fcb->inode == inode) {
729 if (!fcb->ads) {
730 if (fcb->deleted)
731 deleted_fcb = fcb;
732 else {
733#ifdef DEBUG_FCB_REFCOUNTS
735
736 WARN("fcb %p: refcount now %i (subvol %I64x, inode %I64x)\n", fcb, rc, fcb->subvol->id, fcb->inode);
737#else
739#endif
740
741 *pfcb = fcb;
742 release_fcb_lock(Vcb);
743 return STATUS_SUCCESS;
744 }
745 }
746 } else if (fcb->hash > hash) {
747 if (deleted_fcb) {
748 InterlockedIncrement(&deleted_fcb->refcount);
749 *pfcb = deleted_fcb;
750 release_fcb_lock(Vcb);
751 return STATUS_SUCCESS;
752 }
753
754 lastle = le->Blink;
755 fcbs_version = subvol->fcbs_version;
756
757 break;
758 }
759
760 le = le->Flink;
761 }
762 }
763
764 release_fcb_lock(Vcb);
765
766 if (deleted_fcb) {
767 InterlockedIncrement(&deleted_fcb->refcount);
768 *pfcb = deleted_fcb;
769 return STATUS_SUCCESS;
770 }
771
772 fcb = create_fcb(Vcb, pooltype);
773 if (!fcb) {
774 ERR("out of memory\n");
776 }
777
778 fcb->Vcb = Vcb;
779
780 fcb->subvol = subvol;
781 fcb->inode = inode;
782 fcb->hash = hash;
783 fcb->type = type;
784
785 searchkey.obj_id = inode;
786 searchkey.obj_type = TYPE_INODE_ITEM;
787 searchkey.offset = 0xffffffffffffffff;
788
789 Status = find_item(Vcb, subvol, &tp, &searchkey, false, Irp);
790 if (!NT_SUCCESS(Status)) {
791 ERR("error - find_item returned %08lx\n", Status);
792 reap_fcb(fcb);
793 return Status;
794 }
795
796 if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
797 WARN("couldn't find INODE_ITEM for inode %I64x in subvol %I64x\n", inode, subvol->id);
798 reap_fcb(fcb);
800 }
801
802 if (tp.item->size > 0)
804
805 if (fcb->type == 0) { // guess the type from the inode mode, if the caller doesn't know already
808 else if ((fcb->inode_item.st_mode & __S_IFCHR) == __S_IFCHR)
810 else if ((fcb->inode_item.st_mode & __S_IFBLK) == __S_IFBLK)
812 else if ((fcb->inode_item.st_mode & __S_IFIFO) == __S_IFIFO)
814 else if ((fcb->inode_item.st_mode & __S_IFLNK) == __S_IFLNK)
816 else if ((fcb->inode_item.st_mode & __S_IFSOCK) == __S_IFSOCK)
818 else
820 }
821
822 no_data = fcb->inode_item.st_size == 0 || (fcb->type != BTRFS_TYPE_FILE && fcb->type != BTRFS_TYPE_SYMLINK);
823
824 while (find_next_item(Vcb, &tp, &next_tp, false, Irp)) {
825 tp = next_tp;
826
827 if (tp.item->key.obj_id > inode)
828 break;
829
831 break;
832
833 if ((always_add_hl || fcb->inode_item.st_nlink > 1) && tp.item->key.obj_type == TYPE_INODE_REF) {
834 ULONG len;
835 INODE_REF* ir;
836
837 len = tp.item->size;
838 ir = (INODE_REF*)tp.item->data;
839
840 while (len >= sizeof(INODE_REF) - 1) {
841 hardlink* hl;
843
844 hl = ExAllocatePoolWithTag(pooltype, sizeof(hardlink), ALLOC_TAG);
845 if (!hl) {
846 ERR("out of memory\n");
847 reap_fcb(fcb);
849 }
850
851 hl->parent = tp.item->key.offset;
852 hl->index = ir->index;
853
854 hl->utf8.Length = hl->utf8.MaximumLength = ir->n;
855
856 if (hl->utf8.Length > 0) {
858 RtlCopyMemory(hl->utf8.Buffer, ir->name, ir->n);
859 }
860
861 Status = utf8_to_utf16(NULL, 0, &stringlen, ir->name, ir->n);
862 if (!NT_SUCCESS(Status)) {
863 ERR("utf8_to_utf16 1 returned %08lx\n", Status);
864 ExFreePool(hl);
865 reap_fcb(fcb);
866 return Status;
867 }
868
870
871 if (stringlen == 0)
872 hl->name.Buffer = NULL;
873 else {
875
876 if (!hl->name.Buffer) {
877 ERR("out of memory\n");
878 ExFreePool(hl);
879 reap_fcb(fcb);
881 }
882
884 if (!NT_SUCCESS(Status)) {
885 ERR("utf8_to_utf16 2 returned %08lx\n", Status);
887 ExFreePool(hl);
888 reap_fcb(fcb);
889 return Status;
890 }
891 }
892
894
895 len -= sizeof(INODE_REF) - 1 + ir->n;
896 ir = (INODE_REF*)&ir->name[ir->n];
897 }
898 } else if ((always_add_hl || fcb->inode_item.st_nlink > 1) && tp.item->key.obj_type == TYPE_INODE_EXTREF) {
899 ULONG len;
900 INODE_EXTREF* ier;
901
902 len = tp.item->size;
903 ier = (INODE_EXTREF*)tp.item->data;
904
905 while (len >= sizeof(INODE_EXTREF) - 1) {
906 hardlink* hl;
908
909 hl = ExAllocatePoolWithTag(pooltype, sizeof(hardlink), ALLOC_TAG);
910 if (!hl) {
911 ERR("out of memory\n");
912 reap_fcb(fcb);
914 }
915
916 hl->parent = ier->dir;
917 hl->index = ier->index;
918
919 hl->utf8.Length = hl->utf8.MaximumLength = ier->n;
920
921 if (hl->utf8.Length > 0) {
923 RtlCopyMemory(hl->utf8.Buffer, ier->name, ier->n);
924 }
925
926 Status = utf8_to_utf16(NULL, 0, &stringlen, ier->name, ier->n);
927 if (!NT_SUCCESS(Status)) {
928 ERR("utf8_to_utf16 1 returned %08lx\n", Status);
929 ExFreePool(hl);
930 reap_fcb(fcb);
931 return Status;
932 }
933
935
936 if (stringlen == 0)
937 hl->name.Buffer = NULL;
938 else {
940
941 if (!hl->name.Buffer) {
942 ERR("out of memory\n");
943 ExFreePool(hl);
944 reap_fcb(fcb);
946 }
947
948 Status = utf8_to_utf16(hl->name.Buffer, stringlen, &stringlen, ier->name, ier->n);
949 if (!NT_SUCCESS(Status)) {
950 ERR("utf8_to_utf16 2 returned %08lx\n", Status);
952 ExFreePool(hl);
953 reap_fcb(fcb);
954 return Status;
955 }
956 }
957
959
960 len -= sizeof(INODE_EXTREF) - 1 + ier->n;
961 ier = (INODE_EXTREF*)&ier->name[ier->n];
962 }
963 } else if (tp.item->key.obj_type == TYPE_XATTR_ITEM) {
964 ULONG len;
965 DIR_ITEM* di;
966
967 static const char xapref[] = "user.";
968
969 if (tp.item->size < offsetof(DIR_ITEM, name[0])) {
970 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, offsetof(DIR_ITEM, name[0]));
971 continue;
972 }
973
974 len = tp.item->size;
975 di = (DIR_ITEM*)tp.item->data;
976
977 do {
978 if (len < offsetof(DIR_ITEM, name[0]) + di->m + di->n)
979 break;
980
981 if (tp.item->key.offset == EA_REPARSE_HASH && di->n == sizeof(EA_REPARSE) - 1 && RtlCompareMemory(EA_REPARSE, di->name, di->n) == di->n) {
982 if (di->m > 0) {
984 if (!fcb->reparse_xattr.Buffer) {
985 ERR("out of memory\n");
986 reap_fcb(fcb);
988 }
989
990 RtlCopyMemory(fcb->reparse_xattr.Buffer, &di->name[di->n], di->m);
991 } else
993
995 } else if (tp.item->key.offset == EA_EA_HASH && di->n == sizeof(EA_EA) - 1 && RtlCompareMemory(EA_EA, di->name, di->n) == di->n) {
996 if (di->m > 0) {
998
1000
1001 if (!NT_SUCCESS(Status))
1002 WARN("IoCheckEaBufferValidity returned %08lx (error at offset %lu)\n", Status, offset);
1003 else {
1005
1007 if (!fcb->ea_xattr.Buffer) {
1008 ERR("out of memory\n");
1009 reap_fcb(fcb);
1011 }
1012
1013 RtlCopyMemory(fcb->ea_xattr.Buffer, &di->name[di->n], di->m);
1014
1016
1017 fcb->ealen = 4;
1018
1019 // calculate ealen
1020 eainfo = (FILE_FULL_EA_INFORMATION*)&di->name[di->n];
1021 do {
1022 fcb->ealen += 5 + eainfo->EaNameLength + eainfo->EaValueLength;
1023
1024 if (eainfo->NextEntryOffset == 0)
1025 break;
1026
1027 eainfo = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)eainfo) + eainfo->NextEntryOffset);
1028 } while (true);
1029 }
1030 }
1031 } else if (tp.item->key.offset == EA_DOSATTRIB_HASH && di->n == sizeof(EA_DOSATTRIB) - 1 && RtlCompareMemory(EA_DOSATTRIB, di->name, di->n) == di->n) {
1032 if (di->m > 0) {
1033 if (get_file_attributes_from_xattr(&di->name[di->n], di->m, &fcb->atts)) {
1034 atts_set = true;
1035
1038 else if (fcb->type == BTRFS_TYPE_SYMLINK)
1040
1042 fcb->atts &= ~FILE_ATTRIBUTE_DIRECTORY;
1043
1044 if (inode == SUBVOL_ROOT_INODE) {
1047 else
1048 fcb->atts &= ~FILE_ATTRIBUTE_READONLY;
1049 }
1050 }
1051 }
1052 } else if (tp.item->key.offset == EA_NTACL_HASH && di->n == sizeof(EA_NTACL) - 1 && RtlCompareMemory(EA_NTACL, di->name, di->n) == di->n) {
1053 if (di->m > 0) {
1055 if (!fcb->sd) {
1056 ERR("out of memory\n");
1057 reap_fcb(fcb);
1059 }
1060
1061 RtlCopyMemory(fcb->sd, &di->name[di->n], di->m);
1062
1063 // We have to test against our copy rather than the source, as RtlValidRelativeSecurityDescriptor
1064 // will fail if the ACLs aren't 32-bit aligned.
1066 ExFreePool(fcb->sd);
1067 else
1068 sd_set = true;
1069 }
1070 } else if (tp.item->key.offset == EA_PROP_COMPRESSION_HASH && di->n == sizeof(EA_PROP_COMPRESSION) - 1 && RtlCompareMemory(EA_PROP_COMPRESSION, di->name, di->n) == di->n) {
1071 if (di->m > 0) {
1072 static const char lzo[] = "lzo";
1073 static const char zlib[] = "zlib";
1074 static const char zstd[] = "zstd";
1075
1076 if (di->m == sizeof(lzo) - 1 && RtlCompareMemory(&di->name[di->n], lzo, di->m) == di->m)
1078 else if (di->m == sizeof(zlib) - 1 && RtlCompareMemory(&di->name[di->n], zlib, di->m) == di->m)
1080 else if (di->m == sizeof(zstd) - 1 && RtlCompareMemory(&di->name[di->n], zstd, di->m) == di->m)
1082 else
1084 }
1085 } else if (tp.item->key.offset == EA_CASE_SENSITIVE_HASH && di->n == sizeof(EA_CASE_SENSITIVE) - 1 && RtlCompareMemory(EA_CASE_SENSITIVE, di->name, di->n) == di->n) {
1086 if (di->m > 0) {
1087 fcb->case_sensitive = di->m == 1 && di->name[di->n] == '1';
1088 fcb->case_sensitive_set = true;
1089 }
1090 } else if (di->n > sizeof(xapref) - 1 && RtlCompareMemory(xapref, di->name, sizeof(xapref) - 1) == sizeof(xapref) - 1) {
1091 dir_child* dc;
1092 ULONG utf16len;
1093
1094 Status = utf8_to_utf16(NULL, 0, &utf16len, &di->name[sizeof(xapref) - 1], di->n + 1 - sizeof(xapref));
1095 if (!NT_SUCCESS(Status)) {
1096 ERR("utf8_to_utf16 1 returned %08lx\n", Status);
1097 reap_fcb(fcb);
1098 return Status;
1099 }
1100
1102 if (!dc) {
1103 ERR("out of memory\n");
1104 reap_fcb(fcb);
1106 }
1107
1108 RtlZeroMemory(dc, sizeof(dir_child));
1109
1110 dc->utf8.MaximumLength = dc->utf8.Length = di->n + 1 - sizeof(xapref);
1111 dc->utf8.Buffer = ExAllocatePoolWithTag(PagedPool, dc->utf8.MaximumLength, ALLOC_TAG);
1112 if (!dc->utf8.Buffer) {
1113 ERR("out of memory\n");
1114 ExFreePool(dc);
1115 reap_fcb(fcb);
1117 }
1118
1119 RtlCopyMemory(dc->utf8.Buffer, &di->name[sizeof(xapref) - 1], dc->utf8.Length);
1120
1121 dc->name.MaximumLength = dc->name.Length = (uint16_t)utf16len;
1122 dc->name.Buffer = ExAllocatePoolWithTag(PagedPool, dc->name.MaximumLength, ALLOC_TAG);
1123 if (!dc->name.Buffer) {
1124 ERR("out of memory\n");
1125 ExFreePool(dc->utf8.Buffer);
1126 ExFreePool(dc);
1127 reap_fcb(fcb);
1129 }
1130
1131 Status = utf8_to_utf16(dc->name.Buffer, utf16len, &utf16len, dc->utf8.Buffer, dc->utf8.Length);
1132 if (!NT_SUCCESS(Status)) {
1133 ERR("utf8_to_utf16 2 returned %08lx\n", Status);
1134 ExFreePool(dc->utf8.Buffer);
1135 ExFreePool(dc->name.Buffer);
1136 ExFreePool(dc);
1137 reap_fcb(fcb);
1138 return Status;
1139 }
1140
1141 Status = RtlUpcaseUnicodeString(&dc->name_uc, &dc->name, true);
1142 if (!NT_SUCCESS(Status)) {
1143 ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
1144 ExFreePool(dc->utf8.Buffer);
1145 ExFreePool(dc->name.Buffer);
1146 ExFreePool(dc);
1147 reap_fcb(fcb);
1148 return Status;
1149 }
1150
1151 dc->size = di->m;
1152
1153 InsertTailList(&fcb->dir_children_index, &dc->list_entry_index);
1154 } else {
1155 xattr* xa;
1156
1157 xa = ExAllocatePoolWithTag(PagedPool, offsetof(xattr, data[0]) + di->m + di->n, ALLOC_TAG);
1158 if (!xa) {
1159 ERR("out of memory\n");
1160 reap_fcb(fcb);
1162 }
1163
1164 xa->namelen = di->n;
1165 xa->valuelen = di->m;
1166 xa->dirty = false;
1167 RtlCopyMemory(xa->data, di->name, di->m + di->n);
1168
1170 }
1171
1172 len -= (ULONG)offsetof(DIR_ITEM, name[0]) + di->m + di->n;
1173
1174 if (len < offsetof(DIR_ITEM, name[0]))
1175 break;
1176
1177 di = (DIR_ITEM*)&di->name[di->m + di->n];
1178 } while (true);
1179 } else if (tp.item->key.obj_type == TYPE_EXTENT_DATA) {
1180 extent* ext;
1181 bool unique = false;
1182
1183 ed = (EXTENT_DATA*)tp.item->data;
1184
1185 if (tp.item->size < sizeof(EXTENT_DATA)) {
1186 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset,
1187 tp.item->size, sizeof(EXTENT_DATA));
1188
1189 reap_fcb(fcb);
1190 return STATUS_INTERNAL_ERROR;
1191 }
1192
1193 if (ed->type == EXTENT_TYPE_REGULAR || ed->type == EXTENT_TYPE_PREALLOC) {
1194 EXTENT_DATA2* ed2 = (EXTENT_DATA2*)&ed->data[0];
1195
1196 if (tp.item->size < sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2)) {
1197 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset,
1198 tp.item->size, sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2));
1199
1200 reap_fcb(fcb);
1201 return STATUS_INTERNAL_ERROR;
1202 }
1203
1204 if (ed2->address == 0 || ed2->size == 0) // sparse
1205 continue;
1206
1207 if (ed2->size != 0 && is_tree_unique(Vcb, tp.tree, Irp))
1208 unique = is_extent_unique(Vcb, ed2->address, ed2->size, Irp);
1209 }
1210
1211 ext = ExAllocatePoolWithTag(pooltype, offsetof(extent, extent_data) + tp.item->size, ALLOC_TAG);
1212 if (!ext) {
1213 ERR("out of memory\n");
1214 reap_fcb(fcb);
1216 }
1217
1218 ext->offset = tp.item->key.offset;
1219 RtlCopyMemory(&ext->extent_data, tp.item->data, tp.item->size);
1220 ext->datalen = tp.item->size;
1221 ext->unique = unique;
1222 ext->ignore = false;
1223 ext->inserted = false;
1224 ext->csum = NULL;
1225
1226 InsertTailList(&fcb->extents, &ext->list_entry);
1227 }
1228 }
1229
1230 if (fcb->type == BTRFS_TYPE_DIRECTORY) {
1231 Status = load_dir_children(Vcb, fcb, false, Irp);
1232 if (!NT_SUCCESS(Status)) {
1233 ERR("load_dir_children returned %08lx\n", Status);
1234 reap_fcb(fcb);
1235 return Status;
1236 }
1237 }
1238
1239 if (no_data) {
1240 fcb->Header.AllocationSize.QuadPart = 0;
1241 fcb->Header.FileSize.QuadPart = 0;
1242 fcb->Header.ValidDataLength.QuadPart = 0;
1243 } else {
1244 if (ed && ed->type == EXTENT_TYPE_INLINE)
1245 fcb->Header.AllocationSize.QuadPart = fcb->inode_item.st_size;
1246 else
1247 fcb->Header.AllocationSize.QuadPart = sector_align(fcb->inode_item.st_size, fcb->Vcb->superblock.sector_size);
1248
1249 fcb->Header.FileSize.QuadPart = fcb->inode_item.st_size;
1250 fcb->Header.ValidDataLength.QuadPart = fcb->inode_item.st_size;
1251 }
1252
1253 if (!atts_set)
1254 fcb->atts = get_file_attributes(Vcb, fcb->subvol, fcb->inode, fcb->type, utf8 && utf8->Buffer[0] == '.', true, Irp);
1255
1256 if (!sd_set)
1257 fcb_get_sd(fcb, parent, false, Irp);
1258
1259 acquire_fcb_lock_exclusive(Vcb);
1260
1261 if (lastle && subvol->fcbs_version == fcbs_version) {
1262 InsertHeadList(lastle, &fcb->list_entry);
1263
1264 if (!subvol->fcbs_ptrs[hash >> 24] || CONTAINING_RECORD(subvol->fcbs_ptrs[hash >> 24], struct _fcb, list_entry)->hash > hash)
1265 subvol->fcbs_ptrs[hash >> 24] = &fcb->list_entry;
1266 } else {
1267 lastle = NULL;
1268
1269 if (subvol->fcbs_ptrs[hash >> 24]) {
1270 LIST_ENTRY* le = subvol->fcbs_ptrs[hash >> 24];
1271
1272 while (le != &subvol->fcbs) {
1273 struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
1274
1275 if (fcb2->inode == inode) {
1276 if (!fcb2->ads) {
1277 if (fcb2->deleted)
1278 deleted_fcb = fcb2;
1279 else {
1280#ifdef DEBUG_FCB_REFCOUNTS
1281 LONG rc = InterlockedIncrement(&fcb2->refcount);
1282
1283 WARN("fcb %p: refcount now %i (subvol %I64x, inode %I64x)\n", fcb2, rc, fcb2->subvol->id, fcb2->inode);
1284#else
1286#endif
1287
1288 *pfcb = fcb2;
1289 reap_fcb(fcb);
1290 release_fcb_lock(Vcb);
1291 return STATUS_SUCCESS;
1292 }
1293 }
1294 } else if (fcb2->hash > hash) {
1295 if (deleted_fcb) {
1296 InterlockedIncrement(&deleted_fcb->refcount);
1297 *pfcb = deleted_fcb;
1298 reap_fcb(fcb);
1299 release_fcb_lock(Vcb);
1300 return STATUS_SUCCESS;
1301 }
1302
1303 lastle = le->Blink;
1304 break;
1305 }
1306
1307 le = le->Flink;
1308 }
1309 }
1310
1312 fcb->atts &= ~FILE_ATTRIBUTE_REPARSE_POINT;
1313
1314 if (!Vcb->readonly && !is_subvol_readonly(subvol, Irp)) {
1315 fcb->atts_changed = true;
1317 }
1318 }
1319
1320 if (!lastle) {
1321 uint8_t c = hash >> 24;
1322
1323 if (c != 0xff) {
1324 uint8_t d = c + 1;
1325
1326 do {
1327 if (subvol->fcbs_ptrs[d]) {
1328 lastle = subvol->fcbs_ptrs[d]->Blink;
1329 break;
1330 }
1331
1332 d++;
1333 } while (d != 0);
1334 }
1335 }
1336
1337 if (lastle) {
1338 InsertHeadList(lastle, &fcb->list_entry);
1339
1340 if (lastle == &subvol->fcbs || (CONTAINING_RECORD(lastle, struct _fcb, list_entry)->hash >> 24) != (hash >> 24))
1341 subvol->fcbs_ptrs[hash >> 24] = &fcb->list_entry;
1342 } else {
1344
1345 if (fcb->list_entry.Blink == &subvol->fcbs || (CONTAINING_RECORD(fcb->list_entry.Blink, struct _fcb, list_entry)->hash >> 24) != (hash >> 24))
1346 subvol->fcbs_ptrs[hash >> 24] = &fcb->list_entry;
1347 }
1348 }
1349
1350 if (fcb->inode == SUBVOL_ROOT_INODE && fcb->subvol->id == BTRFS_ROOT_FSTREE && fcb->subvol != Vcb->root_fileref->fcb->subvol)
1352
1353 subvol->fcbs_version++;
1354
1355 InsertTailList(&Vcb->all_fcbs, &fcb->list_entry_all);
1356
1357 release_fcb_lock(Vcb);
1358
1359 fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
1360
1361 *pfcb = fcb;
1362
1363 return STATUS_SUCCESS;
1364}
#define EA_CASE_SENSITIVE
Definition: btrfs_drv.h:105
#define EA_EA
Definition: btrfs_drv.h:102
#define EA_EA_HASH
Definition: btrfs_drv.h:103
#define EA_NTACL_HASH
Definition: btrfs_drv.h:94
#define __S_IFDIR
Definition: btrfs_drv.h:1754
#define EA_NTACL
Definition: btrfs_drv.h:93
#define EA_PROP_COMPRESSION_HASH
Definition: btrfs_drv.h:109
void fcb_get_sd(fcb *fcb, struct _fcb *parent, bool look_for_xattr, PIRP Irp)
Definition: security.c:511
#define EA_DOSATTRIB_HASH
Definition: btrfs_drv.h:97
#define EA_REPARSE_HASH
Definition: btrfs_drv.h:100
#define __S_IFLNK
Definition: btrfs_drv.h:1759
#define EA_REPARSE
Definition: btrfs_drv.h:99
#define EA_PROP_COMPRESSION
Definition: btrfs_drv.h:108
#define EA_DOSATTRIB
Definition: btrfs_drv.h:96
#define EA_CASE_SENSITIVE_HASH
Definition: btrfs_drv.h:106
bool is_extent_unique(device_extension *Vcb, uint64_t address, uint64_t size, PIRP Irp)
Definition: extent-tree.c:1697
@ PropCompression_LZO
Definition: btrfs_drv.h:270
@ PropCompression_Zlib
Definition: btrfs_drv.h:269
@ PropCompression_ZSTD
Definition: btrfs_drv.h:271
bool is_tree_unique(device_extension *Vcb, tree *t, PIRP Irp)
Definition: flushthread.c:3243
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
r parent
Definition: btrfs.c:3010
ULONG get_file_attributes(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t inode, _In_ uint8_t type, _In_ bool dotfile, _In_ bool ignore_xa, _In_opt_ PIRP Irp)
Definition: btrfs.c:2664
r fcbs_version
Definition: btrfs.c:3012
#define TYPE_EXTENT_DATA
Definition: btrfs.h:30
#define TYPE_INODE_EXTREF
Definition: btrfs.h:25
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:76
#define BTRFS_SUBVOL_READONLY
Definition: btrfs.h:109
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:74
#define TYPE_INODE_REF
Definition: btrfs.h:24
NTSTATUS load_dir_children(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, fcb *fcb, bool ignore_size, PIRP Irp)
Definition: create.c:510
NTSYSAPI BOOLEAN WINAPI RtlValidRelativeSecurityDescriptor(PSECURITY_DESCRIPTOR, ULONG, SECURITY_INFORMATION)
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
uint16_t m
Definition: btrfs.h:275
uint8_t data[1]
Definition: btrfs.h:364
uint8_t type
Definition: btrfs.h:363
uint64_t dir
Definition: btrfs.h:381
uint64_t index
Definition: btrfs.h:382
char name[1]
Definition: btrfs.h:384
uint16_t n
Definition: btrfs.h:383
uint64_t index
Definition: btrfs.h:375
char name[1]
Definition: btrfs.h:377
uint16_t n
Definition: btrfs.h:376
uint64_t flags
Definition: btrfs.h:319
bool case_sensitive_set
Definition: btrfs_drv.h:311
LIST_ENTRY * fcbs_ptrs[256]
Definition: btrfs_drv.h:465
LIST_ENTRY fcbs
Definition: btrfs_drv.h:464
ROOT_ITEM root_item
Definition: btrfs_drv.h:455
uint64_t fcbs_version
Definition: btrfs_drv.h:461
tree * tree
Definition: btrfs_drv.h:508
bool dirty
Definition: btrfs_drv.h:278
USHORT namelen
Definition: btrfs_drv.h:276
char data[1]
Definition: btrfs_drv.h:279
USHORT valuelen
Definition: btrfs_drv.h:277
LIST_ENTRY list_entry
Definition: btrfs_drv.h:275

Referenced by check_for_orphans_root(), do_create_snapshot(), get_reparse_tag(), load_stored_free_space_cache(), open_fileref_by_inode(), open_fileref_child(), and remove_free_space_inode().

◆ open_fcb_stream()

static NTSTATUS open_fcb_stream ( _Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension Vcb,
dir_child dc,
fcb parent,
fcb **  pfcb,
PIRP  Irp 
)
static

Definition at line 1366 of file create.c.

1367 {
1368 fcb* fcb;
1369 uint8_t* xattrdata;
1370 uint16_t xattrlen, overhead;
1372 KEY searchkey;
1374 static const char xapref[] = "user.";
1377
1378 xattr.Length = sizeof(xapref) - 1 + dc->utf8.Length;
1379 xattr.MaximumLength = xattr.Length + 1;
1380 xattr.Buffer = ExAllocatePoolWithTag(PagedPool, xattr.MaximumLength, ALLOC_TAG);
1381 if (!xattr.Buffer) {
1382 ERR("out of memory\n");
1384 }
1385
1386 RtlCopyMemory(xattr.Buffer, xapref, sizeof(xapref) - 1);
1387 RtlCopyMemory(&xattr.Buffer[sizeof(xapref) - 1], dc->utf8.Buffer, dc->utf8.Length);
1388 xattr.Buffer[xattr.Length] = 0;
1389
1391 if (!fcb) {
1392 ERR("out of memory\n");
1393 ExFreePool(xattr.Buffer);
1395 }
1396
1397 fcb->Vcb = Vcb;
1398
1399 crc32 = calc_crc32c(0xfffffffe, (uint8_t*)xattr.Buffer, xattr.Length);
1400
1401 if (!get_xattr(Vcb, parent->subvol, parent->inode, xattr.Buffer, crc32, &xattrdata, &xattrlen, Irp)) {
1402 ERR("get_xattr failed\n");
1403 reap_fcb(fcb);
1404 ExFreePool(xattr.Buffer);
1405 return STATUS_INTERNAL_ERROR;
1406 }
1407
1408 fcb->subvol = parent->subvol;
1409 fcb->inode = parent->inode;
1410 fcb->type = parent->type;
1411 fcb->ads = true;
1412 fcb->adshash = crc32;
1413 fcb->adsxattr = xattr;
1414
1415 // find XATTR_ITEM overhead and hence calculate maximum length
1416
1417 searchkey.obj_id = parent->inode;
1418 searchkey.obj_type = TYPE_XATTR_ITEM;
1419 searchkey.offset = crc32;
1420
1421 Status = find_item(Vcb, parent->subvol, &tp, &searchkey, false, Irp);
1422 if (!NT_SUCCESS(Status)) {
1423 ERR("find_item returned %08lx\n", Status);
1424 reap_fcb(fcb);
1425 return Status;
1426 }
1427
1428 if (keycmp(tp.item->key, searchkey)) {
1429 ERR("error - could not find key for xattr\n");
1430 reap_fcb(fcb);
1431 return STATUS_INTERNAL_ERROR;
1432 }
1433
1434 if (tp.item->size < xattrlen) {
1435 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %u\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, xattrlen);
1436 reap_fcb(fcb);
1437 return STATUS_INTERNAL_ERROR;
1438 }
1439
1440 overhead = tp.item->size - xattrlen;
1441
1442 fcb->adsmaxlen = Vcb->superblock.node_size - sizeof(tree_header) - sizeof(leaf_node) - overhead;
1443
1444 fcb->adsdata.Buffer = (char*)xattrdata;
1445 fcb->adsdata.Length = fcb->adsdata.MaximumLength = xattrlen;
1446
1447 fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
1448 fcb->Header.AllocationSize.QuadPart = xattrlen;
1449 fcb->Header.FileSize.QuadPart = xattrlen;
1450 fcb->Header.ValidDataLength.QuadPart = xattrlen;
1451
1452 TRACE("stream found: size = %x, hash = %08x\n", xattrlen, fcb->adshash);
1453
1454 *pfcb = fcb;
1455
1456 return STATUS_SUCCESS;
1457}
#define crc32(crc, buf, len)
Definition: inflate.c:1081
ANSI_STRING adsdata
Definition: btrfs_drv.h:334

Referenced by open_fileref_child().

◆ open_file()

static NTSTATUS open_file ( PDEVICE_OBJECT  DeviceObject,
_Requires_lock_held_(_Curr_->tree_lock) device_extension Vcb,
PIRP  Irp,
LIST_ENTRY rollback,
oplock_context **  opctx 
)
static

Definition at line 4466 of file create.c.

4467 {
4469 ULONG RequestedDisposition;
4470 ULONG options;
4473 USHORT parsed;
4474 ULONG fn_offset = 0;
4475 file_ref *related, *fileref = NULL;
4477 ACCESS_MASK granted_access;
4478 bool loaded_related = false;
4480
4481 Irp->IoStatus.Information = 0;
4482
4483 RequestedDisposition = ((IrpSp->Parameters.Create.Options >> 24) & 0xff);
4485
4486 if (options & FILE_DIRECTORY_FILE && RequestedDisposition == FILE_SUPERSEDE) {
4487 WARN("error - supersede requested with FILE_DIRECTORY_FILE\n");
4489 }
4490
4492
4493 if (!FileObject) {
4494 ERR("FileObject was NULL\n");
4496 }
4497
4498 if (FileObject->RelatedFileObject && FileObject->RelatedFileObject->FsContext2) {
4499 struct _ccb* relatedccb = FileObject->RelatedFileObject->FsContext2;
4500
4501 related = relatedccb->fileref;
4502 } else
4503 related = NULL;
4504
4506
4507 switch (RequestedDisposition) {
4508 case FILE_SUPERSEDE:
4509 TRACE("requested disposition: FILE_SUPERSEDE\n");
4510 break;
4511
4512 case FILE_CREATE:
4513 TRACE("requested disposition: FILE_CREATE\n");
4514 break;
4515
4516 case FILE_OPEN:
4517 TRACE("requested disposition: FILE_OPEN\n");
4518 break;
4519
4520 case FILE_OPEN_IF:
4521 TRACE("requested disposition: FILE_OPEN_IF\n");
4522 break;
4523
4524 case FILE_OVERWRITE:
4525 TRACE("requested disposition: FILE_OVERWRITE\n");
4526 break;
4527
4528 case FILE_OVERWRITE_IF:
4529 TRACE("requested disposition: FILE_OVERWRITE_IF\n");
4530 break;
4531
4532 default:
4533 ERR("unknown disposition: %lx\n", RequestedDisposition);
4535 goto exit;
4536 }
4537
4538 fn = FileObject->FileName;
4539
4540 TRACE("(%.*S)\n", (int)(fn.Length / sizeof(WCHAR)), fn.Buffer);
4541 TRACE("FileObject = %p\n", FileObject);
4542
4543 if (Vcb->readonly && (RequestedDisposition == FILE_SUPERSEDE || RequestedDisposition == FILE_CREATE || RequestedDisposition == FILE_OVERWRITE)) {
4545 goto exit;
4546 }
4547
4549 if (RequestedDisposition != FILE_OPEN) {
4550 WARN("FILE_OPEN_BY_FILE_ID not supported for anything other than FILE_OPEN\n");
4552 goto exit;
4553 }
4554
4555 if (fn.Length == sizeof(uint64_t)) {
4557
4558 if (!related) {
4559 WARN("cannot open by short file ID unless related fileref also provided"\n);
4561 goto exit;
4562 }
4563
4564 inode = (*(uint64_t*)fn.Buffer) & 0xffffffffff;
4565
4566 if (related->fcb == Vcb->root_fileref->fcb && inode == 0)
4567 inode = Vcb->root_fileref->fcb->inode;
4568
4569 if (inode == 0) { // we use 0 to mean the parent of a subvolume
4570 fileref = related->parent;
4573 } else
4575
4576 goto loaded;
4577 } else if (fn.Length == sizeof(FILE_ID_128)) {
4578 uint64_t inode, subvol_id;
4579 root* subvol = NULL;
4580
4581 RtlCopyMemory(&inode, fn.Buffer, sizeof(uint64_t));
4582 RtlCopyMemory(&subvol_id, (uint8_t*)fn.Buffer + sizeof(uint64_t), sizeof(uint64_t));
4583
4584 if (subvol_id == BTRFS_ROOT_FSTREE || (subvol_id >= 0x100 && subvol_id < 0x8000000000000000)) {
4585 LIST_ENTRY* le = Vcb->roots.Flink;
4586 while (le != &Vcb->roots) {
4588
4589 if (r->id == subvol_id) {
4590 subvol = r;
4591 break;
4592 }
4593
4594 le = le->Flink;
4595 }
4596 }
4597
4598 if (!subvol) {
4599 WARN("subvol %I64x not found\n", subvol_id);
4601 } else
4603
4604 goto loaded;
4605 } else {
4606 WARN("invalid ID size for FILE_OPEN_BY_FILE_ID\n");
4608 goto exit;
4609 }
4610 }
4611
4612 if (related && fn.Length != 0 && fn.Buffer[0] == '\\') {
4614 goto exit;
4615 }
4616
4617 if (!related && RequestedDisposition != FILE_OPEN && !(IrpSp->Flags & SL_OPEN_TARGET_DIRECTORY)) {
4618 ULONG fnoff;
4619
4620 Status = open_fileref(Vcb, &related, &fn, NULL, true, &parsed, &fnoff,
4621 pool_type, IrpSp->Flags & SL_CASE_SENSITIVE, Irp);
4622
4625 else if (Status == STATUS_REPARSE)
4626 fileref = related;
4627 else if (NT_SUCCESS(Status)) {
4628 fnoff *= sizeof(WCHAR);
4629 fnoff += (related->dc ? related->dc->name.Length : 0) + sizeof(WCHAR);
4630
4631 if (related->fcb->atts & FILE_ATTRIBUTE_REPARSE_POINT) {
4633 fileref = related;
4634 parsed = (USHORT)fnoff - sizeof(WCHAR);
4635 } else {
4636 fn.Buffer = &fn.Buffer[fnoff / sizeof(WCHAR)];
4637 fn.Length -= (USHORT)fnoff;
4638
4639 Status = open_fileref(Vcb, &fileref, &fn, related, IrpSp->Flags & SL_OPEN_TARGET_DIRECTORY, &parsed, &fn_offset,
4640 pool_type, IrpSp->Flags & SL_CASE_SENSITIVE, Irp);
4641
4642 loaded_related = true;
4643 }
4644 }
4645 } else {
4646 Status = open_fileref(Vcb, &fileref, &fn, related, IrpSp->Flags & SL_OPEN_TARGET_DIRECTORY, &parsed, &fn_offset,
4647 pool_type, IrpSp->Flags & SL_CASE_SENSITIVE, Irp);
4648 }
4649
4650loaded:
4651 if (Status == STATUS_REPARSE) {
4653
4657
4658 if (!NT_SUCCESS(Status)) {
4659 ERR("get_reparse_block returned %08lx\n", Status);
4660
4662 } else {
4664 RtlCopyMemory(&Irp->IoStatus.Information, data, sizeof(ULONG));
4665
4666 data->Reserved = FileObject->FileName.Length - parsed;
4667
4668 Irp->Tail.Overlay.AuxiliaryBuffer = (void*)data;
4669
4671
4672 goto exit;
4673 }
4674 }
4675
4678
4679 if (NT_SUCCESS(Status)) {
4680 if (RequestedDisposition == FILE_CREATE) {
4681 TRACE("file already exists, returning STATUS_OBJECT_NAME_COLLISION\n");
4683
4685
4686 goto exit;
4687 }
4688 } else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
4689 if (RequestedDisposition == FILE_OPEN || RequestedDisposition == FILE_OVERWRITE) {
4690 TRACE("file doesn't exist, returning STATUS_OBJECT_NAME_NOT_FOUND\n");
4691 goto exit;
4692 }
4694 TRACE("open_fileref returned %08lx\n", Status);
4695 goto exit;
4696 } else {
4697 ERR("open_fileref returned %08lx\n", Status);
4698 goto exit;
4699 }
4700
4701 if (NT_SUCCESS(Status)) { // file already exists
4702 Status = open_file2(Vcb, RequestedDisposition, fileref, &granted_access, FileObject, &fn,
4703 options, Irp, rollback, opctx);
4704 } else {
4705 file_ref* existing_file = NULL;
4706
4707 Status = file_create(Irp, Vcb, FileObject, related, loaded_related, &fn, RequestedDisposition, options, &existing_file, rollback);
4708
4709 if (Status == STATUS_OBJECT_NAME_COLLISION) { // already exists
4710 fileref = existing_file;
4711
4712 Status = open_file2(Vcb, RequestedDisposition, fileref, &granted_access, FileObject, &fn,
4713 options, Irp, rollback, opctx);
4714 } else {
4715 Irp->IoStatus.Information = NT_SUCCESS(Status) ? FILE_CREATED : 0;
4716 granted_access = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
4717 }
4718 }
4719
4722
4723exit:
4724 if (loaded_related)
4725 free_fileref(related);
4726
4727 if (Status == STATUS_SUCCESS) {
4728 fcb* fcb2;
4729
4730 IrpSp->Parameters.Create.SecurityContext->AccessState->PreviouslyGrantedAccess |= granted_access;
4731 IrpSp->Parameters.Create.SecurityContext->AccessState->RemainingDesiredAccess &= ~(granted_access | MAXIMUM_ALLOWED);
4732
4733 if (!FileObject->Vpb)
4734 FileObject->Vpb = DeviceObject->Vpb;
4735
4736 fcb2 = FileObject->FsContext;
4737
4738 if (fcb2->ads) {
4739 struct _ccb* ccb2 = FileObject->FsContext2;
4740
4741 fcb2 = ccb2->fileref->parent->fcb;
4742 }
4743
4744 ExAcquireResourceExclusiveLite(fcb2->Header.Resource, true);
4745 fcb_load_csums(Vcb, fcb2, Irp);
4746 ExReleaseResourceLite(fcb2->Header.Resource);
4748 TRACE("returning %08lx\n", Status);
4749
4750 return Status;
4751}
static NTSTATUS open_file2(device_extension *Vcb, ULONG RequestedDisposition, file_ref *fileref, ACCESS_MASK *granted_access, PFILE_OBJECT FileObject, UNICODE_STRING *fn, ULONG options, PIRP Irp, LIST_ENTRY *rollback, oplock_context **opctx)
Definition: create.c:3936
static NTSTATUS get_reparse_block(fcb *fcb, uint8_t **data)
Definition: create.c:3425
static __inline void debug_create_options(ULONG RequestedOptions)
Definition: create.c:3300
static void fcb_load_csums(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, fcb *fcb, PIRP Irp)
Definition: create.c:3547
NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, root *subvol, uint64_t inode, file_ref **pfr, PIRP Irp)
Definition: create.c:4136
static NTSTATUS file_create(PIRP Irp, _Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, PFILE_OBJECT FileObject, file_ref *related, bool loaded_related, PUNICODE_STRING fnus, ULONG disposition, ULONG options, file_ref **existing_fileref, LIST_ENTRY *rollback)
Definition: create.c:3007
#define FILE_CREATE
Definition: from_kernel.h:55
#define FILE_OVERWRITE_IF
Definition: from_kernel.h:58
#define FILE_OVERWRITE
Definition: from_kernel.h:57
#define FILE_SUPERSEDE
Definition: from_kernel.h:53
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble n
Definition: glext.h:7729
BOOL loaded
Definition: xmlview.c:54
#define FILE_CREATED
Definition: nt_native.h:770
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
#define STATUS_REPARSE
Definition: ntstatus.h:83
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
* PFILE_OBJECT
Definition: iotypes.h:1998
#define FO_CACHE_SUPPORTED
Definition: iotypes.h:1781

Referenced by _Dispatch_type_().

◆ open_file2()

static NTSTATUS open_file2 ( device_extension Vcb,
ULONG  RequestedDisposition,
file_ref fileref,
ACCESS_MASK granted_access,
PFILE_OBJECT  FileObject,
UNICODE_STRING fn,
ULONG  options,
PIRP  Irp,
LIST_ENTRY rollback,
oplock_context **  opctx 
)
static

Definition at line 3936 of file create.c.

3938 {
3940 file_ref* sf;
3941 bool readonly;
3943
3944 if (RequestedDisposition == FILE_SUPERSEDE || RequestedDisposition == FILE_OVERWRITE || RequestedDisposition == FILE_OVERWRITE_IF) {
3946
3947 if (fileref->fcb->type == BTRFS_TYPE_DIRECTORY || is_subvol_readonly(fileref->fcb->subvol, Irp)) {
3949 goto end;
3950 }
3951
3952 if (Vcb->readonly) {
3954 goto end;
3955 }
3956
3957 zero.QuadPart = 0;
3958 if (!MmCanFileBeTruncated(&fileref->fcb->nonpaged->segment_object, &zero)) {
3960 goto end;
3961 }
3962 }
3963
3964 if (IrpSp->Parameters.Create.SecurityContext->DesiredAccess != 0) {
3965 SeLockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext);
3966
3967 if (!SeAccessCheck((fileref->fcb->ads || fileref->fcb == Vcb->dummy_fcb) ? fileref->parent->fcb->sd : fileref->fcb->sd,
3968 &IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext,
3969 true, IrpSp->Parameters.Create.SecurityContext->DesiredAccess, 0, NULL,
3971 granted_access, &Status)) {
3972 SeUnlockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext);
3973 TRACE("SeAccessCheck failed, returning %08lx\n", Status);
3974 goto end;
3975 }
3976
3977 SeUnlockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext);
3978 } else
3979 *granted_access = 0;
3980
3981 TRACE("deleted = %s\n", fileref->deleted ? "true" : "false");
3982
3983 sf = fileref;
3984 while (sf) {
3985 if (sf->delete_on_close) {
3986 TRACE("could not open as deletion pending\n");
3988 goto end;
3989 }
3990 sf = sf->parent;
3991 }
3992
3993 readonly = (!fileref->fcb->ads && fileref->fcb->atts & FILE_ATTRIBUTE_READONLY && !(IrpSp->Flags & SL_IGNORE_READONLY_ATTRIBUTE)) ||
3994 (fileref->fcb->ads && fileref->parent->fcb->atts & FILE_ATTRIBUTE_READONLY && !(IrpSp->Flags & SL_IGNORE_READONLY_ATTRIBUTE)) ||
3995 is_subvol_readonly(fileref->fcb->subvol, Irp) || fileref->fcb == Vcb->dummy_fcb || Vcb->readonly;
3996
3997 if (options & FILE_DELETE_ON_CLOSE && (fileref == Vcb->root_fileref || readonly)) {
3999 goto end;
4000 }
4001
4002 readonly |= fileref->fcb->inode_item.flags_ro & BTRFS_INODE_RO_VERITY;
4003
4004 if (readonly) {
4005 ACCESS_MASK allowed;
4006
4010
4011 if (!Vcb->readonly && (fileref->fcb == Vcb->dummy_fcb || fileref->fcb->inode == SUBVOL_ROOT_INODE))
4012 allowed |= DELETE;
4013
4014 if (fileref->fcb != Vcb->dummy_fcb && !is_subvol_readonly(fileref->fcb->subvol, Irp) && !Vcb->readonly) {
4016
4017 if (!fileref->fcb->ads && fileref->fcb->type == BTRFS_TYPE_DIRECTORY)
4019 } else if (fileref->fcb->inode == SUBVOL_ROOT_INODE && is_subvol_readonly(fileref->fcb->subvol, Irp) && !Vcb->readonly) {
4020 // We allow a subvolume root to be opened read-write even if its readonly flag is set, so it can be cleared
4021
4022 allowed |= FILE_WRITE_ATTRIBUTES;
4023 }
4024
4025 if (IrpSp->Parameters.Create.SecurityContext->DesiredAccess & MAXIMUM_ALLOWED) {
4026 *granted_access &= allowed;
4027 IrpSp->Parameters.Create.SecurityContext->AccessState->PreviouslyGrantedAccess &= allowed;
4028 } else if (*granted_access & ~allowed) {
4030 goto end;
4031 }
4032
4033 if (RequestedDisposition == FILE_OVERWRITE || RequestedDisposition == FILE_OVERWRITE_IF) {
4034 WARN("cannot overwrite readonly file\n");
4036 goto end;
4037 }
4038 }
4039
4042
4043 /* How reparse points work from the point of view of the filesystem appears to
4044 * undocumented. When returning STATUS_REPARSE, MSDN encourages us to return
4045 * IO_REPARSE in Irp->IoStatus.Information, but that means we have to do our own
4046 * translation. If we instead return the reparse tag in Information, and store
4047 * a pointer to the reparse data buffer in Irp->Tail.Overlay.AuxiliaryBuffer,
4048 * IopSymlinkProcessReparse will do the translation for us. */
4049
4050 Status = get_reparse_block(fileref->fcb, (uint8_t**)&data);
4051 if (!NT_SUCCESS(Status)) {
4052 ERR("get_reparse_block returned %08lx\n", Status);
4054 } else {
4055 Irp->IoStatus.Information = data->ReparseTag;
4056
4057 if (fn->Buffer[(fn->Length / sizeof(WCHAR)) - 1] == '\\')
4058 data->Reserved = sizeof(WCHAR);
4059
4060 Irp->Tail.Overlay.AuxiliaryBuffer = (void*)data;
4061
4063 goto end;
4064 }
4065 }
4066
4067 if (fileref->fcb->type == BTRFS_TYPE_DIRECTORY && !fileref->fcb->ads) {
4070 goto end;
4071 }
4072 } else if (options & FILE_DIRECTORY_FILE) {
4073 TRACE("returning STATUS_NOT_A_DIRECTORY (type = %u)\n", fileref->fcb->type);
4075 goto end;
4076 }
4077
4078 if (fileref->open_count > 0) {
4080
4081 Status = IoCheckShareAccess(*granted_access, IrpSp->Parameters.Create.ShareAccess, FileObject, &fileref->fcb->share_access, false);
4082
4083 if (!NT_SUCCESS(Status)) {
4085 TRACE("IoCheckShareAccess failed, returning %08lx\n", Status);
4086 else
4087 WARN("IoCheckShareAccess failed, returning %08lx\n", Status);
4088
4089 goto end;
4090 }
4091
4093 if (!ctx) {
4094 ERR("out of memory\n");
4096 goto end;
4097 }
4098
4099 ctx->Vcb = Vcb;
4100 ctx->granted_access = *granted_access;
4101 ctx->fileref = fileref;
4102 KeInitializeEvent(&ctx->event, NotificationEvent, false);
4103#ifdef __REACTOS__
4105#else
4107#endif /* __REACTOS__ */
4108 if (Status == STATUS_PENDING) {
4109 *opctx = ctx;
4110 return Status;
4111 }
4112
4113 ExFreePool(ctx);
4114
4115 if (!NT_SUCCESS(Status)) {
4116 WARN("FsRtlCheckOplock returned %08lx\n", Status);
4117 goto end;
4118 }
4119
4121 } else
4122 IoSetShareAccess(*granted_access, IrpSp->Parameters.Create.ShareAccess, FileObject, &fileref->fcb->share_access);
4123
4124 Status = open_file3(Vcb, Irp, *granted_access, fileref, rollback);
4125
4126 if (!NT_SUCCESS(Status))
4128
4129end:
4130 if (!NT_SUCCESS(Status))
4131 free_fileref(fileref);
4132
4133 return Status;
4134}
#define BTRFS_INODE_RO_VERITY
Definition: btrfs.h:107
static void __stdcall oplock_complete(PVOID Context, PIRP Irp)
Definition: create.c:3863
static NTSTATUS open_file3(device_extension *Vcb, PIRP Irp, ACCESS_MASK granted_access, file_ref *fileref, LIST_ENTRY *rollback)
Definition: create.c:3588
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
VOID(NTAPI * POPLOCK_WAIT_COMPLETE_ROUTINE)(_In_ PVOID Context, _In_ PIRP Irp)
Definition: fsrtltypes.h:253
#define SYNCHRONIZE
Definition: nt_native.h:61
#define WRITE_DAC
Definition: nt_native.h:59
#define FILE_READ_DATA
Definition: nt_native.h:628
#define ACCESS_SYSTEM_SECURITY
Definition: nt_native.h:77
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define FILE_LIST_DIRECTORY
Definition: nt_native.h:629
#define FILE_DELETE_CHILD
Definition: nt_native.h:645
#define FILE_READ_EA
Definition: nt_native.h:638
#define FILE_EXECUTE
Definition: nt_native.h:642
#define FILE_TRAVERSE
Definition: nt_native.h:643
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define DELETE
Definition: nt_native.h:57
#define READ_CONTROL
Definition: nt_native.h:58
#define WRITE_OWNER
Definition: nt_native.h:60
#define FILE_WRITE_EA
Definition: nt_native.h:640
@ NotificationEvent
NTSTATUS NTAPI IoCheckShareAccess(IN ACCESS_MASK DesiredAccess, IN ULONG DesiredShareAccess, IN PFILE_OBJECT FileObject, IN PSHARE_ACCESS ShareAccess, IN BOOLEAN Update)
Definition: file.c:3390
VOID NTAPI IoRemoveShareAccess(IN PFILE_OBJECT FileObject, IN PSHARE_ACCESS ShareAccess)
Definition: file.c:3478
VOID NTAPI IoUpdateShareAccess(IN PFILE_OBJECT FileObject, OUT PSHARE_ACCESS ShareAccess)
Definition: file.c:3351
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:322
#define STATUS_USER_MAPPED_FILE
Definition: ntstatus.h:711
NTSTATUS NTAPI FsRtlCheckOplock(IN POPLOCK Oplock, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
Definition: oplock.c:1170
BOOLEAN NTAPI MmCanFileBeTruncated(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER NewFileSize)
Definition: section.c:4255
int zero
Definition: sehframes.cpp:29
uint32_t flags_ro
Definition: btrfs.h:298
bool delete_on_close
Definition: btrfs_drv.h:345
#define STATUS_FILE_IS_A_DIRECTORY
Definition: udferr_usr.h:164
#define STATUS_SHARING_VIOLATION
Definition: udferr_usr.h:154

Referenced by open_file().

◆ open_file3()

static NTSTATUS open_file3 ( device_extension Vcb,
PIRP  Irp,
ACCESS_MASK  granted_access,
file_ref fileref,
LIST_ENTRY rollback 
)
static

Definition at line 3588 of file create.c.

3588 {
3592 ULONG RequestedDisposition = ((IrpSp->Parameters.Create.Options >> 24) & 0xff);
3595 ccb* ccb;
3596
3597 if (granted_access & FILE_WRITE_DATA || options & FILE_DELETE_ON_CLOSE) {
3598 if (!MmFlushImageSection(&fileref->fcb->nonpaged->segment_object, MmFlushForWrite))
3600 }
3601
3602 if (RequestedDisposition == FILE_OVERWRITE || RequestedDisposition == FILE_OVERWRITE_IF || RequestedDisposition == FILE_SUPERSEDE) {
3603 ULONG defda, oldatts, filter;
3606
3607 if (!fileref->fcb->ads && (IrpSp->Parameters.Create.FileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != ((fileref->fcb->atts & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN))))
3608 return STATUS_ACCESS_DENIED;
3609
3610 if (fileref->fcb->ads) {
3611 Status = stream_set_end_of_file_information(Vcb, 0, fileref->fcb, fileref, false);
3612 if (!NT_SUCCESS(Status)) {
3613 ERR("stream_set_end_of_file_information returned %08lx\n", Status);
3614 return Status;
3615 }
3616 } else {
3617 Status = truncate_file(fileref->fcb, 0, Irp, rollback);
3618 if (!NT_SUCCESS(Status)) {
3619 ERR("truncate_file returned %08lx\n", Status);
3620 return Status;
3621 }
3622 }
3623
3624 if (Irp->Overlay.AllocationSize.QuadPart > 0) {
3625 Status = extend_file(fileref->fcb, fileref, Irp->Overlay.AllocationSize.QuadPart, true, NULL, rollback);
3626
3627 if (!NT_SUCCESS(Status)) {
3628 ERR("extend_file returned %08lx\n", Status);
3629 return Status;
3630 }
3631 }
3632
3633 if (!fileref->fcb->ads) {
3634 LIST_ENTRY* le;
3635
3636 if (Irp->AssociatedIrp.SystemBuffer && IrpSp->Parameters.Create.EaLength > 0) {
3637 ULONG offset;
3639
3640 Status = IoCheckEaBufferValidity(Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.Create.EaLength, &offset);
3641 if (!NT_SUCCESS(Status)) {
3642 ERR("IoCheckEaBufferValidity returned %08lx (error at offset %lu)\n", Status, offset);
3643 return Status;
3644 }
3645
3646 fileref->fcb->ealen = 4;
3647
3648 // capitalize EA name
3649 eainfo = Irp->AssociatedIrp.SystemBuffer;
3650 do {
3651 STRING s;
3652
3653 s.Length = s.MaximumLength = eainfo->EaNameLength;
3654 s.Buffer = eainfo->EaName;
3655
3656 RtlUpperString(&s, &s);
3657
3658 fileref->fcb->ealen += 5 + eainfo->EaNameLength + eainfo->EaValueLength;
3659
3660 if (eainfo->NextEntryOffset == 0)
3661 break;
3662
3663 eainfo = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)eainfo) + eainfo->NextEntryOffset);
3664 } while (true);
3665
3666 if (fileref->fcb->ea_xattr.Buffer)
3667 ExFreePool(fileref->fcb->ea_xattr.Buffer);
3668
3669 fileref->fcb->ea_xattr.Buffer = ExAllocatePoolWithTag(pool_type, IrpSp->Parameters.Create.EaLength, ALLOC_TAG);
3670 if (!fileref->fcb->ea_xattr.Buffer) {
3671 ERR("out of memory\n");
3673 }
3674
3675 fileref->fcb->ea_xattr.Length = fileref->fcb->ea_xattr.MaximumLength = (USHORT)IrpSp->Parameters.Create.EaLength;
3676 RtlCopyMemory(fileref->fcb->ea_xattr.Buffer, Irp->AssociatedIrp.SystemBuffer, fileref->fcb->ea_xattr.Length);
3677 } else {
3678 if (fileref->fcb->ea_xattr.Length > 0) {
3679 ExFreePool(fileref->fcb->ea_xattr.Buffer);
3680 fileref->fcb->ea_xattr.Buffer = NULL;
3681 fileref->fcb->ea_xattr.Length = fileref->fcb->ea_xattr.MaximumLength = 0;
3682
3683 fileref->fcb->ea_changed = true;
3684 fileref->fcb->ealen = 0;
3685 }
3686 }
3687
3688 // remove streams and send notifications
3689 le = fileref->fcb->dir_children_index.Flink;
3690 while (le != &fileref->fcb->dir_children_index) {
3691 dir_child* dc = CONTAINING_RECORD(le, dir_child, list_entry_index);
3692 LIST_ENTRY* le2 = le->Flink;
3693
3694 if (dc->index == 0) {
3695 if (!dc->fileref) {
3696 file_ref* fr2;
3697
3698 Status = open_fileref_child(Vcb, fileref, &dc->name, true, true, true, PagedPool, &fr2, NULL);
3699 if (!NT_SUCCESS(Status))
3700 WARN("open_fileref_child returned %08lx\n", Status);
3701 }
3702
3703 if (dc->fileref) {
3705
3706 Status = delete_fileref(dc->fileref, NULL, false, NULL, rollback);
3707 if (!NT_SUCCESS(Status)) {
3708 ERR("delete_fileref returned %08lx\n", Status);
3709 return Status;
3710 }
3711 }
3712 } else
3713 break;
3714
3715 le = le2;
3716 }
3717 }
3718
3721
3723
3724 if (fileref->fcb->ads) {
3725 fileref->parent->fcb->inode_item.st_mtime = now;
3726 fileref->parent->fcb->inode_item_changed = true;
3727 mark_fcb_dirty(fileref->parent->fcb);
3728
3730 } else {
3731 mark_fcb_dirty(fileref->fcb);
3732
3733 oldatts = fileref->fcb->atts;
3734
3735 defda = get_file_attributes(Vcb, fileref->fcb->subvol, fileref->fcb->inode, fileref->fcb->type,
3736 fileref->dc && fileref->dc->name.Length >= sizeof(WCHAR) && fileref->dc->name.Buffer[0] == '.', true, Irp);
3737
3738 if (RequestedDisposition == FILE_SUPERSEDE)
3739 fileref->fcb->atts = IrpSp->Parameters.Create.FileAttributes | FILE_ATTRIBUTE_ARCHIVE;
3740 else
3741 fileref->fcb->atts |= IrpSp->Parameters.Create.FileAttributes | FILE_ATTRIBUTE_ARCHIVE;
3742
3743 if (fileref->fcb->atts != oldatts) {
3744 fileref->fcb->atts_changed = true;
3745 fileref->fcb->atts_deleted = IrpSp->Parameters.Create.FileAttributes == defda;
3747 }
3748
3749 fileref->fcb->inode_item.transid = Vcb->superblock.generation;
3750 fileref->fcb->inode_item.sequence++;
3751 fileref->fcb->inode_item.st_ctime = now;
3752 fileref->fcb->inode_item.st_mtime = now;
3753 fileref->fcb->inode_item_changed = true;
3754
3756 }
3757 } else {
3758 if (options & FILE_NO_EA_KNOWLEDGE && fileref->fcb->ea_xattr.Length > 0) {
3760
3761 do {
3762 if (ffei->Flags & FILE_NEED_EA) {
3763 WARN("returning STATUS_ACCESS_DENIED as no EA knowledge\n");
3764
3765 return STATUS_ACCESS_DENIED;
3766 }
3767
3768 if (ffei->NextEntryOffset == 0)
3769 break;
3770
3771 ffei = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)ffei) + ffei->NextEntryOffset);
3772 } while (true);
3773 }
3774 }
3775
3776 FileObject->FsContext = fileref->fcb;
3777
3779 if (!ccb) {
3780 ERR("out of memory\n");
3781
3783 }
3784
3785 RtlZeroMemory(ccb, sizeof(*ccb));
3786
3788 ccb->NodeSize = sizeof(*ccb);
3789 ccb->disposition = RequestedDisposition;
3790 ccb->options = options;
3791 ccb->query_dir_offset = 0;
3793 ccb->has_wildcard = false;
3794 ccb->specific_file = false;
3795 ccb->access = granted_access;
3797 ccb->reserving = false;
3799
3800 ccb->fileref = fileref;
3801
3802 FileObject->FsContext2 = ccb;
3803 FileObject->SectionObjectPointer = &fileref->fcb->nonpaged->segment_object;
3804
3805 switch (RequestedDisposition) {
3806 case FILE_SUPERSEDE:
3807 Irp->IoStatus.Information = FILE_SUPERSEDED;
3808 break;
3809
3810 case FILE_OPEN:
3811 case FILE_OPEN_IF:
3812 Irp->IoStatus.Information = FILE_OPENED;
3813 break;
3814
3815 case FILE_OVERWRITE:
3816 case FILE_OVERWRITE_IF:
3817 Irp->IoStatus.Information = FILE_OVERWRITTEN;
3818 break;
3819 }
3820
3821 // Make sure paging files don't have any extents marked as being prealloc,
3822 // as this would mean we'd have to lock exclusively when writing.
3824 LIST_ENTRY* le;
3825 bool changed = false;
3826
3827 ExAcquireResourceExclusiveLite(fileref->fcb->Header.Resource, true);
3828
3829 le = fileref->fcb->extents.Flink;
3830
3831 while (le != &fileref->fcb->extents) {
3833
3834 if (ext->extent_data.type == EXTENT_TYPE_PREALLOC) {
3835 ext->extent_data.type = EXTENT_TYPE_REGULAR;
3836 changed = true;
3837 }
3838
3839 le = le->Flink;
3840 }
3841
3842 ExReleaseResourceLite(fileref->fcb->Header.Resource);
3843
3844 if (changed) {
3845 fileref->fcb->extents_changed = true;
3846 mark_fcb_dirty(fileref->fcb);
3847 }
3848
3849 fileref->fcb->Header.Flags2 |= FSRTL_FLAG2_IS_PAGING_FILE;
3850 }
3851
3852#ifdef DEBUG_FCB_REFCOUNTS
3853 LONG oc = InterlockedIncrement(&fileref->open_count);
3854 ERR("fileref %p: open_count now %i\n", fileref, oc);
3855#else
3857#endif
3858 InterlockedIncrement(&Vcb->open_files);
3859
3860 return STATUS_SUCCESS;
3861}
NTSTATUS stream_set_end_of_file_information(device_extension *Vcb, uint16_t end, fcb *fcb, file_ref *fileref, bool advance_only)
Definition: fileinfo.c:3170
NTSTATUS NTSTATUS NTSTATUS truncate_file(fcb *fcb, uint64_t end, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
NTSTATUS delete_fileref(_In_ file_ref *fileref, _In_opt_ PFILE_OBJECT FileObject, _In_ bool make_orphan, _In_opt_ PIRP Irp, _In_ LIST_ENTRY *rollback)
Definition: btrfs.c:2270
NTSTATUS open_fileref_child(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension *Vcb, _In_ file_ref *sf, _In_ PUNICODE_STRING name, _In_ bool case_sensitive, _In_ bool lastpart, _In_ bool streampart, _In_ POOL_TYPE pooltype, _Out_ file_ref **psf2, _In_opt_ PIRP Irp)
Definition: create.c:1459
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glext.h:7005
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
#define FILE_OVERWRITTEN
Definition: nt_native.h:771
#define FILE_SUPERSEDED
Definition: nt_native.h:768
BOOLEAN NTAPI MmFlushImageSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN MMFLUSH_TYPE FlushType)
Definition: section.c:4356
bool atts_deleted
Definition: btrfs_drv.h:322
bool extents_changed
Definition: btrfs_drv.h:323
#define FILE_NOTIFY_CHANGE_SIZE
#define FILE_ACTION_REMOVED_STREAM
#define FILE_NOTIFY_CHANGE_ATTRIBUTES
#define FILE_NEED_EA

Referenced by open_file2(), and oplock_complete().

◆ open_fileref()

NTSTATUS open_fileref ( _Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension Vcb,
_Out_ file_ref **  pfr,
_In_ PUNICODE_STRING  fnus,
_In_opt_ file_ref related,
_In_ bool  parent,
_Out_opt_ USHORT parsed,
_Out_opt_ ULONG fn_offset,
_In_ POOL_TYPE  pooltype,
_In_ bool  case_sensitive,
_In_opt_ PIRP  Irp 
)

Definition at line 1690 of file create.c.

1692 {
1693 UNICODE_STRING fnus2;
1694 file_ref *dir, *sf, *sf2;
1696 bool has_stream = false;
1698 LIST_ENTRY* le;
1699
1700 TRACE("(%p, %p, %p, %u, %p)\n", Vcb, pfr, related, parent, parsed);
1701
1702 if (Vcb->removing || Vcb->locked)
1703 return STATUS_ACCESS_DENIED;
1704
1705 fnus2 = *fnus;
1706
1707 if (fnus2.Length < sizeof(WCHAR) && !related) {
1708 ERR("error - fnus was too short\n");
1709 return STATUS_INTERNAL_ERROR;
1710 }
1711
1712 if (related && fnus->Length == 0) {
1714
1715 *pfr = related;
1716 return STATUS_SUCCESS;
1717 }
1718
1719 if (related) {
1720 dir = related;
1721 } else {
1722 if (fnus2.Buffer[0] != '\\') {
1723 ERR("error - filename %.*S did not begin with \\\n", (int)(fnus2.Length / sizeof(WCHAR)), fnus2.Buffer);
1725 }
1726
1727 // if path starts with two backslashes, ignore one of them
1728 if (fnus2.Length >= 2 * sizeof(WCHAR) && fnus2.Buffer[1] == '\\') {
1729 fnus2.Buffer++;
1730 fnus2.Length -= sizeof(WCHAR);
1731 fnus2.MaximumLength -= sizeof(WCHAR);
1732 }
1733
1734 if (fnus2.Length == sizeof(WCHAR)) {
1735 if (Vcb->root_fileref->open_count == 0 && !(Vcb->Vpb->Flags & VPB_MOUNTED)) // don't allow root to be opened on unmounted FS
1737
1738 increase_fileref_refcount(Vcb->root_fileref);
1739 *pfr = Vcb->root_fileref;
1740
1741 if (fn_offset)
1742 *fn_offset = 0;
1743
1744 return STATUS_SUCCESS;
1745 } else if (fnus2.Length >= 2 * sizeof(WCHAR) && fnus2.Buffer[1] == '\\')
1747
1748 dir = Vcb->root_fileref;
1749
1750 fnus2.Buffer++;
1751 fnus2.Length -= sizeof(WCHAR);
1752 fnus2.MaximumLength -= sizeof(WCHAR);
1753 }
1754
1755 if (dir->fcb->type != BTRFS_TYPE_DIRECTORY && (fnus->Length < sizeof(WCHAR) || fnus->Buffer[0] != ':')) {
1756 WARN("passed related fileref which isn't a directory (fnus = %.*S)\n",
1757 (int)(fnus->Length / sizeof(WCHAR)), fnus->Buffer);
1759 }
1760
1762
1763 if (fnus->Length != 0 &&
1764 (fnus->Length != sizeof(datastring) - sizeof(WCHAR) || RtlCompareMemory(fnus->Buffer, datastring, sizeof(datastring) - sizeof(WCHAR)) != sizeof(datastring) - sizeof(WCHAR))) {
1765 Status = split_path(Vcb, &fnus2, &parts, &has_stream);
1766 if (!NT_SUCCESS(Status)) {
1767 ERR("split_path returned %08lx\n", Status);
1768 return Status;
1769 }
1770 }
1771
1772 sf = dir;
1774
1775 if (parent && !IsListEmpty(&parts)) {
1776 name_bit* nb;
1777
1779 ExFreeToPagedLookasideList(&Vcb->name_bit_lookaside, nb);
1780
1781 if (has_stream && !IsListEmpty(&parts)) {
1783 ExFreeToPagedLookasideList(&Vcb->name_bit_lookaside, nb);
1784
1785 has_stream = false;
1786 }
1787 }
1788
1789 if (IsListEmpty(&parts)) {
1791 *pfr = dir;
1792
1793 if (fn_offset)
1794 *fn_offset = 0;
1795
1796 goto end2;
1797 }
1798
1799 le = parts.Flink;
1800 do {
1802 bool lastpart = le->Flink == &parts || (has_stream && le->Flink->Flink == &parts);
1803 bool streampart = has_stream && le->Flink == &parts;
1804 bool cs = case_sensitive;
1805
1806 if (!cs) {
1807 if (streampart && sf->parent)
1808 cs = sf->parent->fcb->case_sensitive;
1809 else
1810 cs = sf->fcb->case_sensitive;
1811 }
1812
1813 Status = open_fileref_child(Vcb, sf, &nb->us, cs, lastpart, streampart, pooltype, &sf2, Irp);
1814
1815 if (!NT_SUCCESS(Status)) {
1817 TRACE("open_fileref_child returned %08lx\n", Status);
1818 else
1819 ERR("open_fileref_child returned %08lx\n", Status);
1820
1821 goto end;
1822 }
1823
1824 if (le->Flink == &parts) { // last entry
1825 if (fn_offset) {
1826 if (has_stream)
1828
1829 *fn_offset = (ULONG)(nb->us.Buffer - fnus->Buffer);
1830 }
1831
1832 break;
1833 }
1834
1837
1838 if (parsed) {
1840
1841 *parsed = (USHORT)(nb2->us.Buffer - fnus->Buffer - 1) * sizeof(WCHAR);
1842 }
1843
1844 break;
1845 }
1846
1847 free_fileref(sf);
1848 sf = sf2;
1849
1850 le = le->Flink;
1851 } while (le != &parts);
1852
1853 if (Status != STATUS_REPARSE)
1855 *pfr = sf2;
1856
1857end:
1858 free_fileref(sf);
1859
1860 while (!IsListEmpty(&parts)) {
1862 ExFreeToPagedLookasideList(&Vcb->name_bit_lookaside, nb);
1863 }
1864
1865end2:
1866 TRACE("returning %08lx\n", Status);
1867
1868 return Status;
1869}
unsigned int dir
Definition: maze.c:112
static const WCHAR datastring[]
Definition: create.c:30
static NTSTATUS split_path(device_extension *Vcb, PUNICODE_STRING path, LIST_ENTRY *parts, bool *stream)
Definition: create.c:321
#define RemoveTailList(ListHead)
Definition: env_spec_w32.h:975
#define cs
Definition: i386-dis.c:442
static const D3D_BLOB_PART parts[]
Definition: blob.c:76
UNICODE_STRING us
Definition: btrfs_drv.h:955

Referenced by create_snapshot(), create_stream(), create_subvol(), file_create(), open_file(), set_link_information(), and set_rename_information().

◆ open_fileref_by_inode()

NTSTATUS open_fileref_by_inode ( _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension Vcb,
root subvol,
uint64_t  inode,
file_ref **  pfr,
PIRP  Irp 
)

Definition at line 4136 of file create.c.

4137 {
4139 fcb* fcb;
4140 uint64_t parent = 0;
4142 bool hl_alloc = false;
4143 file_ref *parfr, *fr;
4144
4145 Status = open_fcb(Vcb, subvol, inode, 0, NULL, true, NULL, &fcb, PagedPool, Irp);
4146 if (!NT_SUCCESS(Status)) {
4147 ERR("open_fcb returned %08lx\n", Status);
4148 return Status;
4149 }
4150
4151 ExAcquireResourceSharedLite(fcb->Header.Resource, true);
4152
4153 if (fcb->inode_item.st_nlink == 0 || fcb->deleted) {
4154 ExReleaseResourceLite(fcb->Header.Resource);
4155 free_fcb(fcb);
4157 }
4158
4159 if (fcb->fileref) {
4160 *pfr = fcb->fileref;
4162 free_fcb(fcb);
4163 ExReleaseResourceLite(fcb->Header.Resource);
4164 return STATUS_SUCCESS;
4165 }
4166
4167 if (IsListEmpty(&fcb->hardlinks)) {
4168 ExReleaseResourceLite(fcb->Header.Resource);
4169
4170 ExAcquireResourceSharedLite(&Vcb->dirty_filerefs_lock, true);
4171
4172 if (!IsListEmpty(&Vcb->dirty_filerefs)) {
4173 LIST_ENTRY* le = Vcb->dirty_filerefs.Flink;
4174 while (le != &Vcb->dirty_filerefs) {
4175 fr = CONTAINING_RECORD(le, file_ref, list_entry_dirty);
4176
4177 if (fr->fcb == fcb) {
4178 ExReleaseResourceLite(&Vcb->dirty_filerefs_lock);
4180 free_fcb(fcb);
4181 *pfr = fr;
4182 return STATUS_SUCCESS;
4183 }
4184
4185 le = le->Flink;
4186 }
4187 }
4188
4189 ExReleaseResourceLite(&Vcb->dirty_filerefs_lock);
4190
4191 {
4192 KEY searchkey;
4194
4195 searchkey.obj_id = fcb->inode;
4196 searchkey.obj_type = TYPE_INODE_REF;
4197 searchkey.offset = 0;
4198
4199 Status = find_item(Vcb, subvol, &tp, &searchkey, false, Irp);
4200 if (!NT_SUCCESS(Status)) {
4201 ERR("find_item returned %08lx\n", Status);
4202 free_fcb(fcb);
4203 return Status;
4204 }
4205
4206 do {
4207 traverse_ptr next_tp;
4208
4210 break;
4211
4212 if (tp.item->key.obj_id == fcb->inode) {
4213 if (tp.item->key.obj_type == TYPE_INODE_REF) {
4214 INODE_REF* ir = (INODE_REF*)tp.item->data;
4215
4216 if (tp.item->size < offsetof(INODE_REF, name[0]) || tp.item->size < offsetof(INODE_REF, name[0]) + ir->n) {
4217 ERR("INODE_REF was too short\n");
4218 free_fcb(fcb);
4219 return STATUS_INTERNAL_ERROR;
4220 }
4221
4223
4224 Status = utf8_to_utf16(NULL, 0, &stringlen, ir->name, ir->n);
4225 if (!NT_SUCCESS(Status)) {
4226 ERR("utf8_to_utf16 1 returned %08lx\n", Status);
4227 free_fcb(fcb);
4228 return Status;
4229 }
4230
4231 name.Length = name.MaximumLength = (uint16_t)stringlen;
4232
4233 if (stringlen == 0)
4234 name.Buffer = NULL;
4235 else {
4236 name.Buffer = ExAllocatePoolWithTag(PagedPool, name.MaximumLength, ALLOC_TAG);
4237
4238 if (!name.Buffer) {
4239 ERR("out of memory\n");
4240 free_fcb(fcb);
4242 }
4243
4244 Status = utf8_to_utf16(name.Buffer, stringlen, &stringlen, ir->name, ir->n);
4245 if (!NT_SUCCESS(Status)) {
4246 ERR("utf8_to_utf16 2 returned %08lx\n", Status);
4247 ExFreePool(name.Buffer);
4248 free_fcb(fcb);
4249 return Status;
4250 }
4251
4252 hl_alloc = true;
4253 }
4254
4255 parent = tp.item->key.offset;
4256
4257 break;
4258 } else if (tp.item->key.obj_type == TYPE_INODE_EXTREF) {
4260
4261 if (tp.item->size < offsetof(INODE_EXTREF, name[0]) || tp.item->size < offsetof(INODE_EXTREF, name[0]) + ier->n) {
4262 ERR("INODE_EXTREF was too short\n");
4263 free_fcb(fcb);
4264 return STATUS_INTERNAL_ERROR;
4265 }
4266
4268
4269 Status = utf8_to_utf16(NULL, 0, &stringlen, ier->name, ier->n);
4270 if (!NT_SUCCESS(Status)) {
4271 ERR("utf8_to_utf16 1 returned %08lx\n", Status);
4272 free_fcb(fcb);
4273 return Status;
4274 }
4275
4276 name.Length = name.MaximumLength = (uint16_t)stringlen;
4277
4278 if (stringlen == 0)
4279 name.Buffer = NULL;
4280 else {
4281 name.Buffer = ExAllocatePoolWithTag(PagedPool, name.MaximumLength, ALLOC_TAG);
4282
4283 if (!name.Buffer) {
4284 ERR("out of memory\n");
4285 free_fcb(fcb);
4287 }
4288
4289 Status = utf8_to_utf16(name.Buffer, stringlen, &stringlen, ier->name, ier->n);
4290 if (!NT_SUCCESS(Status)) {
4291 ERR("utf8_to_utf16 2 returned %08lx\n", Status);
4292 ExFreePool(name.Buffer);
4293 free_fcb(fcb);
4294 return Status;
4295 }
4296
4297 hl_alloc = true;
4298 }
4299
4300 parent = ier->dir;
4301
4302 break;
4303 }
4304 }
4305
4306 if (find_next_item(Vcb, &tp, &next_tp, false, Irp))
4307 tp = next_tp;
4308 else
4309 break;
4310 } while (true);
4311 }
4312
4313 if (parent == 0) {
4314 WARN("trying to open inode with no references\n");
4315 free_fcb(fcb);
4317 }
4318 } else {
4320
4321 name = hl->name;
4322 parent = hl->parent;
4323
4324 ExReleaseResourceLite(fcb->Header.Resource);
4325 }
4326
4327 if (parent == inode) { // subvolume root
4328 KEY searchkey;
4330
4331 searchkey.obj_id = subvol->id;
4332 searchkey.obj_type = TYPE_ROOT_BACKREF;
4333 searchkey.offset = 0xffffffffffffffff;
4334
4335 Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
4336 if (!NT_SUCCESS(Status)) {
4337 ERR("find_item returned %08lx\n", Status);
4338 free_fcb(fcb);
4339 return Status;
4340 }
4341
4342 if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
4343 ROOT_REF* rr = (ROOT_REF*)tp.item->data;
4344 LIST_ENTRY* le;
4345 root* r = NULL;
4347
4348 if (tp.item->size < sizeof(ROOT_REF)) {
4349 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(ROOT_REF));
4350 free_fcb(fcb);
4351 return STATUS_INTERNAL_ERROR;
4352 }
4353
4354 if (tp.item->size < offsetof(ROOT_REF, name[0]) + rr->n) {
4355 ERR("(%I64x,%x,%I64x) was %u bytes, expected %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, offsetof(ROOT_REF, name[0]) + rr->n);
4356 free_fcb(fcb);
4357 return STATUS_INTERNAL_ERROR;
4358 }
4359
4360 le = Vcb->roots.Flink;
4361 while (le != &Vcb->roots) {
4363
4364 if (r2->id == tp.item->key.offset) {
4365 r = r2;
4366 break;
4367 }
4368
4369 le = le->Flink;
4370 }
4371
4372 if (!r) {
4373 ERR("couldn't find subvol %I64x\n", tp.item->key.offset);
4374 free_fcb(fcb);
4375 return STATUS_INTERNAL_ERROR;
4376 }
4377
4378 Status = open_fileref_by_inode(Vcb, r, rr->dir, &parfr, Irp);
4379 if (!NT_SUCCESS(Status)) {
4380 ERR("open_fileref_by_inode returned %08lx\n", Status);
4381 free_fcb(fcb);
4382 return Status;
4383 }
4384
4385 Status = utf8_to_utf16(NULL, 0, &stringlen, rr->name, rr->n);
4386 if (!NT_SUCCESS(Status)) {
4387 ERR("utf8_to_utf16 1 returned %08lx\n", Status);
4388 free_fcb(fcb);
4389 return Status;
4390 }
4391
4392 name.Length = name.MaximumLength = (uint16_t)stringlen;
4393
4394 if (stringlen == 0)
4395 name.Buffer = NULL;
4396 else {
4397 if (hl_alloc)
4398 ExFreePool(name.Buffer);
4399
4400 name.Buffer = ExAllocatePoolWithTag(PagedPool, name.MaximumLength, ALLOC_TAG);
4401
4402 if (!name.Buffer) {
4403 ERR("out of memory\n");
4404 free_fcb(fcb);
4406 }
4407
4408 Status = utf8_to_utf16(name.Buffer, stringlen, &stringlen, rr->name, rr->n);
4409 if (!NT_SUCCESS(Status)) {
4410 ERR("utf8_to_utf16 2 returned %08lx\n", Status);
4411 ExFreePool(name.Buffer);
4412 free_fcb(fcb);
4413 return Status;
4414 }
4415
4416 hl_alloc = true;
4417 }
4418 } else {
4419 if (!Vcb->options.no_root_dir && subvol->id == BTRFS_ROOT_FSTREE && Vcb->root_fileref->fcb->subvol != subvol) {
4420 Status = open_fileref_by_inode(Vcb, Vcb->root_fileref->fcb->subvol, SUBVOL_ROOT_INODE, &parfr, Irp);
4421 if (!NT_SUCCESS(Status)) {
4422 ERR("open_fileref_by_inode returned %08lx\n", Status);
4423 free_fcb(fcb);
4424 return Status;
4425 }
4426
4427 name.Length = name.MaximumLength = sizeof(root_dir_utf16) - sizeof(WCHAR);
4428 name.Buffer = (WCHAR*)root_dir_utf16;
4429 } else {
4430 ERR("couldn't find parent for subvol %I64x\n", subvol->id);
4431 free_fcb(fcb);
4432 return STATUS_INTERNAL_ERROR;
4433 }
4434 }
4435 } else {
4436 Status = open_fileref_by_inode(Vcb, subvol, parent, &parfr, Irp);
4437 if (!NT_SUCCESS(Status)) {
4438 ERR("open_fileref_by_inode returned %08lx\n", Status);
4439 free_fcb(fcb);
4440 return Status;
4441 }
4442 }
4443
4444 Status = open_fileref_child(Vcb, parfr, &name, true, true, false, PagedPool, &fr, Irp);
4445
4446 if (hl_alloc)
4447 ExFreePool(name.Buffer);
4448
4449 if (!NT_SUCCESS(Status)) {
4450 ERR("open_fileref_child returned %08lx\n", Status);
4451
4452 free_fcb(fcb);
4453 free_fileref(parfr);
4454
4455 return Status;
4456 }
4457
4458 *pfr = fr;
4459
4460 free_fcb(fcb);
4461 free_fileref(parfr);
4462
4463 return STATUS_SUCCESS;
4464}
#define TYPE_ROOT_BACKREF
Definition: btrfs.h:33
NTSTATUS open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, root *subvol, uint64_t inode, uint8_t type, PANSI_STRING utf8, bool always_add_hl, fcb *parent, fcb **pfcb, POOL_TYPE pooltype, PIRP Irp)
Definition: create.c:706
uint64_t dir
Definition: btrfs.h:462
char name[1]
Definition: btrfs.h:465
uint16_t n
Definition: btrfs.h:464

Referenced by fill_in_hard_link_full_id_information(), fill_in_hard_link_information(), get_subvol_path(), open_file(), open_fileref_by_inode(), and send_notification_fcb().

◆ open_fileref_child()

NTSTATUS open_fileref_child ( _Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension Vcb,
_In_ file_ref sf,
_In_ PUNICODE_STRING  name,
_In_ bool  case_sensitive,
_In_ bool  lastpart,
_In_ bool  streampart,
_In_ POOL_TYPE  pooltype,
_Out_ file_ref **  psf2,
_In_opt_ PIRP  Irp 
)

Definition at line 1459 of file create.c.

1461 {
1463 file_ref* sf2;
1464
1465 if (sf->fcb == Vcb->dummy_fcb)
1467
1468 if (streampart) {
1469 bool locked = false;
1470 LIST_ENTRY* le;
1471 UNICODE_STRING name_uc;
1472 dir_child* dc = NULL;
1473 fcb* fcb;
1474 struct _fcb* duff_fcb = NULL;
1475 file_ref* duff_fr = NULL;
1476
1477 if (!case_sensitive) {
1478 Status = RtlUpcaseUnicodeString(&name_uc, name, true);
1479 if (!NT_SUCCESS(Status)) {
1480 ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
1481 return Status;
1482 }
1483 }
1484
1485 if (!ExIsResourceAcquiredSharedLite(&sf->fcb->nonpaged->dir_children_lock)) {
1486 ExAcquireResourceSharedLite(&sf->fcb->nonpaged->dir_children_lock, true);
1487 locked = true;
1488 }
1489
1490 le = sf->fcb->dir_children_index.Flink;
1491 while (le != &sf->fcb->dir_children_index) {
1492 dir_child* dc2 = CONTAINING_RECORD(le, dir_child, list_entry_index);
1493
1494 if (dc2->index == 0) {
1495 if ((case_sensitive && dc2->name.Length == name->Length && RtlCompareMemory(dc2->name.Buffer, name->Buffer, dc2->name.Length) == dc2->name.Length) ||
1496 (!case_sensitive && dc2->name_uc.Length == name_uc.Length && RtlCompareMemory(dc2->name_uc.Buffer, name_uc.Buffer, dc2->name_uc.Length) == dc2->name_uc.Length)
1497 ) {
1498 dc = dc2;
1499 break;
1500 }
1501 } else
1502 break;
1503
1504 le = le->Flink;
1505 }
1506
1507 if (!dc) {
1508 if (locked)
1509 ExReleaseResourceLite(&sf->fcb->nonpaged->dir_children_lock);
1510
1511 if (!case_sensitive)
1512 ExFreePool(name_uc.Buffer);
1513
1515 }
1516
1517 if (dc->fileref) {
1518 if (locked)
1519 ExReleaseResourceLite(&sf->fcb->nonpaged->dir_children_lock);
1520
1521 if (!case_sensitive)
1522 ExFreePool(name_uc.Buffer);
1523
1524 increase_fileref_refcount(dc->fileref);
1525 *psf2 = dc->fileref;
1526 return STATUS_SUCCESS;
1527 }
1528
1529 if (locked)
1530 ExReleaseResourceLite(&sf->fcb->nonpaged->dir_children_lock);
1531
1532 if (!case_sensitive)
1533 ExFreePool(name_uc.Buffer);
1534
1535 Status = open_fcb_stream(Vcb, dc, sf->fcb, &fcb, Irp);
1536 if (!NT_SUCCESS(Status)) {
1537 ERR("open_fcb_stream returned %08lx\n", Status);
1538 return Status;
1539 }
1540
1541 fcb->hash = sf->fcb->hash;
1542
1543 acquire_fcb_lock_exclusive(Vcb);
1544
1545 if (sf->fcb->subvol->fcbs_ptrs[fcb->hash >> 24]) {
1546 le = sf->fcb->subvol->fcbs_ptrs[fcb->hash >> 24];
1547
1548 while (le != &sf->fcb->subvol->fcbs) {
1549 struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
1550
1551 if (fcb2->inode == fcb->inode) {
1552 if (fcb2->ads && fcb2->adshash == fcb->adshash) { // FIXME - handle hash collisions
1553 duff_fcb = fcb;
1554 fcb = fcb2;
1555 break;
1556 }
1557 } else if (fcb2->hash > fcb->hash)
1558 break;
1559
1560 le = le->Flink;
1561 }
1562 }
1563
1564 if (!duff_fcb) {
1565 InsertHeadList(&sf->fcb->list_entry, &fcb->list_entry);
1566 InsertTailList(&Vcb->all_fcbs, &fcb->list_entry_all);
1567 fcb->subvol->fcbs_version++;
1568 }
1569
1570 release_fcb_lock(Vcb);
1571
1572 if (duff_fcb) {
1573 reap_fcb(duff_fcb);
1575 }
1576
1577 sf2 = create_fileref(Vcb);
1578 if (!sf2) {
1579 ERR("out of memory\n");
1580 free_fcb(fcb);
1582 }
1583
1584 ExAcquireResourceExclusiveLite(&sf->fcb->nonpaged->dir_children_lock, true);
1585
1586 if (dc->fileref) {
1587 duff_fr = sf2;
1588 sf2 = dc->fileref;
1590 } else {
1591 sf2->fcb = fcb;
1592 sf2->parent = (struct _file_ref*)sf;
1593 sf2->dc = dc;
1594 dc->fileref = sf2;
1596 InsertTailList(&sf->children, &sf2->list_entry);
1597 }
1598
1599 ExReleaseResourceLite(&sf->fcb->nonpaged->dir_children_lock);
1600
1601 if (duff_fr)
1602 ExFreeToPagedLookasideList(&Vcb->fileref_lookaside, duff_fr);
1603 } else {
1604 root* subvol;
1606 dir_child* dc;
1607
1608 Status = find_file_in_dir(name, sf->fcb, &subvol, &inode, &dc, case_sensitive);
1610 TRACE("could not find %.*S\n", (int)(name->Length / sizeof(WCHAR)), name->Buffer);
1611
1613 } else if (Status == STATUS_OBJECT_NAME_INVALID) {
1614 TRACE("invalid filename: %.*S\n", (int)(name->Length / sizeof(WCHAR)), name->Buffer);
1615 return Status;
1616 } else if (!NT_SUCCESS(Status)) {
1617 ERR("find_file_in_dir returned %08lx\n", Status);
1618 return Status;
1619 } else {
1620 fcb* fcb;
1621 file_ref* duff_fr = NULL;
1622
1623 if (dc->fileref) {
1624 if (!lastpart && dc->type != BTRFS_TYPE_DIRECTORY) {
1625 TRACE("passed path including file as subdirectory\n");
1627 }
1628
1629 InterlockedIncrement(&dc->fileref->refcount);
1630 *psf2 = dc->fileref;
1631 return STATUS_SUCCESS;
1632 }
1633
1634 if (!subvol || (subvol != Vcb->root_fileref->fcb->subvol && inode == SUBVOL_ROOT_INODE && subvol->parent != sf->fcb->subvol->id && !dc->root_dir)) {
1635 fcb = Vcb->dummy_fcb;
1637 } else {
1638 Status = open_fcb(Vcb, subvol, inode, dc->type, &dc->utf8, false, sf->fcb, &fcb, pooltype, Irp);
1639
1640 if (!NT_SUCCESS(Status)) {
1641 ERR("open_fcb returned %08lx\n", Status);
1642 return Status;
1643 }
1644 }
1645
1646 if (dc->type != BTRFS_TYPE_DIRECTORY && !lastpart && !(fcb->atts & FILE_ATTRIBUTE_REPARSE_POINT)) {
1647 TRACE("passed path including file as subdirectory\n");
1648 free_fcb(fcb);
1650 }
1651
1652 sf2 = create_fileref(Vcb);
1653 if (!sf2) {
1654 ERR("out of memory\n");
1655 free_fcb(fcb);
1657 }
1658
1659 sf2->fcb = fcb;
1660
1661 ExAcquireResourceExclusiveLite(&sf->fcb->nonpaged->dir_children_lock, true);
1662
1663 if (!dc->fileref) {
1664 sf2->parent = (struct _file_ref*)sf;
1665 sf2->dc = dc;
1666 dc->fileref = sf2;
1667 InsertTailList(&sf->children, &sf2->list_entry);
1669
1670 if (dc->type == BTRFS_TYPE_DIRECTORY)
1671 fcb->fileref = sf2;
1672 } else {
1673 duff_fr = sf2;
1674 sf2 = dc->fileref;
1676 }
1677
1678 ExReleaseResourceLite(&sf->fcb->nonpaged->dir_children_lock);
1679
1680 if (duff_fr)
1681 reap_fileref(Vcb, duff_fr);
1682 }
1683 }
1684
1685 *psf2 = sf2;
1686
1687 return STATUS_SUCCESS;
1688}
static NTSTATUS open_fcb_stream(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, dir_child *dc, fcb *parent, fcb **pfcb, PIRP Irp)
Definition: create.c:1366
NTSTATUS find_file_in_dir(PUNICODE_STRING filename, fcb *fcb, root **subvol, uint64_t *inode, dir_child **pdc, bool case_sensitive)
Definition: create.c:182
uint64_t parent
Definition: btrfs_drv.h:459

Referenced by add_children_to_move_list(), open_file3(), open_fileref(), open_fileref_by_inode(), rename_file_to_stream(), and rename_stream().

◆ oplock_complete()

static void __stdcall oplock_complete ( PVOID  Context,
PIRP  Irp 
)
static

Definition at line 3863 of file create.c.

3863 {
3866 bool skip_lock;
3868 device_extension* Vcb = ctx->Vcb;
3869
3870 TRACE("(%p, %p)\n", Context, Irp);
3871
3873
3874 skip_lock = ExIsResourceAcquiredExclusiveLite(&Vcb->tree_lock);
3875
3876 if (!skip_lock)
3877 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
3878
3879 ExAcquireResourceSharedLite(&Vcb->fileref_lock, true);
3880
3881 // FIXME - trans
3882 Status = open_file3(Vcb, Irp, ctx->granted_access, ctx->fileref, &rollback);
3883
3884 if (!NT_SUCCESS(Status)) {
3885 free_fileref(ctx->fileref);
3886 do_rollback(ctx->Vcb, &rollback);
3887 } else
3889
3890 ExReleaseResourceLite(&Vcb->fileref_lock);
3891
3892 if (Status == STATUS_SUCCESS) {
3893 fcb* fcb2;
3896 bool skip_fcb_lock;
3897
3898 IrpSp->Parameters.Create.SecurityContext->AccessState->PreviouslyGrantedAccess |= ctx->granted_access;
3899 IrpSp->Parameters.Create.SecurityContext->AccessState->RemainingDesiredAccess &= ~(ctx->granted_access | MAXIMUM_ALLOWED);
3900
3901 if (!FileObject->Vpb)
3902 FileObject->Vpb = Vcb->devobj->Vpb;
3903
3904 fcb2 = FileObject->FsContext;
3905
3906 if (fcb2->ads) {
3907 struct _ccb* ccb2 = FileObject->FsContext2;
3908
3909 fcb2 = ccb2->fileref->parent->fcb;
3910 }
3911
3912 skip_fcb_lock = ExIsResourceAcquiredExclusiveLite(fcb2->Header.Resource);
3913
3914 if (!skip_fcb_lock)
3915 ExAcquireResourceExclusiveLite(fcb2->Header.Resource, true);
3916
3917 fcb_load_csums(Vcb, fcb2, Irp);
3918
3919 if (!skip_fcb_lock)
3920 ExReleaseResourceLite(fcb2->Header.Resource);
3921 }
3922
3923 if (!skip_lock)
3924 ExReleaseResourceLite(&Vcb->tree_lock);
3925
3926 // FIXME - call free_trans if failed and within transaction
3927
3928 Irp->IoStatus.Status = Status;
3930
3931 ctx->Status = Status;
3932
3933 KeSetEvent(&ctx->event, 0, false);
3934}
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476

Referenced by open_file2().

◆ split_path()

static NTSTATUS split_path ( device_extension Vcb,
PUNICODE_STRING  path,
LIST_ENTRY parts,
bool stream 
)
static

Definition at line 321 of file create.c.

321 {
322 ULONG len, i;
323 bool has_stream;
324 WCHAR* buf;
325 name_bit* nb;
327
328 len = path->Length / sizeof(WCHAR);
329 if (len > 0 && (path->Buffer[len - 1] == '/' || path->Buffer[len - 1] == '\\'))
330 len--;
331
332 if (len == 0 || (path->Buffer[len - 1] == '/' || path->Buffer[len - 1] == '\\')) {
333 WARN("zero-length filename part\n");
335 }
336
337 has_stream = false;
338 for (i = 0; i < len; i++) {
339 if (path->Buffer[i] == '/' || path->Buffer[i] == '\\') {
340 has_stream = false;
341 } else if (path->Buffer[i] == ':') {
342 has_stream = true;
343 }
344 }
345
346 buf = path->Buffer;
347
348 for (i = 0; i < len; i++) {
349 if (path->Buffer[i] == '/' || path->Buffer[i] == '\\') {
350 if (buf[0] == '/' || buf[0] == '\\') {
351 WARN("zero-length filename part\n");
353 goto cleanup;
354 }
355
356 nb = ExAllocateFromPagedLookasideList(&Vcb->name_bit_lookaside);
357 if (!nb) {
358 ERR("out of memory\n");
360 goto cleanup;
361 }
362
363 nb->us.Buffer = buf;
364 nb->us.Length = nb->us.MaximumLength = (USHORT)(&path->Buffer[i] - buf) * sizeof(WCHAR);
366
367 buf = &path->Buffer[i+1];
368 }
369 }
370
371 nb = ExAllocateFromPagedLookasideList(&Vcb->name_bit_lookaside);
372 if (!nb) {
373 ERR("out of memory\n");
375 goto cleanup;
376 }
377
378 nb->us.Buffer = buf;
379 nb->us.Length = nb->us.MaximumLength = (USHORT)(&path->Buffer[i] - buf) * sizeof(WCHAR);
381
382 if (has_stream) {
383 static const WCHAR datasuf[] = {':','$','D','A','T','A',0};
384 UNICODE_STRING dsus;
385
386 dsus.Buffer = (WCHAR*)datasuf;
387 dsus.Length = dsus.MaximumLength = sizeof(datasuf) - sizeof(WCHAR);
388
389 for (i = 0; i < nb->us.Length / sizeof(WCHAR); i++) {
390 if (nb->us.Buffer[i] == ':') {
391 name_bit* nb2;
392
393 if (i + 1 == nb->us.Length / sizeof(WCHAR)) {
394 WARN("zero-length stream name\n");
396 goto cleanup;
397 }
398
399 nb2 = ExAllocateFromPagedLookasideList(&Vcb->name_bit_lookaside);
400 if (!nb2) {
401 ERR("out of memory\n");
403 goto cleanup;
404 }
405
406 nb2->us.Buffer = &nb->us.Buffer[i+1];
407 nb2->us.Length = nb2->us.MaximumLength = (uint16_t)(nb->us.Length - (i * sizeof(WCHAR)) - sizeof(WCHAR));
409
410 nb->us.Length = (uint16_t)i * sizeof(WCHAR);
411 nb->us.MaximumLength = nb->us.Length;
412
413 nb = nb2;
414
415 break;
416 }
417 }
418
419 // FIXME - should comparison be case-insensitive?
420 // remove :$DATA suffix
421 if (nb->us.Length >= dsus.Length && RtlCompareMemory(&nb->us.Buffer[(nb->us.Length - dsus.Length)/sizeof(WCHAR)], dsus.Buffer, dsus.Length) == dsus.Length)
422 nb->us.Length -= dsus.Length;
423
424 if (nb->us.Length == 0) {
426 ExFreeToPagedLookasideList(&Vcb->name_bit_lookaside, nb);
427
428 has_stream = false;
429 }
430 }
431
432 // if path is just stream name, remove first empty item
433 if (has_stream && path->Length >= sizeof(WCHAR) && path->Buffer[0] == ':') {
435
436 ExFreeToPagedLookasideList(&Vcb->name_bit_lookaside, nb1);
437 }
438
439 *stream = has_stream;
440
441 return STATUS_SUCCESS;
442
443cleanup:
444 while (!IsListEmpty(parts)) {
446
447 ExFreeToPagedLookasideList(&Vcb->name_bit_lookaside, nb);
448 }
449
450 return Status;
451}
static void cleanup(void)
Definition: main.c:1335
LIST_ENTRY list_entry
Definition: btrfs_drv.h:956

Referenced by open_fileref().

◆ verify_vcb()

static NTSTATUS verify_vcb ( device_extension Vcb,
PIRP  Irp 
)
static

Definition at line 4753 of file create.c.

4753 {
4755 LIST_ENTRY* le;
4756 bool need_verify = false;
4757
4758 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
4759
4760 le = Vcb->devices.Flink;
4761 while (le != &Vcb->devices) {
4763
4764 if (dev->devobj && dev->removable) {
4765 ULONG cc;
4767
4768 Status = dev_ioctl(dev->devobj, IOCTL_STORAGE_CHECK_VERIFY, NULL, 0, &cc, sizeof(ULONG), true, &iosb);
4769
4771 ERR("IOCTL_STORAGE_CHECK_VERIFY returned %08lx (user-induced)\n", Status);
4772 need_verify = true;
4773 } else if (!NT_SUCCESS(Status)) {
4774 ERR("IOCTL_STORAGE_CHECK_VERIFY returned %08lx\n", Status);
4775 goto end;
4776 } else if (iosb.Information < sizeof(ULONG)) {
4777 ERR("iosb.Information was too short\n");
4779 } else if (cc != dev->change_count) {
4780 dev->devobj->Flags |= DO_VERIFY_VOLUME;
4781 need_verify = true;
4782 }
4783 }
4784
4785 le = le->Flink;
4786 }
4787
4789
4790end:
4791 ExReleaseResourceLite(&Vcb->tree_lock);
4792
4793 if (need_verify) {
4794 PDEVICE_OBJECT devobj;
4795
4796 devobj = IoGetDeviceToVerify(Irp->Tail.Overlay.Thread);
4797 IoSetDeviceToVerify(Irp->Tail.Overlay.Thread, NULL);
4798
4799 if (!devobj) {
4802 }
4803
4804 devobj = Vcb->Vpb ? Vcb->Vpb->RealDevice : NULL;
4805
4806 if (devobj)
4807 Status = IoVerifyVolume(devobj, false);
4808 else
4810 }
4811
4812 return Status;
4813}
NTSTATUS dev_ioctl(_In_ PDEVICE_OBJECT DeviceObject, _In_ ULONG ControlCode, _In_reads_bytes_opt_(InputBufferSize) PVOID InputBuffer, _In_ ULONG InputBufferSize, _Out_writes_bytes_opt_(OutputBufferSize) PVOID OutputBuffer, _In_ ULONG OutputBufferSize, _In_ bool Override, _Out_opt_ IO_STATUS_BLOCK *iosb)
Definition: btrfs.c:2954
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
uint32_t cc
Definition: isohybrid.c:75
static PIO_STATUS_BLOCK iosb
Definition: file.c:98
#define IOCTL_STORAGE_CHECK_VERIFY
Definition: ntddstor.h:98
VOID NTAPI IoSetDeviceToVerify(IN PETHREAD Thread, IN PDEVICE_OBJECT DeviceObject)
Definition: util.c:304
PDEVICE_OBJECT NTAPI IoGetDeviceToVerify(IN PETHREAD Thread)
Definition: util.c:336
NTSTATUS NTAPI IoVerifyVolume(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN AllowRawMount)
Definition: volume.c:877
Definition: devices.h:37
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2817

Referenced by _Dispatch_type_().

Variable Documentation

◆ datastring

const WCHAR datastring[] = L"::$DATA"
static

Definition at line 30 of file create.c.

Referenced by open_fileref().

◆ fFsRtlGetEcpListFromIrp

tFsRtlGetEcpListFromIrp fFsRtlGetEcpListFromIrp
extern

Definition at line 96 of file btrfs.c.

Referenced by _Function_class_(), and file_create().

◆ fFsRtlGetNextExtraCreateParameter

tFsRtlGetNextExtraCreateParameter fFsRtlGetNextExtraCreateParameter
extern

Definition at line 97 of file btrfs.c.

Referenced by _Function_class_(), and file_create().

◆ fFsRtlValidateReparsePointBuffer

tFsRtlValidateReparsePointBuffer fFsRtlValidateReparsePointBuffer
extern

Definition at line 98 of file btrfs.c.

Referenced by get_reparse_block().

◆ GUID_ECP_ATOMIC_CREATE

const GUID GUID_ECP_ATOMIC_CREATE = { 0x4720bd83, 0x52ac, 0x4104, { 0xa1, 0x30, 0xd1, 0xec, 0x6a, 0x8c, 0xc8, 0xe5 } }
static

Definition at line 79 of file create.c.

Referenced by file_create().

◆ GUID_ECP_CREATE_REDIRECTION

const GUID GUID_ECP_CREATE_REDIRECTION = { 0x188d6bd6, 0xa126, 0x4fa8, { 0xbd, 0xf2, 0x1c, 0xcd, 0xf8, 0x96, 0xf3, 0xe0 } }
static

Definition at line 81 of file create.c.

Referenced by file_create().

◆ GUID_ECP_QUERY_ON_CREATE

const GUID GUID_ECP_QUERY_ON_CREATE = { 0x1aca62e9, 0xabb4, 0x4ff2, { 0xbb, 0x5c, 0x1c, 0x79, 0x02, 0x5e, 0x41, 0x7f } }
static

Definition at line 80 of file create.c.

Referenced by file_create().

◆ master_devobj

PDEVICE_OBJECT master_devobj
extern

Definition at line 66 of file btrfs.c.

Referenced by _Dispatch_type_().

◆ root_dir

const char root_dir[] = "$Root"
static

Definition at line 32 of file create.c.

Referenced by fnt_face_get_dll_font(), and load_dir_children().

◆ root_dir_utf16

const WCHAR root_dir_utf16[] = L"$Root"
static

Definition at line 33 of file create.c.

Referenced by load_dir_children(), and open_fileref_by_inode().