ReactOS 0.4.15-dev-8100-g1887773
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:115
#define ERR(fmt,...)
Definition: debug.h:113
#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::@1567 Parameters
struct _IO_STACK_LOCATION::@3982::@3983 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
USHORT ReparseDataLength
Definition: shellext.h:166
struct _REPARSE_DATA_BUFFER::@320::@322 SymbolicLinkReparseBuffer
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
1037 fcb->atts |=