mirror of
https://github.com/reactos/reactos.git
synced 2024-06-29 09:21:31 +00:00
[BTRFS] Upgrade to 1.3
CORE-16111
This commit is contained in:
parent
90aa2c26f8
commit
f381137c89
|
@ -25,18 +25,18 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
|||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
|
@ -51,8 +51,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,1,0,0
|
||||
PRODUCTVERSION 1,1,0,0
|
||||
FILEVERSION 1,3,0,0
|
||||
PRODUCTVERSION 1,3,0,0
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -60,20 +60,20 @@ VS_VERSION_INFO VERSIONINFO
|
|||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x0L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "080904b0"
|
||||
BEGIN
|
||||
VALUE "FileDescription", "Btrfs formatting utility"
|
||||
VALUE "FileVersion", "1.1"
|
||||
VALUE "InternalName", "mkbtrfs"
|
||||
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-18"
|
||||
VALUE "OriginalFilename", "mkbtrfs.exe"
|
||||
VALUE "FileDescription", "Btrfs utility DLL"
|
||||
VALUE "FileVersion", "1.3"
|
||||
VALUE "InternalName", "ubtrfs"
|
||||
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-19"
|
||||
VALUE "OriginalFilename", "ubtrfs.dll"
|
||||
VALUE "ProductName", "WinBtrfs"
|
||||
VALUE "ProductVersion", "1.1"
|
||||
VALUE "ProductVersion", "1.3"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -795,7 +795,8 @@ static NTSTATUS drv_query_volume_information(_In_ PDEVICE_OBJECT DeviceObject, _
|
|||
data->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES | FILE_CASE_SENSITIVE_SEARCH |
|
||||
FILE_UNICODE_ON_DISK | FILE_NAMED_STREAMS | FILE_SUPPORTS_HARD_LINKS | FILE_PERSISTENT_ACLS |
|
||||
FILE_SUPPORTS_REPARSE_POINTS | FILE_SUPPORTS_SPARSE_FILES | FILE_SUPPORTS_OBJECT_IDS |
|
||||
FILE_SUPPORTS_OPEN_BY_FILE_ID | FILE_SUPPORTS_EXTENDED_ATTRIBUTES | FILE_SUPPORTS_BLOCK_REFCOUNTING;
|
||||
FILE_SUPPORTS_OPEN_BY_FILE_ID | FILE_SUPPORTS_EXTENDED_ATTRIBUTES | FILE_SUPPORTS_BLOCK_REFCOUNTING |
|
||||
FILE_SUPPORTS_POSIX_UNLINK_RENAME;
|
||||
if (Vcb->readonly)
|
||||
data->FileSystemAttributes |= FILE_READ_ONLY_VOLUME;
|
||||
|
||||
|
@ -1068,6 +1069,7 @@ NTSTATUS create_root(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) devi
|
|||
RtlZeroMemory(&r->root_item, sizeof(ROOT_ITEM));
|
||||
r->root_item.num_references = 1;
|
||||
r->fcbs_version = 0;
|
||||
r->checked_for_orphans = TRUE;
|
||||
InitializeListHead(&r->fcbs);
|
||||
RtlZeroMemory(r->fcbs_ptrs, sizeof(LIST_ENTRY*) * 256);
|
||||
|
||||
|
@ -1966,7 +1968,63 @@ void uninit(_In_ device_extension* Vcb) {
|
|||
ZwClose(Vcb->flush_thread_handle);
|
||||
}
|
||||
|
||||
NTSTATUS delete_fileref(_In_ file_ref* fileref, _In_opt_ PFILE_OBJECT FileObject, _In_opt_ PIRP Irp, _In_ LIST_ENTRY* rollback) {
|
||||
static NTSTATUS delete_fileref_fcb(_In_ file_ref* fileref, _In_opt_ PFILE_OBJECT FileObject, _In_opt_ PIRP Irp, _In_ LIST_ENTRY* rollback) {
|
||||
NTSTATUS Status;
|
||||
LIST_ENTRY* le;
|
||||
|
||||
// excise extents
|
||||
|
||||
if (fileref->fcb->type != BTRFS_TYPE_DIRECTORY && fileref->fcb->inode_item.st_size > 0) {
|
||||
Status = excise_extents(fileref->fcb->Vcb, fileref->fcb, 0, sector_align(fileref->fcb->inode_item.st_size, fileref->fcb->Vcb->superblock.sector_size), Irp, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("excise_extents returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
fileref->fcb->Header.AllocationSize.QuadPart = 0;
|
||||
fileref->fcb->Header.FileSize.QuadPart = 0;
|
||||
fileref->fcb->Header.ValidDataLength.QuadPart = 0;
|
||||
|
||||
if (FileObject) {
|
||||
CC_FILE_SIZES ccfs;
|
||||
|
||||
ccfs.AllocationSize = fileref->fcb->Header.AllocationSize;
|
||||
ccfs.FileSize = fileref->fcb->Header.FileSize;
|
||||
ccfs.ValidDataLength = fileref->fcb->Header.ValidDataLength;
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
_SEH2_TRY {
|
||||
CcSetFileSizes(FileObject, &ccfs);
|
||||
} _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
} _SEH2_END;
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("CcSetFileSizes threw exception %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
fileref->fcb->deleted = TRUE;
|
||||
|
||||
le = fileref->children.Flink;
|
||||
while (le != &fileref->children) {
|
||||
file_ref* fr2 = CONTAINING_RECORD(le, file_ref, list_entry);
|
||||
|
||||
if (fr2->fcb->ads) {
|
||||
fr2->fcb->deleted = TRUE;
|
||||
mark_fcb_dirty(fr2->fcb);
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS delete_fileref(_In_ file_ref* fileref, _In_opt_ PFILE_OBJECT FileObject, _In_ BOOL make_orphan, _In_opt_ PIRP Irp, _In_ LIST_ENTRY* rollback) {
|
||||
LARGE_INTEGER newlength, time;
|
||||
BTRFS_TIME now;
|
||||
NTSTATUS Status;
|
||||
|
@ -2002,61 +2060,17 @@ NTSTATUS delete_fileref(_In_ file_ref* fileref, _In_opt_ PFILE_OBJECT FileObject
|
|||
|
||||
fileref->fcb->inode_item_changed = TRUE;
|
||||
|
||||
if (fileref->fcb->inode_item.st_nlink > 1) {
|
||||
if (fileref->fcb->inode_item.st_nlink > 1 || make_orphan) {
|
||||
fileref->fcb->inode_item.st_nlink--;
|
||||
fileref->fcb->inode_item.transid = fileref->fcb->Vcb->superblock.generation;
|
||||
fileref->fcb->inode_item.sequence++;
|
||||
fileref->fcb->inode_item.st_ctime = now;
|
||||
} else {
|
||||
// excise extents
|
||||
|
||||
if (fileref->fcb->type != BTRFS_TYPE_DIRECTORY && fileref->fcb->inode_item.st_size > 0) {
|
||||
Status = excise_extents(fileref->fcb->Vcb, fileref->fcb, 0, sector_align(fileref->fcb->inode_item.st_size, fileref->fcb->Vcb->superblock.sector_size), Irp, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("excise_extents returned %08x\n", Status);
|
||||
ExReleaseResourceLite(fileref->fcb->Header.Resource);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
fileref->fcb->Header.AllocationSize.QuadPart = 0;
|
||||
fileref->fcb->Header.FileSize.QuadPart = 0;
|
||||
fileref->fcb->Header.ValidDataLength.QuadPart = 0;
|
||||
|
||||
if (FileObject) {
|
||||
CC_FILE_SIZES ccfs;
|
||||
|
||||
ccfs.AllocationSize = fileref->fcb->Header.AllocationSize;
|
||||
ccfs.FileSize = fileref->fcb->Header.FileSize;
|
||||
ccfs.ValidDataLength = fileref->fcb->Header.ValidDataLength;
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
_SEH2_TRY {
|
||||
CcSetFileSizes(FileObject, &ccfs);
|
||||
} _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
} _SEH2_END;
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("CcSetFileSizes threw exception %08x\n", Status);
|
||||
ExReleaseResourceLite(fileref->fcb->Header.Resource);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
fileref->fcb->deleted = TRUE;
|
||||
|
||||
le = fileref->children.Flink;
|
||||
while (le != &fileref->children) {
|
||||
file_ref* fr2 = CONTAINING_RECORD(le, file_ref, list_entry);
|
||||
|
||||
if (fr2->fcb->ads) {
|
||||
fr2->fcb->deleted = TRUE;
|
||||
mark_fcb_dirty(fr2->fcb);
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
Status = delete_fileref_fcb(fileref, FileObject, Irp, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("delete_fileref_fcb returned %08x\n", Status);
|
||||
ExReleaseResourceLite(fileref->fcb->Header.Resource);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2271,9 +2285,26 @@ static NTSTATUS drv_cleanup(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
|
|||
// FIXME - flush all of subvol's fcbs
|
||||
}
|
||||
|
||||
if (fileref && oc == 0) {
|
||||
if (fileref && (oc == 0 || (fileref->delete_on_close && fileref->posix_delete))) {
|
||||
if (!fcb->Vcb->removing) {
|
||||
if (fileref && fileref->delete_on_close && fileref != fcb->Vcb->root_fileref && fcb != fcb->Vcb->volume_fcb) {
|
||||
if (oc == 0 && fileref->fcb->inode_item.st_nlink == 0 && fileref != fcb->Vcb->root_fileref && fcb != fcb->Vcb->volume_fcb) { // last handle closed on POSIX-deleted file
|
||||
LIST_ENTRY rollback;
|
||||
|
||||
InitializeListHead(&rollback);
|
||||
|
||||
Status = delete_fileref_fcb(fileref, FileObject, Irp, &rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("delete_fileref_fcb returned %08x\n", Status);
|
||||
do_rollback(fcb->Vcb, &rollback);
|
||||
ExReleaseResourceLite(fileref->fcb->Header.Resource);
|
||||
ExReleaseResourceLite(&fcb->Vcb->tree_lock);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
clear_rollback(&rollback);
|
||||
|
||||
mark_fcb_dirty(fileref->fcb);
|
||||
} else if (fileref->delete_on_close && fileref != fcb->Vcb->root_fileref && fcb != fcb->Vcb->volume_fcb) {
|
||||
LIST_ENTRY rollback;
|
||||
|
||||
InitializeListHead(&rollback);
|
||||
|
@ -2292,7 +2323,7 @@ static NTSTATUS drv_cleanup(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
|
|||
// fileref_lock needs to be acquired before fcb->Header.Resource
|
||||
ExAcquireResourceExclusiveLite(&fcb->Vcb->fileref_lock, TRUE);
|
||||
|
||||
Status = delete_fileref(fileref, FileObject, Irp, &rollback);
|
||||
Status = delete_fileref(fileref, FileObject, oc > 0 && fileref->posix_delete, Irp, &rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("delete_fileref returned %08x\n", Status);
|
||||
do_rollback(fcb->Vcb, &rollback);
|
||||
|
@ -2677,6 +2708,7 @@ static NTSTATUS add_root(_Inout_ device_extension* Vcb, _In_ UINT64 id, _In_ UIN
|
|||
r->parent = 0;
|
||||
r->send_ops = 0;
|
||||
r->fcbs_version = 0;
|
||||
r->checked_for_orphans = FALSE;
|
||||
InitializeListHead(&r->fcbs);
|
||||
RtlZeroMemory(r->fcbs_ptrs, sizeof(LIST_ENTRY*) * 256);
|
||||
|
||||
|
@ -3530,6 +3562,26 @@ void protect_superblocks(_Inout_ chunk* c) {
|
|||
}
|
||||
}
|
||||
|
||||
UINT64 chunk_estimate_phys_size(device_extension* Vcb, chunk* c, UINT64 u) {
|
||||
UINT64 nfactor, dfactor;
|
||||
|
||||
if (c->chunk_item->type & BLOCK_FLAG_DUPLICATE || c->chunk_item->type & BLOCK_FLAG_RAID1 || c->chunk_item->type & BLOCK_FLAG_RAID10) {
|
||||
nfactor = 1;
|
||||
dfactor = 2;
|
||||
} else if (c->chunk_item->type & BLOCK_FLAG_RAID5) {
|
||||
nfactor = Vcb->superblock.num_devices - 1;
|
||||
dfactor = Vcb->superblock.num_devices;
|
||||
} else if (c->chunk_item->type & BLOCK_FLAG_RAID6) {
|
||||
nfactor = Vcb->superblock.num_devices - 2;
|
||||
dfactor = Vcb->superblock.num_devices;
|
||||
} else {
|
||||
nfactor = 1;
|
||||
dfactor = 1;
|
||||
}
|
||||
|
||||
return u * dfactor / nfactor;
|
||||
}
|
||||
|
||||
NTSTATUS find_chunk_usage(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _In_opt_ PIRP Irp) {
|
||||
LIST_ENTRY* le = Vcb->chunks.Flink;
|
||||
chunk* c;
|
||||
|
@ -3540,6 +3592,8 @@ NTSTATUS find_chunk_usage(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_ex
|
|||
|
||||
searchkey.obj_type = TYPE_BLOCK_GROUP_ITEM;
|
||||
|
||||
Vcb->superblock.bytes_used = 0;
|
||||
|
||||
while (le != &Vcb->chunks) {
|
||||
c = CONTAINING_RECORD(le, chunk, list_entry);
|
||||
|
||||
|
@ -3559,6 +3613,8 @@ NTSTATUS find_chunk_usage(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_ex
|
|||
c->used = c->oldused = bgi->used;
|
||||
|
||||
TRACE("chunk %llx has %llx bytes used\n", c->offset, c->used);
|
||||
|
||||
Vcb->superblock.bytes_used += chunk_estimate_phys_size(Vcb, c, bgi->used);
|
||||
} else {
|
||||
ERR("(%llx;%llx,%x,%llx) is %u bytes, expected %u\n",
|
||||
Vcb->extent_root->id, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(BLOCK_GROUP_ITEM));
|
||||
|
|
|
@ -19,6 +19,7 @@ static const UINT64 superblock_addrs[] = { 0x10000, 0x4000000, 0x4000000000, 0x4
|
|||
#define TYPE_INODE_REF 0x0C
|
||||
#define TYPE_INODE_EXTREF 0x0D
|
||||
#define TYPE_XATTR_ITEM 0x18
|
||||
#define TYPE_ORPHAN_INODE 0x30
|
||||
#define TYPE_DIR_ITEM 0x54
|
||||
#define TYPE_DIR_INDEX 0x60
|
||||
#define TYPE_EXTENT_DATA 0x6C
|
||||
|
@ -113,6 +114,8 @@ static const UINT64 superblock_addrs[] = { 0x10000, 0x4000000, 0x4000000000, 0x4
|
|||
|
||||
#define BTRFS_SUPERBLOCK_FLAGS_SEEDING 0x100000000
|
||||
|
||||
#define BTRFS_ORPHAN_INODE_OBJID 0xFFFFFFFFFFFFFFFB
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -51,8 +51,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,2,1,0
|
||||
PRODUCTVERSION 1,2,1,0
|
||||
FILEVERSION 1,3,0,0
|
||||
PRODUCTVERSION 1,3,0,0
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -68,12 +68,12 @@ BEGIN
|
|||
BLOCK "080904b0"
|
||||
BEGIN
|
||||
VALUE "FileDescription", "WinBtrfs"
|
||||
VALUE "FileVersion", "1.2.1"
|
||||
VALUE "FileVersion", "1.3"
|
||||
VALUE "InternalName", "btrfs"
|
||||
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-19"
|
||||
VALUE "OriginalFilename", "btrfs.sys"
|
||||
VALUE "ProductName", "WinBtrfs"
|
||||
VALUE "ProductVersion", "1.2.1"
|
||||
VALUE "ProductVersion", "1.3"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -101,6 +101,9 @@
|
|||
#define EA_EA "user.EA"
|
||||
#define EA_EA_HASH 0x8270dd43
|
||||
|
||||
#define EA_CASE_SENSITIVE "user.casesensitive"
|
||||
#define EA_CASE_SENSITIVE_HASH 0x1a9d97d4
|
||||
|
||||
#define EA_PROP_COMPRESSION "btrfs.compression"
|
||||
#define EA_PROP_COMPRESSION_HASH 0x20ccdf69
|
||||
|
||||
|
@ -132,10 +135,20 @@
|
|||
#define FILE_SUPPORTS_BLOCK_REFCOUNTING 0x08000000
|
||||
#endif
|
||||
|
||||
#ifndef FILE_SUPPORTS_POSIX_UNLINK_RENAME
|
||||
#define FILE_SUPPORTS_POSIX_UNLINK_RENAME 0x00000400
|
||||
#endif
|
||||
|
||||
#ifndef FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL
|
||||
#define FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL 0x00020000
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
typedef struct _FILE_ID_128 {
|
||||
UCHAR Identifier[16];
|
||||
} FILE_ID_128, *PFILE_ID_128;
|
||||
#endif
|
||||
|
||||
typedef struct _DUPLICATE_EXTENTS_DATA {
|
||||
HANDLE FileHandle;
|
||||
LARGE_INTEGER SourceFileOffset;
|
||||
|
@ -280,6 +293,9 @@ typedef struct _fcb {
|
|||
BOOL inode_item_changed;
|
||||
enum prop_compression_type prop_compression;
|
||||
LIST_ENTRY xattrs;
|
||||
BOOL marked_as_orphan;
|
||||
BOOL case_sensitive;
|
||||
BOOL case_sensitive_set;
|
||||
|
||||
LIST_ENTRY dir_children_index;
|
||||
LIST_ENTRY dir_children_hash;
|
||||
|
@ -317,6 +333,7 @@ typedef struct _file_ref {
|
|||
ANSI_STRING oldutf8;
|
||||
UINT64 oldindex;
|
||||
BOOL delete_on_close;
|
||||
BOOL posix_delete;
|
||||
BOOL deleted;
|
||||
BOOL created;
|
||||
file_ref_nonpaged* nonpaged;
|
||||
|
@ -434,6 +451,7 @@ typedef struct _root {
|
|||
UINT64 parent;
|
||||
LONG send_ops;
|
||||
UINT64 fcbs_version;
|
||||
BOOL checked_for_orphans;
|
||||
LIST_ENTRY fcbs;
|
||||
LIST_ENTRY* fcbs_ptrs[256];
|
||||
LIST_ENTRY list_entry;
|
||||
|
@ -1123,7 +1141,7 @@ WCHAR* file_desc(_In_ PFILE_OBJECT FileObject);
|
|||
WCHAR* file_desc_fileref(_In_ file_ref* fileref);
|
||||
void mark_fcb_dirty(_In_ fcb* fcb);
|
||||
void mark_fileref_dirty(_In_ file_ref* fileref);
|
||||
NTSTATUS delete_fileref(_In_ file_ref* fileref, _In_opt_ PFILE_OBJECT FileObject, _In_opt_ PIRP Irp, _In_ LIST_ENTRY* rollback);
|
||||
NTSTATUS delete_fileref(_In_ file_ref* fileref, _In_opt_ PFILE_OBJECT FileObject, _In_ BOOL make_orphan, _In_opt_ PIRP Irp, _In_ LIST_ENTRY* rollback);
|
||||
void chunk_lock_range(_In_ device_extension* Vcb, _In_ chunk* c, _In_ UINT64 start, _In_ UINT64 length);
|
||||
void chunk_unlock_range(_In_ device_extension* Vcb, _In_ chunk* c, _In_ UINT64 start, _In_ UINT64 length);
|
||||
void init_device(_In_ device_extension* Vcb, _Inout_ device* dev, _In_ BOOL get_nums);
|
||||
|
@ -1142,6 +1160,7 @@ void reap_fcb(fcb* fcb);
|
|||
void reap_fcbs(device_extension* Vcb);
|
||||
void reap_fileref(device_extension* Vcb, file_ref* fr);
|
||||
void reap_filerefs(device_extension* Vcb, file_ref* fr);
|
||||
UINT64 chunk_estimate_phys_size(device_extension* Vcb, chunk* c, UINT64 u);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define funcname __FUNCTION__
|
||||
|
@ -1412,7 +1431,7 @@ NTSTATUS open_fileref(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusiv
|
|||
_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 open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension* Vcb,
|
||||
root* subvol, UINT64 inode, UINT8 type, PANSI_STRING utf8, fcb* parent, fcb** pfcb, POOL_TYPE pooltype, PIRP Irp);
|
||||
root* subvol, UINT64 inode, UINT8 type, PANSI_STRING utf8, BOOL always_add_hl, fcb* parent, fcb** pfcb, POOL_TYPE pooltype, PIRP Irp);
|
||||
NTSTATUS load_csum(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, UINT32* csum, UINT64 start, UINT64 length, PIRP Irp);
|
||||
NTSTATUS load_dir_children(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, fcb* fcb, BOOL ignore_size, PIRP Irp);
|
||||
NTSTATUS add_dir_child(fcb* fcb, UINT64 inode, BOOL subvol, PANSI_STRING utf8, PUNICODE_STRING name, UINT8 type, dir_child** pdc);
|
||||
|
|
|
@ -593,7 +593,7 @@ cont:
|
|||
}
|
||||
|
||||
NTSTATUS open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension* Vcb,
|
||||
root* subvol, UINT64 inode, UINT8 type, PANSI_STRING utf8, fcb* parent, fcb** pfcb, POOL_TYPE pooltype, PIRP Irp) {
|
||||
root* subvol, UINT64 inode, UINT8 type, PANSI_STRING utf8, BOOL always_add_hl, fcb* parent, fcb** pfcb, POOL_TYPE pooltype, PIRP Irp) {
|
||||
KEY searchkey;
|
||||
traverse_ptr tp, next_tp;
|
||||
NTSTATUS Status;
|
||||
|
@ -719,7 +719,7 @@ NTSTATUS open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lo
|
|||
if ((no_data && tp.item->key.obj_type > TYPE_XATTR_ITEM) || tp.item->key.obj_type > TYPE_EXTENT_DATA)
|
||||
break;
|
||||
|
||||
if (fcb->inode_item.st_nlink > 1 && tp.item->key.obj_type == TYPE_INODE_REF) {
|
||||
if ((always_add_hl || fcb->inode_item.st_nlink > 1) && tp.item->key.obj_type == TYPE_INODE_REF) {
|
||||
ULONG len;
|
||||
INODE_REF* ir;
|
||||
|
||||
|
@ -784,7 +784,7 @@ NTSTATUS open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lo
|
|||
len -= sizeof(INODE_REF) - 1 + ir->n;
|
||||
ir = (INODE_REF*)&ir->name[ir->n];
|
||||
}
|
||||
} else if (fcb->inode_item.st_nlink > 1 && tp.item->key.obj_type == TYPE_INODE_EXTREF) {
|
||||
} else if ((always_add_hl || fcb->inode_item.st_nlink > 1) && tp.item->key.obj_type == TYPE_INODE_EXTREF) {
|
||||
ULONG len;
|
||||
INODE_EXTREF* ier;
|
||||
|
||||
|
@ -971,6 +971,11 @@ NTSTATUS open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lo
|
|||
else
|
||||
fcb->prop_compression = PropCompression_None;
|
||||
}
|
||||
} else if (tp.item->key.offset == EA_CASE_SENSITIVE_HASH && di->n == sizeof(EA_CASE_SENSITIVE) - 1 && RtlCompareMemory(EA_CASE_SENSITIVE, di->name, di->n) == di->n) {
|
||||
if (di->m > 0) {
|
||||
fcb->case_sensitive = di->m == 1 && di->name[di->n] == '1';
|
||||
fcb->case_sensitive_set = TRUE;
|
||||
}
|
||||
} else if (di->n > sizeof(xapref) - 1 && RtlCompareMemory(xapref, di->name, sizeof(xapref) - 1) == sizeof(xapref) - 1) {
|
||||
dir_child* dc;
|
||||
ULONG utf16len;
|
||||
|
@ -1165,8 +1170,8 @@ NTSTATUS open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lo
|
|||
#endif
|
||||
|
||||
*pfcb = fcb2;
|
||||
release_fcb_lock(Vcb);
|
||||
reap_fcb(fcb);
|
||||
release_fcb_lock(Vcb);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
@ -1174,8 +1179,8 @@ NTSTATUS open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lo
|
|||
if (deleted_fcb) {
|
||||
InterlockedIncrement(&deleted_fcb->refcount);
|
||||
*pfcb = deleted_fcb;
|
||||
release_fcb_lock(Vcb);
|
||||
reap_fcb(fcb);
|
||||
release_fcb_lock(Vcb);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1514,7 +1519,7 @@ NTSTATUS open_fileref_child(_Requires_lock_held_(_Curr_->tree_lock) _Requires_ex
|
|||
#ifdef DEBUG_STATS
|
||||
time1 = KeQueryPerformanceCounter(NULL);
|
||||
#endif
|
||||
Status = open_fcb(Vcb, subvol, inode, dc->type, &dc->utf8, sf->fcb, &fcb, pooltype, Irp);
|
||||
Status = open_fcb(Vcb, subvol, inode, dc->type, &dc->utf8, FALSE, sf->fcb, &fcb, pooltype, Irp);
|
||||
#ifdef DEBUG_STATS
|
||||
time2 = KeQueryPerformanceCounter(NULL);
|
||||
Vcb->stats.open_fcb_calls++;
|
||||
|
@ -1692,7 +1697,16 @@ NTSTATUS open_fileref(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusiv
|
|||
#ifdef DEBUG_STATS
|
||||
time1 = KeQueryPerformanceCounter(NULL);
|
||||
#endif
|
||||
Status = open_fileref_child(Vcb, sf, &nb->us, case_sensitive, lastpart, streampart, pooltype, &sf2, Irp);
|
||||
BOOL cs = case_sensitive;
|
||||
|
||||
if (!cs) {
|
||||
if (streampart)
|
||||
cs = sf->parent->fcb->case_sensitive;
|
||||
else
|
||||
cs = sf->fcb->case_sensitive;
|
||||
}
|
||||
|
||||
Status = open_fileref_child(Vcb, sf, &nb->us, cs, lastpart, streampart, pooltype, &sf2, Irp);
|
||||
#ifdef DEBUG_STATS
|
||||
time2 = KeQueryPerformanceCounter(NULL);
|
||||
Vcb->stats.open_fileref_child_calls++;
|
||||
|
@ -2529,6 +2543,7 @@ static NTSTATUS create_stream(_Requires_lock_held_(_Curr_->tree_lock) _Requires_
|
|||
static const WCHAR DOSATTRIB[] = L"DOSATTRIB";
|
||||
static const WCHAR EA[] = L"EA";
|
||||
static const WCHAR reparse[] = L"reparse";
|
||||
static const WCHAR casesensitive_str[] = L"casesensitive";
|
||||
LARGE_INTEGER time;
|
||||
BTRFS_TIME now;
|
||||
ULONG utf8len, overhead;
|
||||
|
@ -2634,7 +2649,8 @@ static NTSTATUS create_stream(_Requires_lock_held_(_Curr_->tree_lock) _Requires_
|
|||
|
||||
if ((stream->Length == sizeof(DOSATTRIB) - sizeof(WCHAR) && RtlCompareMemory(stream->Buffer, DOSATTRIB, stream->Length) == stream->Length) ||
|
||||
(stream->Length == sizeof(EA) - sizeof(WCHAR) && RtlCompareMemory(stream->Buffer, EA, stream->Length) == stream->Length) ||
|
||||
(stream->Length == sizeof(reparse) - sizeof(WCHAR) && RtlCompareMemory(stream->Buffer, reparse, stream->Length) == stream->Length)) {
|
||||
(stream->Length == sizeof(reparse) - sizeof(WCHAR) && RtlCompareMemory(stream->Buffer, reparse, stream->Length) == stream->Length) ||
|
||||
(stream->Length == sizeof(casesensitive_str) - sizeof(WCHAR) && RtlCompareMemory(stream->Buffer, casesensitive_str, stream->Length) == stream->Length)) {
|
||||
free_fileref(parfileref);
|
||||
return STATUS_OBJECT_NAME_INVALID;
|
||||
}
|
||||
|
@ -3774,7 +3790,7 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO
|
|||
if (dc->fileref) {
|
||||
send_notification_fcb(fileref, FILE_NOTIFY_CHANGE_STREAM_NAME, FILE_ACTION_REMOVED_STREAM, &dc->name);
|
||||
|
||||
Status = delete_fileref(dc->fileref, NULL, NULL, rollback);
|
||||
Status = delete_fileref(dc->fileref, NULL, FALSE, NULL, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("delete_fileref returned %08x\n", Status);
|
||||
|
||||
|
@ -3953,30 +3969,198 @@ NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock)
|
|||
UNICODE_STRING name;
|
||||
BOOL hl_alloc = FALSE;
|
||||
file_ref *parfr, *fr;
|
||||
#ifdef __REACTOS__
|
||||
hardlink* hl;
|
||||
#endif
|
||||
|
||||
Status = open_fcb(Vcb, subvol, inode, 0, NULL, NULL, &fcb, PagedPool, Irp);
|
||||
Status = open_fcb(Vcb, subvol, inode, 0, NULL, TRUE, NULL, &fcb, PagedPool, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("open_fcb returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
ExAcquireResourceSharedLite(fcb->Header.Resource, TRUE);
|
||||
|
||||
if (fcb->inode_item.st_nlink == 0 || fcb->deleted) {
|
||||
ExReleaseResourceLite(fcb->Header.Resource);
|
||||
free_fcb(fcb);
|
||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (fcb->fileref) {
|
||||
*pfr = fcb->fileref;
|
||||
increase_fileref_refcount(fcb->fileref);
|
||||
free_fcb(fcb);
|
||||
ExReleaseResourceLite(fcb->Header.Resource);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#ifndef __REACTOS__
|
||||
hardlink* hl = CONTAINING_RECORD(fcb->hardlinks.Flink, hardlink, list_entry);
|
||||
#else
|
||||
hl = CONTAINING_RECORD(fcb->hardlinks.Flink, hardlink, list_entry);
|
||||
if (IsListEmpty(&fcb->hardlinks)) {
|
||||
ExReleaseResourceLite(fcb->Header.Resource);
|
||||
|
||||
ExAcquireResourceSharedLite(&Vcb->dirty_filerefs_lock, TRUE);
|
||||
|
||||
if (!IsListEmpty(&Vcb->dirty_filerefs)) {
|
||||
LIST_ENTRY* le = Vcb->dirty_filerefs.Flink;
|
||||
while (le != &Vcb->dirty_filerefs) {
|
||||
file_ref* fr = CONTAINING_RECORD(le, file_ref, list_entry_dirty);
|
||||
|
||||
if (fr->fcb == fcb) {
|
||||
ExReleaseResourceLite(&Vcb->dirty_filerefs_lock);
|
||||
increase_fileref_refcount(fr);
|
||||
free_fcb(fcb);
|
||||
*pfr = fr;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&Vcb->dirty_filerefs_lock);
|
||||
|
||||
{
|
||||
KEY searchkey;
|
||||
traverse_ptr tp;
|
||||
|
||||
searchkey.obj_id = fcb->inode;
|
||||
searchkey.obj_type = TYPE_INODE_REF;
|
||||
searchkey.offset = 0;
|
||||
|
||||
Status = find_item(Vcb, subvol, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("find_item returned %08x\n", Status);
|
||||
free_fcb(fcb);
|
||||
return Status;
|
||||
}
|
||||
|
||||
do {
|
||||
traverse_ptr next_tp;
|
||||
|
||||
if (tp.item->key.obj_id > fcb->inode || (tp.item->key.obj_id == fcb->inode && tp.item->key.obj_type > TYPE_INODE_EXTREF))
|
||||
break;
|
||||
|
||||
if (tp.item->key.obj_id == fcb->inode) {
|
||||
if (tp.item->key.obj_type == TYPE_INODE_REF) {
|
||||
INODE_REF* ir = (INODE_REF*)tp.item->data;
|
||||
#ifdef __REACTOS__
|
||||
ULONG stringlen;
|
||||
#endif
|
||||
|
||||
name = hl->name;
|
||||
parent = hl->parent;
|
||||
if (tp.item->size < offsetof(INODE_REF, name[0]) || tp.item->size < offsetof(INODE_REF, name[0]) + ir->n) {
|
||||
ERR("INODE_REF was too short\n");
|
||||
free_fcb(fcb);
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
#ifndef __REACTOS__
|
||||
ULONG stringlen;
|
||||
#endif
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(NULL, 0, &stringlen, ir->name, ir->n);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("RtlUTF8ToUnicodeN 1 returned %08x\n", Status);
|
||||
free_fcb(fcb);
|
||||
return Status;
|
||||
}
|
||||
|
||||
name.Length = name.MaximumLength = (UINT16)stringlen;
|
||||
|
||||
if (stringlen == 0)
|
||||
name.Buffer = NULL;
|
||||
else {
|
||||
name.Buffer = ExAllocatePoolWithTag(PagedPool, name.MaximumLength, ALLOC_TAG);
|
||||
|
||||
if (!name.Buffer) {
|
||||
ERR("out of memory\n");
|
||||
free_fcb(fcb);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(name.Buffer, stringlen, &stringlen, ir->name, ir->n);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("RtlUTF8ToUnicodeN 2 returned %08x\n", Status);
|
||||
ExFreePool(name.Buffer);
|
||||
free_fcb(fcb);
|
||||
return Status;
|
||||
}
|
||||
|
||||
hl_alloc = TRUE;
|
||||
}
|
||||
|
||||
parent = tp.item->key.offset;
|
||||
|
||||
break;
|
||||
} else if (tp.item->key.obj_type == TYPE_INODE_EXTREF) {
|
||||
INODE_EXTREF* ier = (INODE_EXTREF*)tp.item->data;
|
||||
#ifdef __REACTOS__
|
||||
ULONG stringlen;
|
||||
#endif
|
||||
|
||||
if (tp.item->size < offsetof(INODE_EXTREF, name[0]) || tp.item->size < offsetof(INODE_EXTREF, name[0]) + ier->n) {
|
||||
ERR("INODE_EXTREF was too short\n");
|
||||
free_fcb(fcb);
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
#ifndef __REACTOS__
|
||||
ULONG stringlen;
|
||||
#endif
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(NULL, 0, &stringlen, ier->name, ier->n);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("RtlUTF8ToUnicodeN 1 returned %08x\n", Status);
|
||||
free_fcb(fcb);
|
||||
return Status;
|
||||
}
|
||||
|
||||
name.Length = name.MaximumLength = (UINT16)stringlen;
|
||||
|
||||
if (stringlen == 0)
|
||||
name.Buffer = NULL;
|
||||
else {
|
||||
name.Buffer = ExAllocatePoolWithTag(PagedPool, name.MaximumLength, ALLOC_TAG);
|
||||
|
||||
if (!name.Buffer) {
|
||||
ERR("out of memory\n");
|
||||
free_fcb(fcb);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(name.Buffer, stringlen, &stringlen, ier->name, ier->n);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("RtlUTF8ToUnicodeN 2 returned %08x\n", Status);
|
||||
ExFreePool(name.Buffer);
|
||||
free_fcb(fcb);
|
||||
return Status;
|
||||
}
|
||||
|
||||
hl_alloc = TRUE;
|
||||
}
|
||||
|
||||
parent = ier->dir;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (find_next_item(Vcb, &tp, &next_tp, FALSE, Irp))
|
||||
tp = next_tp;
|
||||
else
|
||||
break;
|
||||
} while (TRUE);
|
||||
}
|
||||
|
||||
if (parent == 0) {
|
||||
WARN("trying to open inode with no references\n");
|
||||
free_fcb(fcb);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
} else {
|
||||
hardlink* hl = CONTAINING_RECORD(fcb->hardlinks.Flink, hardlink, list_entry);
|
||||
|
||||
name = hl->name;
|
||||
parent = hl->parent;
|
||||
|
||||
ExReleaseResourceLite(fcb->Header.Resource);
|
||||
}
|
||||
|
||||
if (parent == inode) { // subvolume root
|
||||
KEY searchkey;
|
||||
|
@ -4048,6 +4232,9 @@ NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock)
|
|||
if (stringlen == 0)
|
||||
name.Buffer = NULL;
|
||||
else {
|
||||
if (hl_alloc)
|
||||
ExFreePool(name.Buffer);
|
||||
|
||||
name.Buffer = ExAllocatePoolWithTag(PagedPool, name.MaximumLength, ALLOC_TAG);
|
||||
|
||||
if (!name.Buffer) {
|
||||
|
@ -4190,9 +4377,21 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur
|
|||
}
|
||||
|
||||
if (options & FILE_OPEN_BY_FILE_ID) {
|
||||
if (fn.Length == sizeof(UINT64) && related && RequestedDisposition == FILE_OPEN) {
|
||||
if (RequestedDisposition != FILE_OPEN) {
|
||||
WARN("FILE_OPEN_BY_FILE_ID not supported for anything other than FILE_OPEN\n");
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (fn.Length == sizeof(UINT64)) {
|
||||
UINT64 inode;
|
||||
|
||||
if (!related) {
|
||||
WARN("cannot open by short file ID unless related fileref also provided");
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
RtlCopyMemory(&inode, fn.Buffer, sizeof(UINT64));
|
||||
|
||||
if (related->fcb == Vcb->root_fileref->fcb && inode == 0)
|
||||
|
@ -4205,10 +4404,38 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur
|
|||
} else
|
||||
Status = open_fileref_by_inode(Vcb, related->fcb->subvol, inode, &fileref, Irp);
|
||||
|
||||
goto loaded;
|
||||
} else if (fn.Length == sizeof(FILE_ID_128)) {
|
||||
UINT64 inode, subvol_id;
|
||||
root* subvol = NULL;
|
||||
|
||||
RtlCopyMemory(&inode, fn.Buffer, sizeof(UINT64));
|
||||
RtlCopyMemory(&subvol_id, (UINT8*)fn.Buffer + sizeof(UINT64), sizeof(UINT64));
|
||||
|
||||
if (subvol_id == BTRFS_ROOT_FSTREE || (subvol_id >= 0x100 && subvol_id < 0x8000000000000000)) {
|
||||
LIST_ENTRY* le = Vcb->roots.Flink;
|
||||
while (le != &Vcb->roots) {
|
||||
root* r = CONTAINING_RECORD(le, root, list_entry);
|
||||
|
||||
if (r->id == subvol_id) {
|
||||
subvol = r;
|
||||
break;
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
}
|
||||
|
||||
if (!subvol) {
|
||||
WARN("subvol %llx not found\n", subvol_id);
|
||||
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
} else
|
||||
Status = open_fileref_by_inode(Vcb, subvol, inode, &fileref, Irp);
|
||||
|
||||
goto loaded;
|
||||
} else {
|
||||
WARN("FILE_OPEN_BY_FILE_ID only supported for inodes\n");
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
WARN("invalid ID size for FILE_OPEN_BY_FILE_ID\n");
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,49 @@
|
|||
|
||||
#include "btrfs_drv.h"
|
||||
|
||||
// not currently in mingw
|
||||
#ifndef _MSC_VER
|
||||
#define FileIdExtdDirectoryInformation (enum _FILE_INFORMATION_CLASS)60
|
||||
#define FileIdExtdBothDirectoryInformation (enum _FILE_INFORMATION_CLASS)63
|
||||
|
||||
typedef struct _FILE_ID_EXTD_DIR_INFORMATION {
|
||||
ULONG NextEntryOffset;
|
||||
ULONG FileIndex;
|
||||
LARGE_INTEGER CreationTime;
|
||||
LARGE_INTEGER LastAccessTime;
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
LARGE_INTEGER ChangeTime;
|
||||
LARGE_INTEGER EndOfFile;
|
||||
LARGE_INTEGER AllocationSize;
|
||||
ULONG FileAttributes;
|
||||
ULONG FileNameLength;
|
||||
ULONG EaSize;
|
||||
ULONG ReparsePointTag;
|
||||
FILE_ID_128 FileId;
|
||||
WCHAR FileName[1];
|
||||
} FILE_ID_EXTD_DIR_INFORMATION, *PFILE_ID_EXTD_DIR_INFORMATION;
|
||||
|
||||
typedef struct _FILE_ID_EXTD_BOTH_DIR_INFORMATION {
|
||||
ULONG NextEntryOffset;
|
||||
ULONG FileIndex;
|
||||
LARGE_INTEGER CreationTime;
|
||||
LARGE_INTEGER LastAccessTime;
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
LARGE_INTEGER ChangeTime;
|
||||
LARGE_INTEGER EndOfFile;
|
||||
LARGE_INTEGER AllocationSize;
|
||||
ULONG FileAttributes;
|
||||
ULONG FileNameLength;
|
||||
ULONG EaSize;
|
||||
ULONG ReparsePointTag;
|
||||
FILE_ID_128 FileId;
|
||||
CCHAR ShortNameLength;
|
||||
WCHAR ShortName[12];
|
||||
WCHAR FileName[1];
|
||||
} FILE_ID_EXTD_BOTH_DIR_INFORMATION, *PFILE_ID_EXTD_BOTH_DIR_INFORMATION;
|
||||
|
||||
#endif
|
||||
|
||||
enum DirEntryType {
|
||||
DirEntryType_File,
|
||||
DirEntryType_Self,
|
||||
|
@ -79,7 +122,7 @@ ULONG get_reparse_tag(device_extension* Vcb, root* subvol, UINT64 inode, UINT8 t
|
|||
if (!(atts & FILE_ATTRIBUTE_REPARSE_POINT))
|
||||
return 0;
|
||||
|
||||
Status = open_fcb(Vcb, subvol, inode, type, NULL, NULL, &fcb, PagedPool, Irp);
|
||||
Status = open_fcb(Vcb, subvol, inode, type, NULL, FALSE, NULL, &fcb, PagedPool, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("open_fcb returned %08x\n", Status);
|
||||
return 0;
|
||||
|
@ -221,7 +264,9 @@ static NTSTATUS query_dir_item(fcb* fcb, ccb* ccb, void* buf, LONG* len, PIRP Ir
|
|||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileDirectoryInformation ||
|
||||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileFullDirectoryInformation ||
|
||||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdBothDirectoryInformation ||
|
||||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdFullDirectoryInformation) {
|
||||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdFullDirectoryInformation ||
|
||||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdExtdDirectoryInformation ||
|
||||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdExtdBothDirectoryInformation) {
|
||||
|
||||
BOOL dotfile = de->name.Length > sizeof(WCHAR) && de->name.Buffer[0] == '.';
|
||||
|
||||
|
@ -231,7 +276,9 @@ static NTSTATUS query_dir_item(fcb* fcb, ccb* ccb, void* buf, LONG* len, PIRP Ir
|
|||
if (IrpSp->Parameters.QueryDirectory.FileInformationClass == FileBothDirectoryInformation ||
|
||||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileFullDirectoryInformation ||
|
||||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdBothDirectoryInformation ||
|
||||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdFullDirectoryInformation) {
|
||||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdFullDirectoryInformation ||
|
||||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdExtdDirectoryInformation ||
|
||||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdExtdBothDirectoryInformation) {
|
||||
ealen = get_ea_len(fcb->Vcb, r, inode, Irp);
|
||||
}
|
||||
}
|
||||
|
@ -465,6 +512,102 @@ static NTSTATUS query_dir_item(fcb* fcb, ccb* ccb, void* buf, LONG* len, PIRP Ir
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wswitch"
|
||||
#endif
|
||||
case FileIdExtdDirectoryInformation:
|
||||
{
|
||||
FILE_ID_EXTD_DIR_INFORMATION* fiedi = buf;
|
||||
|
||||
TRACE("FileIdExtdDirectoryInformation\n");
|
||||
|
||||
needed = offsetof(FILE_ID_EXTD_DIR_INFORMATION, FileName[0]) + de->name.Length;
|
||||
|
||||
if (needed > *len) {
|
||||
TRACE("buffer overflow - %u > %u\n", needed, *len);
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
fiedi->NextEntryOffset = 0;
|
||||
fiedi->FileIndex = 0;
|
||||
fiedi->CreationTime.QuadPart = unix_time_to_win(&ii.otime);
|
||||
fiedi->LastAccessTime.QuadPart = unix_time_to_win(&ii.st_atime);
|
||||
fiedi->LastWriteTime.QuadPart = unix_time_to_win(&ii.st_mtime);
|
||||
fiedi->ChangeTime.QuadPart = unix_time_to_win(&ii.st_ctime);
|
||||
fiedi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
|
||||
|
||||
if (de->type == BTRFS_TYPE_SYMLINK)
|
||||
fiedi->AllocationSize.QuadPart = 0;
|
||||
else if (atts & FILE_ATTRIBUTE_SPARSE_FILE)
|
||||
fiedi->AllocationSize.QuadPart = ii.st_blocks;
|
||||
else
|
||||
fiedi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size);
|
||||
|
||||
fiedi->FileAttributes = atts;
|
||||
fiedi->FileNameLength = de->name.Length;
|
||||
fiedi->EaSize = ealen;
|
||||
fiedi->ReparsePointTag = get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, ccb->lxss, Irp);
|
||||
|
||||
RtlCopyMemory(&fiedi->FileId.Identifier[0], &fcb->inode, sizeof(UINT64));
|
||||
RtlCopyMemory(&fiedi->FileId.Identifier[sizeof(UINT64)], &fcb->subvol->id, sizeof(UINT64));
|
||||
|
||||
RtlCopyMemory(fiedi->FileName, de->name.Buffer, de->name.Length);
|
||||
|
||||
*len -= needed;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
case FileIdExtdBothDirectoryInformation:
|
||||
{
|
||||
FILE_ID_EXTD_BOTH_DIR_INFORMATION* fiebdi = buf;
|
||||
|
||||
TRACE("FileIdExtdBothDirectoryInformation\n");
|
||||
|
||||
needed = offsetof(FILE_ID_EXTD_BOTH_DIR_INFORMATION, FileName[0]) + de->name.Length;
|
||||
|
||||
if (needed > *len) {
|
||||
TRACE("buffer overflow - %u > %u\n", needed, *len);
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
fiebdi->NextEntryOffset = 0;
|
||||
fiebdi->FileIndex = 0;
|
||||
fiebdi->CreationTime.QuadPart = unix_time_to_win(&ii.otime);
|
||||
fiebdi->LastAccessTime.QuadPart = unix_time_to_win(&ii.st_atime);
|
||||
fiebdi->LastWriteTime.QuadPart = unix_time_to_win(&ii.st_mtime);
|
||||
fiebdi->ChangeTime.QuadPart = unix_time_to_win(&ii.st_ctime);
|
||||
fiebdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
|
||||
|
||||
if (de->type == BTRFS_TYPE_SYMLINK)
|
||||
fiebdi->AllocationSize.QuadPart = 0;
|
||||
else if (atts & FILE_ATTRIBUTE_SPARSE_FILE)
|
||||
fiebdi->AllocationSize.QuadPart = ii.st_blocks;
|
||||
else
|
||||
fiebdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size);
|
||||
|
||||
fiebdi->FileAttributes = atts;
|
||||
fiebdi->FileNameLength = de->name.Length;
|
||||
fiebdi->EaSize = ealen;
|
||||
fiebdi->ReparsePointTag = get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, ccb->lxss, Irp);
|
||||
|
||||
RtlCopyMemory(&fiebdi->FileId.Identifier[0], &fcb->inode, sizeof(UINT64));
|
||||
RtlCopyMemory(&fiebdi->FileId.Identifier[sizeof(UINT64)], &fcb->subvol->id, sizeof(UINT64));
|
||||
|
||||
fiebdi->ShortNameLength = 0;
|
||||
|
||||
RtlCopyMemory(fiebdi->FileName, de->name.Buffer, de->name.Length);
|
||||
|
||||
*len -= needed;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
case FileNamesInformation:
|
||||
{
|
||||
FILE_NAMES_INFORMATION* fni = buf;
|
||||
|
@ -857,13 +1000,22 @@ static NTSTATUS query_directory(PIRP Irp) {
|
|||
|
||||
while (length > 0) {
|
||||
switch (IrpSp->Parameters.QueryDirectory.FileInformationClass) {
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wswitch"
|
||||
#endif
|
||||
case FileBothDirectoryInformation:
|
||||
case FileDirectoryInformation:
|
||||
case FileIdBothDirectoryInformation:
|
||||
case FileFullDirectoryInformation:
|
||||
case FileIdFullDirectoryInformation:
|
||||
case FileIdExtdDirectoryInformation:
|
||||
case FileIdExtdBothDirectoryInformation:
|
||||
length -= length % 8;
|
||||
break;
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
case FileNamesInformation:
|
||||
length -= length % 4;
|
||||
|
|
|
@ -21,7 +21,32 @@
|
|||
// not currently in mingw - introduced with Windows 10
|
||||
#ifndef _MSC_VER
|
||||
#define FileIdInformation (enum _FILE_INFORMATION_CLASS)59
|
||||
#define FileHardLinkFullIdInformation (enum _FILE_INFORMATION_CLASS)62
|
||||
#define FileDispositionInformationEx (enum _FILE_INFORMATION_CLASS)64
|
||||
#define FileRenameInformationEx (enum _FILE_INFORMATION_CLASS)65
|
||||
#define FileStatInformation (enum _FILE_INFORMATION_CLASS)68
|
||||
#define FileStatLxInformation (enum _FILE_INFORMATION_CLASS)70
|
||||
#define FileCaseSensitiveInformation (enum _FILE_INFORMATION_CLASS)71
|
||||
#define FileLinkInformationEx (enum _FILE_INFORMATION_CLASS)72
|
||||
|
||||
typedef struct _FILE_ID_INFORMATION {
|
||||
ULONGLONG VolumeSerialNumber;
|
||||
FILE_ID_128 FileId;
|
||||
} FILE_ID_INFORMATION, *PFILE_ID_INFORMATION;
|
||||
|
||||
typedef struct _FILE_STAT_INFORMATION {
|
||||
LARGE_INTEGER FileId;
|
||||
LARGE_INTEGER CreationTime;
|
||||
LARGE_INTEGER LastAccessTime;
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
LARGE_INTEGER ChangeTime;
|
||||
LARGE_INTEGER AllocationSize;
|
||||
LARGE_INTEGER EndOfFile;
|
||||
ULONG FileAttributes;
|
||||
ULONG ReparseTag;
|
||||
ULONG NumberOfLinks;
|
||||
ACCESS_MASK EffectiveAccess;
|
||||
} FILE_STAT_INFORMATION, *PFILE_STAT_INFORMATION;
|
||||
|
||||
typedef struct _FILE_STAT_LX_INFORMATION {
|
||||
LARGE_INTEGER FileId;
|
||||
|
@ -49,9 +74,119 @@ typedef struct _FILE_STAT_LX_INFORMATION {
|
|||
#define LX_FILE_METADATA_HAS_DEVICE_ID 0x08
|
||||
#define LX_FILE_CASE_SENSITIVE_DIR 0x10
|
||||
|
||||
typedef struct _FILE_RENAME_INFORMATION_EX {
|
||||
union {
|
||||
BOOLEAN ReplaceIfExists;
|
||||
ULONG Flags;
|
||||
};
|
||||
HANDLE RootDirectory;
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
} FILE_RENAME_INFORMATION_EX, *PFILE_RENAME_INFORMATION_EX;
|
||||
|
||||
typedef struct _FILE_DISPOSITION_INFORMATION_EX {
|
||||
ULONG Flags;
|
||||
} FILE_DISPOSITION_INFORMATION_EX, *PFILE_DISPOSITION_INFORMATION_EX;
|
||||
|
||||
typedef struct _FILE_LINK_INFORMATION_EX {
|
||||
union {
|
||||
BOOLEAN ReplaceIfExists;
|
||||
ULONG Flags;
|
||||
};
|
||||
HANDLE RootDirectory;
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
} FILE_LINK_INFORMATION_EX, *PFILE_LINK_INFORMATION_EX;
|
||||
|
||||
typedef struct _FILE_CASE_SENSITIVE_INFORMATION {
|
||||
ULONG Flags;
|
||||
} FILE_CASE_SENSITIVE_INFORMATION, *PFILE_CASE_SENSITIVE_INFORMATION;
|
||||
|
||||
typedef struct _FILE_LINK_ENTRY_FULL_ID_INFORMATION {
|
||||
ULONG NextEntryOffset;
|
||||
FILE_ID_128 ParentFileId;
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
} FILE_LINK_ENTRY_FULL_ID_INFORMATION, *PFILE_LINK_ENTRY_FULL_ID_INFORMATION;
|
||||
|
||||
typedef struct _FILE_LINKS_FULL_ID_INFORMATION {
|
||||
ULONG BytesNeeded;
|
||||
ULONG EntriesReturned;
|
||||
FILE_LINK_ENTRY_FULL_ID_INFORMATION Entry;
|
||||
} FILE_LINKS_FULL_ID_INFORMATION, *PFILE_LINKS_FULL_ID_INFORMATION;
|
||||
|
||||
#define FILE_RENAME_REPLACE_IF_EXISTS 0x001
|
||||
#define FILE_RENAME_POSIX_SEMANTICS 0x002
|
||||
#define FILE_RENAME_SUPPRESS_PIN_STATE_INHERITANCE 0x004
|
||||
#define FILE_RENAME_SUPPRESS_STORAGE_RESERVE_INHERITANCE 0x008
|
||||
#define FILE_RENAME_NO_INCREASE_AVAILABLE_SPACE 0x010
|
||||
#define FILE_RENAME_NO_DECREASE_AVAILABLE_SPACE 0x020
|
||||
#define FILE_RENAME_IGNORE_READONLY_ATTRIBUTE 0x040
|
||||
#define FILE_RENAME_FORCE_RESIZE_TARGET_SR 0x080
|
||||
#define FILE_RENAME_FORCE_RESIZE_SOURCE_SR 0x100
|
||||
|
||||
#define FILE_DISPOSITION_DELETE 0x1
|
||||
#define FILE_DISPOSITION_POSIX_SEMANTICS 0x2
|
||||
#define FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK 0x4
|
||||
#define FILE_DISPOSITION_ON_CLOSE 0x8
|
||||
|
||||
#define FILE_LINK_REPLACE_IF_EXISTS 0x001
|
||||
#define FILE_LINK_POSIX_SEMANTICS 0x002
|
||||
#define FILE_LINK_SUPPRESS_STORAGE_RESERVE_INHERITANCE 0x008
|
||||
#define FILE_LINK_NO_INCREASE_AVAILABLE_SPACE 0x010
|
||||
#define FILE_LINK_NO_DECREASE_AVAILABLE_SPACE 0x020
|
||||
#define FILE_LINK_IGNORE_READONLY_ATTRIBUTE 0x040
|
||||
#define FILE_LINK_FORCE_RESIZE_TARGET_SR 0x080
|
||||
#define FILE_LINK_FORCE_RESIZE_SOURCE_SR 0x100
|
||||
|
||||
#define FILE_CS_FLAG_CASE_SENSITIVE_DIR 1
|
||||
|
||||
#else
|
||||
|
||||
#define FILE_RENAME_INFORMATION_EX FILE_RENAME_INFORMATION
|
||||
#define FILE_LINK_INFORMATION_EX FILE_LINK_INFORMATION
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __REACTOS__
|
||||
typedef struct _FILE_RENAME_INFORMATION_EX {
|
||||
union {
|
||||
BOOLEAN ReplaceIfExists;
|
||||
ULONG Flags;
|
||||
};
|
||||
HANDLE RootDirectory;
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
} FILE_RENAME_INFORMATION_EX, *PFILE_RENAME_INFORMATION_EX;
|
||||
|
||||
typedef struct _FILE_DISPOSITION_INFORMATION_EX {
|
||||
ULONG Flags;
|
||||
} FILE_DISPOSITION_INFORMATION_EX, *PFILE_DISPOSITION_INFORMATION_EX;
|
||||
|
||||
typedef struct _FILE_LINK_INFORMATION_EX {
|
||||
union {
|
||||
BOOLEAN ReplaceIfExists;
|
||||
ULONG Flags;
|
||||
};
|
||||
HANDLE RootDirectory;
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
} FILE_LINK_INFORMATION_EX, *PFILE_LINK_INFORMATION_EX;
|
||||
|
||||
#define FILE_RENAME_REPLACE_IF_EXISTS 0x001
|
||||
#define FILE_RENAME_POSIX_SEMANTICS 0x002
|
||||
#define FILE_RENAME_IGNORE_READONLY_ATTRIBUTE 0x040
|
||||
|
||||
#define FILE_DISPOSITION_DELETE 0x1
|
||||
#define FILE_DISPOSITION_POSIX_SEMANTICS 0x2
|
||||
#define FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK 0x4
|
||||
|
||||
#define FILE_LINK_REPLACE_IF_EXISTS 0x001
|
||||
#define FILE_LINK_POSIX_SEMANTICS 0x002
|
||||
#define FILE_LINK_IGNORE_READONLY_ATTRIBUTE 0x040
|
||||
#endif
|
||||
|
||||
static NTSTATUS set_basic_information(device_extension* Vcb, PIRP Irp, PFILE_OBJECT FileObject) {
|
||||
FILE_BASIC_INFORMATION* fbi = Irp->AssociatedIrp.SystemBuffer;
|
||||
fcb* fcb = FileObject->FsContext;
|
||||
|
@ -219,20 +354,29 @@ end:
|
|||
return Status;
|
||||
}
|
||||
|
||||
static NTSTATUS set_disposition_information(device_extension* Vcb, PIRP Irp, PFILE_OBJECT FileObject) {
|
||||
FILE_DISPOSITION_INFORMATION* fdi = Irp->AssociatedIrp.SystemBuffer;
|
||||
static NTSTATUS set_disposition_information(device_extension* Vcb, PIRP Irp, PFILE_OBJECT FileObject, BOOL ex) {
|
||||
fcb* fcb = FileObject->FsContext;
|
||||
ccb* ccb = FileObject->FsContext2;
|
||||
file_ref* fileref = ccb ? ccb->fileref : NULL;
|
||||
ULONG atts;
|
||||
ULONG atts, flags;
|
||||
NTSTATUS Status;
|
||||
|
||||
if (!fileref)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if (ex) {
|
||||
FILE_DISPOSITION_INFORMATION_EX* fdi = Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
flags = fdi->Flags;
|
||||
} else {
|
||||
FILE_DISPOSITION_INFORMATION* fdi = Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
flags = fdi->DeleteFile ? FILE_DISPOSITION_DELETE : 0;
|
||||
}
|
||||
|
||||
ExAcquireResourceExclusiveLite(fcb->Header.Resource, TRUE);
|
||||
|
||||
TRACE("changing delete_on_close to %s for %S (fcb %p)\n", fdi->DeleteFile ? "TRUE" : "FALSE", file_desc(FileObject), fcb);
|
||||
TRACE("changing delete_on_close to %s for %S (fcb %p)\n", flags & FILE_DISPOSITION_DELETE ? "TRUE" : "FALSE", file_desc(FileObject), fcb);
|
||||
|
||||
if (fcb->ads) {
|
||||
if (fileref->parent)
|
||||
|
@ -261,14 +405,19 @@ static NTSTATUS set_disposition_information(device_extension* Vcb, PIRP Irp, PFI
|
|||
}
|
||||
|
||||
if (!MmFlushImageSection(&fcb->nonpaged->segment_object, MmFlushForDelete)) {
|
||||
TRACE("trying to delete file which is being mapped as an image\n");
|
||||
Status = STATUS_CANNOT_DELETE;
|
||||
goto end;
|
||||
if (!ex || flags & FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK) {
|
||||
TRACE("trying to delete file which is being mapped as an image\n");
|
||||
Status = STATUS_CANNOT_DELETE;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
ccb->fileref->delete_on_close = fdi->DeleteFile;
|
||||
ccb->fileref->delete_on_close = flags & FILE_DISPOSITION_DELETE;
|
||||
|
||||
FileObject->DeletePending = fdi->DeleteFile;
|
||||
FileObject->DeletePending = flags & FILE_DISPOSITION_DELETE;
|
||||
|
||||
if (flags & FILE_DISPOSITION_DELETE && flags & FILE_DISPOSITION_POSIX_SEMANTICS)
|
||||
ccb->fileref->posix_delete = TRUE;
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
|
@ -276,7 +425,7 @@ end:
|
|||
ExReleaseResourceLite(fcb->Header.Resource);
|
||||
|
||||
// send notification that directory is about to be deleted
|
||||
if (NT_SUCCESS(Status) && fdi->DeleteFile && fcb->type == BTRFS_TYPE_DIRECTORY) {
|
||||
if (NT_SUCCESS(Status) && flags & FILE_DISPOSITION_DELETE && fcb->type == BTRFS_TYPE_DIRECTORY) {
|
||||
FsRtlNotifyFullChangeDirectory(Vcb->NotifySync, &Vcb->DirNotifyList, FileObject->FsContext,
|
||||
NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
|
||||
}
|
||||
|
@ -1161,7 +1310,7 @@ static NTSTATUS move_across_subvols(file_ref* fileref, ccb* ccb, file_ref* destd
|
|||
}
|
||||
|
||||
if (!me->dummyfileref->fcb->ads) {
|
||||
Status = delete_fileref(me->dummyfileref, NULL, Irp, rollback);
|
||||
Status = delete_fileref(me->dummyfileref, NULL, FALSE, Irp, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("delete_fileref returned %08x\n", Status);
|
||||
goto end;
|
||||
|
@ -1217,7 +1366,7 @@ static NTSTATUS move_across_subvols(file_ref* fileref, ccb* ccb, file_ref* destd
|
|||
me = CONTAINING_RECORD(le, move_entry, list_entry);
|
||||
|
||||
if (me->dummyfileref->fcb->ads && me->parent->dummyfileref->fcb->deleted) {
|
||||
Status = delete_fileref(me->dummyfileref, NULL, Irp, rollback);
|
||||
Status = delete_fileref(me->dummyfileref, NULL, FALSE, Irp, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("delete_fileref returned %08x\n", Status);
|
||||
goto end;
|
||||
|
@ -1349,9 +1498,8 @@ void insert_dir_child_into_hash_lists(fcb* fcb, dir_child* dc) {
|
|||
}
|
||||
}
|
||||
|
||||
static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OBJECT FileObject, PFILE_OBJECT tfo) {
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
FILE_RENAME_INFORMATION* fri = Irp->AssociatedIrp.SystemBuffer;
|
||||
static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OBJECT FileObject, PFILE_OBJECT tfo, BOOL ex) {
|
||||
FILE_RENAME_INFORMATION_EX* fri = Irp->AssociatedIrp.SystemBuffer;
|
||||
fcb *fcb = FileObject->FsContext;
|
||||
ccb* ccb = FileObject->FsContext2;
|
||||
file_ref *fileref = ccb ? ccb->fileref : NULL, *oldfileref = NULL, *related = NULL, *fr2 = NULL;
|
||||
|
@ -1366,11 +1514,17 @@ static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OB
|
|||
hardlink* hl;
|
||||
SECURITY_SUBJECT_CONTEXT subjcont;
|
||||
ACCESS_MASK access;
|
||||
ULONG flags;
|
||||
|
||||
InitializeListHead(&rollback);
|
||||
|
||||
if (ex)
|
||||
flags = fri->Flags;
|
||||
else
|
||||
flags = fri->ReplaceIfExists ? FILE_RENAME_REPLACE_IF_EXISTS : 0;
|
||||
|
||||
TRACE("tfo = %p\n", tfo);
|
||||
TRACE("ReplaceIfExists = %u\n", IrpSp->Parameters.SetFile.ReplaceIfExists);
|
||||
TRACE("Flags = %x\n", flags);
|
||||
TRACE("RootDirectory = %p\n", fri->RootDirectory);
|
||||
TRACE("FileName = %.*S\n", fri->FileNameLength / sizeof(WCHAR), fri->FileName);
|
||||
|
||||
|
@ -1451,16 +1605,21 @@ static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OB
|
|||
TRACE("destination file %S already exists\n", file_desc_fileref(oldfileref));
|
||||
|
||||
if (fileref != oldfileref && !oldfileref->deleted) {
|
||||
if (!IrpSp->Parameters.SetFile.ReplaceIfExists) {
|
||||
if (!(flags & FILE_RENAME_REPLACE_IF_EXISTS)) {
|
||||
Status = STATUS_OBJECT_NAME_COLLISION;
|
||||
goto end;
|
||||
} else if ((oldfileref->open_count >= 1 || has_open_children(oldfileref)) && !oldfileref->deleted) {
|
||||
} else if (fileref == oldfileref) {
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
goto end;
|
||||
} else if (!(flags & FILE_RENAME_POSIX_SEMANTICS) && (oldfileref->open_count > 0 || has_open_children(oldfileref)) && !oldfileref->deleted) {
|
||||
WARN("trying to overwrite open file\n");
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (oldfileref->fcb->type == BTRFS_TYPE_DIRECTORY) {
|
||||
} else if (!(flags & FILE_RENAME_IGNORE_READONLY_ATTRIBUTE) && oldfileref->fcb->atts & FILE_ATTRIBUTE_READONLY) {
|
||||
WARN("trying to overwrite readonly file\n");
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
goto end;
|
||||
} else if (oldfileref->fcb->type == BTRFS_TYPE_DIRECTORY) {
|
||||
WARN("trying to overwrite directory\n");
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
goto end;
|
||||
|
@ -1516,7 +1675,12 @@ static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OB
|
|||
|
||||
SeReleaseSubjectContext(&subjcont);
|
||||
|
||||
Status = delete_fileref(oldfileref, NULL, Irp, &rollback);
|
||||
if (oldfileref->open_count > 0 && flags & FILE_RENAME_POSIX_SEMANTICS) {
|
||||
oldfileref->delete_on_close = TRUE;
|
||||
oldfileref->posix_delete = TRUE;
|
||||
}
|
||||
|
||||
Status = delete_fileref(oldfileref, NULL, oldfileref->open_count > 0 && flags & FILE_RENAME_POSIX_SEMANTICS, Irp, &rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("delete_fileref returned %08x\n", Status);
|
||||
goto end;
|
||||
|
@ -2177,8 +2341,8 @@ static NTSTATUS set_position_information(PFILE_OBJECT FileObject, PIRP Irp) {
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS set_link_information(device_extension* Vcb, PIRP Irp, PFILE_OBJECT FileObject, PFILE_OBJECT tfo) {
|
||||
FILE_LINK_INFORMATION* fli = Irp->AssociatedIrp.SystemBuffer;
|
||||
static NTSTATUS set_link_information(device_extension* Vcb, PIRP Irp, PFILE_OBJECT FileObject, PFILE_OBJECT tfo, BOOL ex) {
|
||||
FILE_LINK_INFORMATION_EX* fli = Irp->AssociatedIrp.SystemBuffer;
|
||||
fcb *fcb = FileObject->FsContext, *tfofcb, *parfcb;
|
||||
ccb* ccb = FileObject->FsContext2;
|
||||
file_ref *fileref = ccb ? ccb->fileref : NULL, *oldfileref = NULL, *related = NULL, *fr2 = NULL;
|
||||
|
@ -2194,13 +2358,19 @@ static NTSTATUS set_link_information(device_extension* Vcb, PIRP Irp, PFILE_OBJE
|
|||
ACCESS_MASK access;
|
||||
SECURITY_SUBJECT_CONTEXT subjcont;
|
||||
dir_child* dc = NULL;
|
||||
ULONG flags;
|
||||
|
||||
InitializeListHead(&rollback);
|
||||
|
||||
// FIXME - check fli length
|
||||
// FIXME - don't ignore fli->RootDirectory
|
||||
|
||||
TRACE("ReplaceIfExists = %x\n", fli->ReplaceIfExists);
|
||||
if (ex)
|
||||
flags = fli->Flags;
|
||||
else
|
||||
flags = fli->ReplaceIfExists ? FILE_LINK_REPLACE_IF_EXISTS : 0;
|
||||
|
||||
TRACE("flags = %x\n", flags);
|
||||
TRACE("RootDirectory = %p\n", fli->RootDirectory);
|
||||
TRACE("FileNameLength = %x\n", fli->FileNameLength);
|
||||
TRACE("FileName = %.*S\n", fli->FileNameLength / sizeof(WCHAR), fli->FileName);
|
||||
|
@ -2292,19 +2462,21 @@ static NTSTATUS set_link_information(device_extension* Vcb, PIRP Irp, PFILE_OBJE
|
|||
if (!oldfileref->deleted) {
|
||||
WARN("destination file %S already exists\n", file_desc_fileref(oldfileref));
|
||||
|
||||
if (!fli->ReplaceIfExists) {
|
||||
if (!(flags & FILE_LINK_REPLACE_IF_EXISTS)) {
|
||||
Status = STATUS_OBJECT_NAME_COLLISION;
|
||||
goto end;
|
||||
} else if (oldfileref->open_count >= 1 && !oldfileref->deleted) {
|
||||
WARN("trying to overwrite open file\n");
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
goto end;
|
||||
} else if (fileref == oldfileref) {
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (oldfileref->fcb->type == BTRFS_TYPE_DIRECTORY) {
|
||||
} else if (!(flags & FILE_LINK_POSIX_SEMANTICS) && (oldfileref->open_count > 0 || has_open_children(oldfileref)) && !oldfileref->deleted) {
|
||||
WARN("trying to overwrite open file\n");
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
goto end;
|
||||
} else if (!(flags & FILE_LINK_IGNORE_READONLY_ATTRIBUTE) && oldfileref->fcb->atts & FILE_ATTRIBUTE_READONLY) {
|
||||
WARN("trying to overwrite readonly file\n");
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
goto end;
|
||||
} else if (oldfileref->fcb->type == BTRFS_TYPE_DIRECTORY) {
|
||||
WARN("trying to overwrite directory\n");
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
goto end;
|
||||
|
@ -2353,7 +2525,12 @@ static NTSTATUS set_link_information(device_extension* Vcb, PIRP Irp, PFILE_OBJE
|
|||
|
||||
SeReleaseSubjectContext(&subjcont);
|
||||
|
||||
Status = delete_fileref(oldfileref, NULL, Irp, &rollback);
|
||||
if (oldfileref->open_count > 0 && flags & FILE_RENAME_POSIX_SEMANTICS) {
|
||||
oldfileref->delete_on_close = TRUE;
|
||||
oldfileref->posix_delete = TRUE;
|
||||
}
|
||||
|
||||
Status = delete_fileref(oldfileref, NULL, oldfileref->open_count > 0 && flags & FILE_RENAME_POSIX_SEMANTICS, Irp, &rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("delete_fileref returned %08x\n", Status);
|
||||
goto end;
|
||||
|
@ -2608,6 +2785,40 @@ end:
|
|||
return Status;
|
||||
}
|
||||
|
||||
#ifndef __REACTOS__
|
||||
static NTSTATUS set_case_sensitive_information(PIRP Irp) {
|
||||
FILE_CASE_SENSITIVE_INFORMATION* fcsi = (FILE_CASE_SENSITIVE_INFORMATION*)Irp->AssociatedIrp.SystemBuffer;
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
if (IrpSp->Parameters.FileSystemControl.InputBufferLength < sizeof(FILE_CASE_SENSITIVE_INFORMATION))
|
||||
return STATUS_INFO_LENGTH_MISMATCH;
|
||||
|
||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
|
||||
if (!FileObject)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
fcb* fcb = FileObject->FsContext;
|
||||
|
||||
if (!fcb)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if (!(fcb->atts & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
WARN("cannot set case-sensitive flag on anything other than directory\n");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, TRUE);
|
||||
|
||||
fcb->case_sensitive = fcsi->Flags & FILE_CS_FLAG_CASE_SENSITIVE_DIR;
|
||||
mark_fcb_dirty(fcb);
|
||||
|
||||
ExReleaseResourceLite(&fcb->Vcb->tree_lock);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
_Dispatch_type_(IRP_MJ_SET_INFORMATION)
|
||||
_Function_class_(DRIVER_DISPATCH)
|
||||
NTSTATUS NTAPI drv_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
|
||||
|
@ -2655,7 +2866,11 @@ NTSTATUS NTAPI drv_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|||
}
|
||||
|
||||
if (fcb != Vcb->dummy_fcb && is_subvol_readonly(fcb->subvol, Irp) && IrpSp->Parameters.SetFile.FileInformationClass != FilePositionInformation &&
|
||||
#ifndef __REACTOS__
|
||||
(fcb->inode != SUBVOL_ROOT_INODE || (IrpSp->Parameters.SetFile.FileInformationClass != FileBasicInformation && IrpSp->Parameters.SetFile.FileInformationClass != FileRenameInformation && IrpSp->Parameters.SetFile.FileInformationClass != FileRenameInformationEx))) {
|
||||
#else
|
||||
(fcb->inode != SUBVOL_ROOT_INODE || (IrpSp->Parameters.SetFile.FileInformationClass != FileBasicInformation && IrpSp->Parameters.SetFile.FileInformationClass != FileRenameInformation))) {
|
||||
#endif
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
goto end;
|
||||
}
|
||||
|
@ -2704,7 +2919,7 @@ NTSTATUS NTAPI drv_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|||
break;
|
||||
}
|
||||
|
||||
Status = set_disposition_information(Vcb, Irp, IrpSp->FileObject);
|
||||
Status = set_disposition_information(Vcb, Irp, IrpSp->FileObject, FALSE);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -2726,7 +2941,7 @@ NTSTATUS NTAPI drv_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|||
|
||||
case FileLinkInformation:
|
||||
TRACE("FileLinkInformation\n");
|
||||
Status = set_link_information(Vcb, Irp, IrpSp->FileObject, IrpSp->Parameters.SetFile.FileObject);
|
||||
Status = set_link_information(Vcb, Irp, IrpSp->FileObject, IrpSp->Parameters.SetFile.FileObject, FALSE);
|
||||
break;
|
||||
|
||||
case FilePositionInformation:
|
||||
|
@ -2737,7 +2952,7 @@ NTSTATUS NTAPI drv_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|||
case FileRenameInformation:
|
||||
TRACE("FileRenameInformation\n");
|
||||
// FIXME - make this work with streams
|
||||
Status = set_rename_information(Vcb, Irp, IrpSp->FileObject, IrpSp->Parameters.SetFile.FileObject);
|
||||
Status = set_rename_information(Vcb, Irp, IrpSp->FileObject, IrpSp->Parameters.SetFile.FileObject, FALSE);
|
||||
break;
|
||||
|
||||
case FileValidDataLengthInformation:
|
||||
|
@ -2755,6 +2970,52 @@ NTSTATUS NTAPI drv_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|||
break;
|
||||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wswitch"
|
||||
#endif
|
||||
#ifndef __REACTOS__
|
||||
case FileDispositionInformationEx:
|
||||
{
|
||||
TRACE("FileDispositionInformationEx\n");
|
||||
|
||||
if (Irp->RequestorMode == UserMode && !(ccb->access & DELETE)) {
|
||||
WARN("insufficient privileges\n");
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
Status = set_disposition_information(Vcb, Irp, IrpSp->FileObject, TRUE);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case FileRenameInformationEx:
|
||||
TRACE("FileRenameInformationEx\n");
|
||||
Status = set_rename_information(Vcb, Irp, IrpSp->FileObject, IrpSp->Parameters.SetFile.FileObject, TRUE);
|
||||
break;
|
||||
|
||||
case FileLinkInformationEx:
|
||||
TRACE("FileLinkInformationEx\n");
|
||||
Status = set_link_information(Vcb, Irp, IrpSp->FileObject, IrpSp->Parameters.SetFile.FileObject, TRUE);
|
||||
break;
|
||||
|
||||
case FileCaseSensitiveInformation:
|
||||
TRACE("FileCaseSensitiveInformation\n");
|
||||
|
||||
if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_WRITE_ATTRIBUTES)) {
|
||||
WARN("insufficient privileges\n");
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
Status = set_case_sensitive_information(Irp);
|
||||
break;
|
||||
#endif
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
default:
|
||||
WARN("unknown FileInformationClass %u\n", IrpSp->Parameters.SetFile.FileInformationClass);
|
||||
}
|
||||
|
@ -3362,16 +3623,176 @@ static NTSTATUS fill_in_hard_link_information(FILE_LINKS_INFORMATION* fli, file_
|
|||
#endif /* __REACTOS__ */
|
||||
|
||||
#if (NTDDI_VERSION >= NTDDI_WIN10)
|
||||
#ifdef __MINGW32__
|
||||
typedef struct _FILE_ID_128 {
|
||||
UCHAR Identifier[16];
|
||||
} FILE_ID_128, *PFILE_ID_128;
|
||||
static NTSTATUS fill_in_hard_link_full_id_information(FILE_LINKS_FULL_ID_INFORMATION* flfii, file_ref* fileref, PIRP Irp, LONG* length) {
|
||||
NTSTATUS Status;
|
||||
LIST_ENTRY* le;
|
||||
LONG bytes_needed;
|
||||
FILE_LINK_ENTRY_FULL_ID_INFORMATION* flefii;
|
||||
BOOL overflow = FALSE;
|
||||
fcb* fcb = fileref->fcb;
|
||||
ULONG len;
|
||||
|
||||
typedef struct _FILE_ID_INFORMATION {
|
||||
ULONGLONG VolumeSerialNumber;
|
||||
FILE_ID_128 FileId;
|
||||
} FILE_ID_INFORMATION, *PFILE_ID_INFORMATION;
|
||||
#endif
|
||||
if (fcb->ads)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if (*length < (LONG)offsetof(FILE_LINKS_FULL_ID_INFORMATION, Entry))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
RtlZeroMemory(flfii, *length);
|
||||
|
||||
bytes_needed = offsetof(FILE_LINKS_FULL_ID_INFORMATION, Entry);
|
||||
len = bytes_needed;
|
||||
flefii = NULL;
|
||||
|
||||
ExAcquireResourceSharedLite(fcb->Header.Resource, TRUE);
|
||||
|
||||
if (fcb->inode == SUBVOL_ROOT_INODE) {
|
||||
ULONG namelen;
|
||||
|
||||
if (fcb == fcb->Vcb->root_fileref->fcb)
|
||||
namelen = sizeof(WCHAR);
|
||||
else
|
||||
namelen = fileref->dc->name.Length;
|
||||
|
||||
bytes_needed += offsetof(FILE_LINK_ENTRY_FULL_ID_INFORMATION, FileName[0]) + namelen;
|
||||
|
||||
if (bytes_needed > *length)
|
||||
overflow = TRUE;
|
||||
|
||||
if (!overflow) {
|
||||
flefii = &flfii->Entry;
|
||||
|
||||
flefii->NextEntryOffset = 0;
|
||||
|
||||
if (fcb == fcb->Vcb->root_fileref->fcb) {
|
||||
RtlZeroMemory(&flefii->ParentFileId.Identifier[0], sizeof(FILE_ID_128));
|
||||
flefii->FileNameLength = 1;
|
||||
flefii->FileName[0] = '.';
|
||||
} else {
|
||||
RtlCopyMemory(&flefii->ParentFileId.Identifier[0], &fileref->parent->fcb->inode, sizeof(UINT64));
|
||||
RtlCopyMemory(&flefii->ParentFileId.Identifier[sizeof(UINT64)], &fileref->parent->fcb->subvol->id, sizeof(UINT64));
|
||||
|
||||
flefii->FileNameLength = fileref->dc->name.Length / sizeof(WCHAR);
|
||||
RtlCopyMemory(flefii->FileName, fileref->dc->name.Buffer, fileref->dc->name.Length);
|
||||
}
|
||||
|
||||
flfii->EntriesReturned++;
|
||||
|
||||
len = bytes_needed;
|
||||
}
|
||||
} else {
|
||||
ExAcquireResourceExclusiveLite(&fcb->Vcb->fileref_lock, TRUE);
|
||||
|
||||
if (IsListEmpty(&fcb->hardlinks)) {
|
||||
bytes_needed += offsetof(FILE_LINK_ENTRY_FULL_ID_INFORMATION, FileName[0]) + fileref->dc->name.Length;
|
||||
|
||||
if (bytes_needed > *length)
|
||||
overflow = TRUE;
|
||||
|
||||
if (!overflow) {
|
||||
flefii = &flfii->Entry;
|
||||
|
||||
flefii->NextEntryOffset = 0;
|
||||
|
||||
RtlCopyMemory(&flefii->ParentFileId.Identifier[0], &fileref->parent->fcb->inode, sizeof(UINT64));
|
||||
RtlCopyMemory(&flefii->ParentFileId.Identifier[sizeof(UINT64)], &fileref->parent->fcb->subvol->id, sizeof(UINT64));
|
||||
|
||||
flefii->FileNameLength = fileref->dc->name.Length / sizeof(WCHAR);
|
||||
RtlCopyMemory(flefii->FileName, fileref->dc->name.Buffer, fileref->dc->name.Length);
|
||||
|
||||
flfii->EntriesReturned++;
|
||||
|
||||
len = bytes_needed;
|
||||
}
|
||||
} else {
|
||||
le = fcb->hardlinks.Flink;
|
||||
while (le != &fcb->hardlinks) {
|
||||
hardlink* hl = CONTAINING_RECORD(le, hardlink, list_entry);
|
||||
file_ref* parfr;
|
||||
|
||||
TRACE("parent %llx, index %llx, name %.*S\n", hl->parent, hl->index, hl->name.Length / sizeof(WCHAR), hl->name.Buffer);
|
||||
|
||||
Status = open_fileref_by_inode(fcb->Vcb, fcb->subvol, hl->parent, &parfr, Irp);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("open_fileref_by_inode returned %08x\n", Status);
|
||||
} else if (!parfr->deleted) {
|
||||
LIST_ENTRY* le2;
|
||||
BOOL found = FALSE, deleted = FALSE;
|
||||
UNICODE_STRING* fn = NULL;
|
||||
|
||||
le2 = parfr->children.Flink;
|
||||
while (le2 != &parfr->children) {
|
||||
file_ref* fr2 = CONTAINING_RECORD(le2, file_ref, list_entry);
|
||||
|
||||
if (fr2->dc->index == hl->index) {
|
||||
found = TRUE;
|
||||
deleted = fr2->deleted;
|
||||
|
||||
if (!deleted)
|
||||
fn = &fr2->dc->name;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
le2 = le2->Flink;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
fn = &hl->name;
|
||||
|
||||
if (!deleted) {
|
||||
TRACE("fn = %.*S (found = %u)\n", fn->Length / sizeof(WCHAR), fn->Buffer, found);
|
||||
|
||||
if (flefii)
|
||||
bytes_needed = (LONG)sector_align(bytes_needed, 8);
|
||||
|
||||
bytes_needed += offsetof(FILE_LINK_ENTRY_FULL_ID_INFORMATION, FileName[0]) + fn->Length;
|
||||
|
||||
if (bytes_needed > *length)
|
||||
overflow = TRUE;
|
||||
|
||||
if (!overflow) {
|
||||
if (flefii) {
|
||||
flefii->NextEntryOffset = (ULONG)sector_align(offsetof(FILE_LINK_ENTRY_FULL_ID_INFORMATION, FileName[0]) + (flefii->FileNameLength * sizeof(WCHAR)), 8);
|
||||
flefii = (FILE_LINK_ENTRY_FULL_ID_INFORMATION*)((UINT8*)flefii + flefii->NextEntryOffset);
|
||||
} else
|
||||
flefii = &flfii->Entry;
|
||||
|
||||
flefii->NextEntryOffset = 0;
|
||||
|
||||
RtlCopyMemory(&flefii->ParentFileId.Identifier[0], &parfr->fcb->inode, sizeof(UINT64));
|
||||
RtlCopyMemory(&flefii->ParentFileId.Identifier[sizeof(UINT64)], &parfr->fcb->subvol->id, sizeof(UINT64));
|
||||
|
||||
flefii->FileNameLength = fn->Length / sizeof(WCHAR);
|
||||
RtlCopyMemory(flefii->FileName, fn->Buffer, fn->Length);
|
||||
|
||||
flfii->EntriesReturned++;
|
||||
|
||||
len = bytes_needed;
|
||||
}
|
||||
}
|
||||
|
||||
free_fileref(parfr);
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&fcb->Vcb->fileref_lock);
|
||||
}
|
||||
|
||||
flfii->BytesNeeded = bytes_needed;
|
||||
|
||||
*length -= len;
|
||||
|
||||
Status = overflow ? STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS;
|
||||
|
||||
ExReleaseResourceLite(fcb->Header.Resource);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
static NTSTATUS fill_in_file_id_information(FILE_ID_INFORMATION* fii, fcb* fcb, LONG* length) {
|
||||
RtlCopyMemory(&fii->VolumeSerialNumber, &fcb->Vcb->superblock.uuid.uuid[8], sizeof(UINT64));
|
||||
|
@ -3385,6 +3806,66 @@ static NTSTATUS fill_in_file_id_information(FILE_ID_INFORMATION* fii, fcb* fcb,
|
|||
#endif
|
||||
|
||||
#ifndef __REACTOS__
|
||||
static NTSTATUS fill_in_file_stat_information(FILE_STAT_INFORMATION* fsi, fcb* fcb, ccb* ccb, LONG* length) {
|
||||
INODE_ITEM* ii;
|
||||
|
||||
fsi->FileId.LowPart = (UINT32)fcb->inode;
|
||||
fsi->FileId.HighPart = (UINT32)fcb->subvol->id;
|
||||
|
||||
if (fcb->ads)
|
||||
ii = &ccb->fileref->parent->fcb->inode_item;
|
||||
else
|
||||
ii = &fcb->inode_item;
|
||||
|
||||
if (fcb == fcb->Vcb->dummy_fcb) {
|
||||
LARGE_INTEGER time;
|
||||
|
||||
KeQuerySystemTime(&time);
|
||||
fsi->CreationTime = fsi->LastAccessTime = fsi->LastWriteTime = fsi->ChangeTime = time;
|
||||
} else {
|
||||
fsi->CreationTime.QuadPart = unix_time_to_win(&ii->otime);
|
||||
fsi->LastAccessTime.QuadPart = unix_time_to_win(&ii->st_atime);
|
||||
fsi->LastWriteTime.QuadPart = unix_time_to_win(&ii->st_mtime);
|
||||
fsi->ChangeTime.QuadPart = unix_time_to_win(&ii->st_ctime);
|
||||
}
|
||||
|
||||
if (fcb->ads) {
|
||||
fsi->AllocationSize.QuadPart = fsi->EndOfFile.QuadPart = fcb->adsdata.Length;
|
||||
fsi->FileAttributes = ccb->fileref->parent->fcb->atts == 0 ? FILE_ATTRIBUTE_NORMAL : ccb->fileref->parent->fcb->atts;
|
||||
} else {
|
||||
fsi->AllocationSize.QuadPart = fcb_alloc_size(fcb);
|
||||
fsi->EndOfFile.QuadPart = S_ISDIR(fcb->inode_item.st_mode) ? 0 : fcb->inode_item.st_size;
|
||||
fsi->FileAttributes = fcb->atts == 0 ? FILE_ATTRIBUTE_NORMAL : fcb->atts;
|
||||
}
|
||||
|
||||
if (fcb->type == BTRFS_TYPE_SOCKET)
|
||||
fsi->ReparseTag = IO_REPARSE_TAG_LXSS_SOCKET;
|
||||
else if (fcb->type == BTRFS_TYPE_FIFO)
|
||||
fsi->ReparseTag = IO_REPARSE_TAG_LXSS_FIFO;
|
||||
else if (fcb->type == BTRFS_TYPE_CHARDEV)
|
||||
fsi->ReparseTag = IO_REPARSE_TAG_LXSS_CHARDEV;
|
||||
else if (fcb->type == BTRFS_TYPE_BLOCKDEV)
|
||||
fsi->ReparseTag = IO_REPARSE_TAG_LXSS_BLOCKDEV;
|
||||
else if (!(fsi->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
|
||||
fsi->ReparseTag = 0;
|
||||
else
|
||||
fsi->ReparseTag = get_reparse_tag_fcb(fcb);
|
||||
|
||||
if (fcb->type == BTRFS_TYPE_SOCKET || fcb->type == BTRFS_TYPE_FIFO || fcb->type == BTRFS_TYPE_CHARDEV || fcb->type == BTRFS_TYPE_BLOCKDEV)
|
||||
fsi->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
|
||||
|
||||
if (fcb->ads)
|
||||
fsi->NumberOfLinks = ccb->fileref->parent->fcb->inode_item.st_nlink;
|
||||
else
|
||||
fsi->NumberOfLinks = fcb->inode_item.st_nlink;
|
||||
|
||||
fsi->EffectiveAccess = ccb->access;
|
||||
|
||||
*length -= sizeof(FILE_STAT_INFORMATION);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS fill_in_file_stat_lx_information(FILE_STAT_LX_INFORMATION* fsli, fcb* fcb, ccb* ccb, LONG* length) {
|
||||
INODE_ITEM* ii;
|
||||
|
||||
|
@ -3439,7 +3920,11 @@ static NTSTATUS fill_in_file_stat_lx_information(FILE_STAT_LX_INFORMATION* fsli,
|
|||
fsli->NumberOfLinks = fcb->inode_item.st_nlink;
|
||||
|
||||
fsli->EffectiveAccess = ccb->access;
|
||||
fsli->LxFlags = LX_FILE_METADATA_HAS_UID | LX_FILE_METADATA_HAS_GID | LX_FILE_METADATA_HAS_MODE | LX_FILE_METADATA_HAS_DEVICE_ID; // FIXME - LX_FILE_CASE_SENSITIVE_DIR
|
||||
fsli->LxFlags = LX_FILE_METADATA_HAS_UID | LX_FILE_METADATA_HAS_GID | LX_FILE_METADATA_HAS_MODE | LX_FILE_METADATA_HAS_DEVICE_ID;
|
||||
|
||||
if (fcb->case_sensitive)
|
||||
fsli->LxFlags |= LX_FILE_CASE_SENSITIVE_DIR;
|
||||
|
||||
fsli->LxUid = ii->st_uid;
|
||||
fsli->LxGid = ii->st_gid;
|
||||
fsli->LxMode = ii->st_mode;
|
||||
|
@ -3456,6 +3941,14 @@ static NTSTATUS fill_in_file_stat_lx_information(FILE_STAT_LX_INFORMATION* fsli,
|
|||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS fill_in_file_case_sensitive_information(FILE_CASE_SENSITIVE_INFORMATION* fcsi, fcb* fcb, LONG* length) {
|
||||
fcsi->Flags = fcb->case_sensitive ? FILE_CS_FLAG_CASE_SENSITIVE_DIR : 0;
|
||||
|
||||
*length -= sizeof(FILE_CASE_SENSITIVE_INFORMATION);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static NTSTATUS query_info(device_extension* Vcb, PFILE_OBJECT FileObject, PIRP Irp) {
|
||||
|
@ -3746,6 +4239,23 @@ static NTSTATUS query_info(device_extension* Vcb, PFILE_OBJECT FileObject, PIRP
|
|||
break;
|
||||
}
|
||||
|
||||
case FileStatInformation:
|
||||
{
|
||||
FILE_STAT_INFORMATION* fsi = Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
if (IrpSp->Parameters.QueryFile.Length < sizeof(FILE_STAT_LX_INFORMATION)) {
|
||||
WARN("overflow\n");
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
TRACE("FileStatInformation\n");
|
||||
|
||||
Status = fill_in_file_stat_information(fsi, fcb, ccb, &length);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case FileStatLxInformation:
|
||||
{
|
||||
FILE_STAT_LX_INFORMATION* fsli = Irp->AssociatedIrp.SystemBuffer;
|
||||
|
@ -3762,6 +4272,36 @@ static NTSTATUS query_info(device_extension* Vcb, PFILE_OBJECT FileObject, PIRP
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
case FileCaseSensitiveInformation:
|
||||
{
|
||||
FILE_CASE_SENSITIVE_INFORMATION* fcsi = Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
if (IrpSp->Parameters.QueryFile.Length < sizeof(FILE_CASE_SENSITIVE_INFORMATION)) {
|
||||
WARN("overflow\n");
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
TRACE("FileCaseSensitiveInformation\n");
|
||||
|
||||
Status = fill_in_file_case_sensitive_information(fcsi, fcb, &length);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case FileHardLinkFullIdInformation:
|
||||
{
|
||||
FILE_LINKS_FULL_ID_INFORMATION* flfii = Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
TRACE("FileHardLinkFullIdInformation\n");
|
||||
|
||||
ExAcquireResourceSharedLite(&Vcb->tree_lock, TRUE);
|
||||
Status = fill_in_hard_link_full_id_information(flfii, fileref, Irp, &length);
|
||||
ExReleaseResourceLite(&Vcb->tree_lock);
|
||||
|
||||
break;
|
||||
}
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
|
|
@ -515,6 +515,9 @@ static NTSTATUS add_parents(device_extension* Vcb, PIRP Irp) {
|
|||
KEY searchkey;
|
||||
traverse_ptr tp;
|
||||
NTSTATUS Status;
|
||||
#ifdef __REACTOS__
|
||||
tree* t2;
|
||||
#endif
|
||||
|
||||
searchkey.obj_id = t->root->id;
|
||||
searchkey.obj_type = TYPE_ROOT_ITEM;
|
||||
|
@ -555,6 +558,17 @@ static NTSTATUS add_parents(device_extension* Vcb, PIRP Irp) {
|
|||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __REACTOS__
|
||||
tree* t2 = tp.tree;
|
||||
#else
|
||||
t2 = tp.tree;
|
||||
#endif
|
||||
while (t2) {
|
||||
t2->write = TRUE;
|
||||
|
||||
t2 = t2->parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2713,6 +2727,9 @@ static NTSTATUS update_chunk_usage(device_extension* Vcb, PIRP Irp, LIST_ENTRY*
|
|||
}
|
||||
|
||||
if (c->used != c->oldused) {
|
||||
#ifdef __REACTOS__
|
||||
UINT64 old_phys_used, phys_used;
|
||||
#endif
|
||||
searchkey.obj_id = c->offset;
|
||||
searchkey.obj_type = TYPE_BLOCK_GROUP_ITEM;
|
||||
searchkey.offset = c->chunk_item->size;
|
||||
|
@ -2767,11 +2784,18 @@ static NTSTATUS update_chunk_usage(device_extension* Vcb, PIRP Irp, LIST_ENTRY*
|
|||
goto end;
|
||||
}
|
||||
|
||||
TRACE("bytes_used = %llx\n", Vcb->superblock.bytes_used);
|
||||
#ifndef __REACTOS__
|
||||
UINT64 old_phys_used = chunk_estimate_phys_size(Vcb, c, c->oldused);
|
||||
UINT64 phys_used = chunk_estimate_phys_size(Vcb, c, c->used);
|
||||
#else
|
||||
old_phys_used = chunk_estimate_phys_size(Vcb, c, c->oldused);
|
||||
phys_used = chunk_estimate_phys_size(Vcb, c, c->used);
|
||||
#endif
|
||||
|
||||
Vcb->superblock.bytes_used += c->used - c->oldused;
|
||||
|
||||
TRACE("bytes_used = %llx\n", Vcb->superblock.bytes_used);
|
||||
if (Vcb->superblock.bytes_used + phys_used > old_phys_used)
|
||||
Vcb->superblock.bytes_used += phys_used - old_phys_used;
|
||||
else
|
||||
Vcb->superblock.bytes_used = 0;
|
||||
|
||||
c->oldused = c->used;
|
||||
}
|
||||
|
@ -4118,6 +4142,8 @@ static NTSTATUS create_chunk(device_extension* Vcb, chunk* c, PIRP Irp) {
|
|||
c->created = FALSE;
|
||||
c->oldused = c->used;
|
||||
|
||||
Vcb->superblock.bytes_used += chunk_estimate_phys_size(Vcb, c, c->used);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -4652,6 +4678,15 @@ NTSTATUS flush_fcb(fcb* fcb, BOOL cache, LIST_ENTRY* batchlist, PIRP Irp) {
|
|||
}
|
||||
}
|
||||
|
||||
if (fcb->marked_as_orphan) {
|
||||
Status = insert_tree_item_batch(batchlist, fcb->Vcb, fcb->subvol, BTRFS_ORPHAN_INODE_OBJID, TYPE_ORPHAN_INODE,
|
||||
fcb->inode, NULL, 0, Batch_Delete);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("insert_tree_item_batch returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
goto end;
|
||||
}
|
||||
|
@ -5146,6 +5181,37 @@ NTSTATUS flush_fcb(fcb* fcb, BOOL cache, LIST_ENTRY* batchlist, PIRP Irp) {
|
|||
fcb->xattrs_changed = FALSE;
|
||||
}
|
||||
|
||||
if ((fcb->case_sensitive_set && !fcb->case_sensitive)) {
|
||||
Status = delete_xattr(fcb->Vcb, batchlist, fcb->subvol, fcb->inode, EA_CASE_SENSITIVE,
|
||||
sizeof(EA_CASE_SENSITIVE) - 1, EA_CASE_SENSITIVE_HASH);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("delete_xattr returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
fcb->case_sensitive_set = FALSE;
|
||||
} else if ((!fcb->case_sensitive_set && fcb->case_sensitive)) {
|
||||
Status = set_xattr(fcb->Vcb, batchlist, fcb->subvol, fcb->inode, EA_CASE_SENSITIVE,
|
||||
sizeof(EA_CASE_SENSITIVE) - 1, EA_CASE_SENSITIVE_HASH, (UINT8*)"1", 1);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("set_xattr returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
fcb->case_sensitive_set = TRUE;
|
||||
}
|
||||
|
||||
if (fcb->inode_item.st_nlink == 0 && !fcb->marked_as_orphan) { // mark as orphan
|
||||
Status = insert_tree_item_batch(batchlist, fcb->Vcb, fcb->subvol, BTRFS_ORPHAN_INODE_OBJID, TYPE_ORPHAN_INODE,
|
||||
fcb->inode, NULL, 0, Batch_Insert);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("insert_tree_item_batch returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
fcb->marked_as_orphan = TRUE;
|
||||
}
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
end:
|
||||
|
@ -5197,6 +5263,9 @@ static NTSTATUS drop_chunk(device_extension* Vcb, chunk* c, LIST_ENTRY* batchlis
|
|||
KEY searchkey;
|
||||
traverse_ptr tp;
|
||||
UINT64 i, factor;
|
||||
#ifdef __REACTOS__
|
||||
UINT64 phys_used;
|
||||
#endif
|
||||
CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&c->chunk_item[1];;
|
||||
|
||||
TRACE("dropping chunk %llx\n", c->offset);
|
||||
|
@ -5441,7 +5510,16 @@ static NTSTATUS drop_chunk(device_extension* Vcb, chunk* c, LIST_ENTRY* batchlis
|
|||
Vcb->superblock.incompat_flags &= ~BTRFS_INCOMPAT_FLAGS_RAID56;
|
||||
}
|
||||
|
||||
Vcb->superblock.bytes_used -= c->oldused;
|
||||
#ifndef __REACTOS__
|
||||
UINT64 phys_used = chunk_estimate_phys_size(Vcb, c, c->oldused);
|
||||
#else
|
||||
phys_used = chunk_estimate_phys_size(Vcb, c, c->oldused);
|
||||
#endif
|
||||
|
||||
if (phys_used < Vcb->superblock.bytes_used)
|
||||
Vcb->superblock.bytes_used -= phys_used;
|
||||
else
|
||||
Vcb->superblock.bytes_used = 0;
|
||||
|
||||
ExFreePool(c->chunk_item);
|
||||
ExFreePool(c->devices);
|
||||
|
@ -6943,6 +7021,108 @@ static NTSTATUS test_not_full(device_extension* Vcb) {
|
|||
return STATUS_DISK_FULL;
|
||||
}
|
||||
|
||||
static NTSTATUS check_for_orphans_root(device_extension* Vcb, root* r, PIRP Irp) {
|
||||
NTSTATUS Status;
|
||||
KEY searchkey;
|
||||
traverse_ptr tp;
|
||||
LIST_ENTRY rollback;
|
||||
|
||||
TRACE("(%p, %p)\n", Vcb, r);
|
||||
|
||||
InitializeListHead(&rollback);
|
||||
|
||||
searchkey.obj_id = BTRFS_ORPHAN_INODE_OBJID;
|
||||
searchkey.obj_type = TYPE_ORPHAN_INODE;
|
||||
searchkey.offset = 0;
|
||||
|
||||
Status = find_item(Vcb, r, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
do {
|
||||
traverse_ptr next_tp;
|
||||
|
||||
if (tp.item->key.obj_id > searchkey.obj_id || (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type > searchkey.obj_type))
|
||||
break;
|
||||
|
||||
if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
|
||||
fcb* fcb;
|
||||
|
||||
TRACE("removing orphaned inode %llx\n", tp.item->key.offset);
|
||||
|
||||
Status = open_fcb(Vcb, r, tp.item->key.offset, 0, NULL, FALSE, NULL, &fcb, PagedPool, Irp);
|
||||
if (!NT_SUCCESS(Status))
|
||||
ERR("open_fcb returned %08x\n", Status);
|
||||
else {
|
||||
if (fcb->inode_item.st_nlink == 0) {
|
||||
if (fcb->type != BTRFS_TYPE_DIRECTORY && fcb->inode_item.st_size > 0) {
|
||||
Status = excise_extents(Vcb, fcb, 0, sector_align(fcb->inode_item.st_size, Vcb->superblock.sector_size), Irp, &rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("excise_extents returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
fcb->deleted = TRUE;
|
||||
|
||||
mark_fcb_dirty(fcb);
|
||||
}
|
||||
|
||||
free_fcb(fcb);
|
||||
|
||||
Status = delete_tree_item(Vcb, &tp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("delete_tree_item returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (find_next_item(Vcb, &tp, &next_tp, FALSE, Irp))
|
||||
tp = next_tp;
|
||||
else
|
||||
break;
|
||||
} while (TRUE);
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
clear_rollback(&rollback);
|
||||
|
||||
end:
|
||||
do_rollback(Vcb, &rollback);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
static NTSTATUS check_for_orphans(device_extension* Vcb, PIRP Irp) {
|
||||
NTSTATUS Status;
|
||||
LIST_ENTRY* le;
|
||||
|
||||
if (IsListEmpty(&Vcb->dirty_filerefs))
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
le = Vcb->dirty_filerefs.Flink;
|
||||
while (le != &Vcb->dirty_filerefs) {
|
||||
file_ref* fr = CONTAINING_RECORD(le, file_ref, list_entry_dirty);
|
||||
|
||||
if (!fr->fcb->subvol->checked_for_orphans) {
|
||||
Status = check_for_orphans_root(Vcb, fr->fcb->subvol, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("check_for_orphans_root returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
fr->fcb->subvol->checked_for_orphans = TRUE;
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS do_write2(device_extension* Vcb, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
NTSTATUS Status;
|
||||
LIST_ENTRY *le, batchlist;
|
||||
|
@ -6965,6 +7145,12 @@ static NTSTATUS do_write2(device_extension* Vcb, PIRP Irp, LIST_ENTRY* rollback)
|
|||
time1 = KeQueryPerformanceCounter(&freq);
|
||||
#endif
|
||||
|
||||
Status = check_for_orphans(Vcb, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("check_for_orphans returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
ExAcquireResourceExclusiveLite(&Vcb->dirty_filerefs_lock, TRUE);
|
||||
|
||||
while (!IsListEmpty(&Vcb->dirty_filerefs)) {
|
||||
|
|
|
@ -25,7 +25,7 @@ static NTSTATUS remove_free_space_inode(device_extension* Vcb, UINT64 inode, LIS
|
|||
NTSTATUS Status;
|
||||
fcb* fcb;
|
||||
|
||||
Status = open_fcb(Vcb, Vcb->root_root, inode, BTRFS_TYPE_FILE, NULL, NULL, &fcb, PagedPool, Irp);
|
||||
Status = open_fcb(Vcb, Vcb->root_root, inode, BTRFS_TYPE_FILE, NULL, FALSE, NULL, &fcb, PagedPool, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("open_fcb returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -497,7 +497,7 @@ NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c, BOOL load
|
|||
num_entries = fsi->num_entries;
|
||||
num_bitmaps = fsi->num_bitmaps;
|
||||
|
||||
Status = open_fcb(Vcb, Vcb->root_root, inode, BTRFS_TYPE_FILE, NULL, NULL, &c->cache, PagedPool, Irp);
|
||||
Status = open_fcb(Vcb, Vcb->root_root, inode, BTRFS_TYPE_FILE, NULL, FALSE, NULL, &c->cache, PagedPool, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("open_fcb returned %08x\n", Status);
|
||||
return STATUS_NOT_FOUND;
|
||||
|
|
|
@ -432,7 +432,7 @@ static NTSTATUS do_create_snapshot(device_extension* Vcb, PFILE_OBJECT parent, f
|
|||
goto end;
|
||||
}
|
||||
|
||||
Status = open_fcb(Vcb, r, r->root_item.objid, BTRFS_TYPE_DIRECTORY, utf8, fcb, &fr->fcb, PagedPool, Irp);
|
||||
Status = open_fcb(Vcb, r, r->root_item.objid, BTRFS_TYPE_DIRECTORY, utf8, FALSE, fcb, &fr->fcb, PagedPool, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("open_fcb returned %08x\n", Status);
|
||||
free_fileref(fr);
|
||||
|
@ -4342,6 +4342,14 @@ static NTSTATUS fsctl_set_xattr(device_extension* Vcb, PFILE_OBJECT FileObject,
|
|||
fcb->ea_changed = TRUE;
|
||||
mark_fcb_dirty(fcb);
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
goto end;
|
||||
} else if (bsxa->namelen == sizeof(EA_CASE_SENSITIVE) - 1 && RtlCompareMemory(bsxa->data, EA_CASE_SENSITIVE, sizeof(EA_CASE_SENSITIVE) - 1) == sizeof(EA_CASE_SENSITIVE) - 1) {
|
||||
if (bsxa->valuelen > 0 && bsxa->data[bsxa->namelen] == '1') {
|
||||
fcb->case_sensitive = TRUE;
|
||||
mark_fcb_dirty(fcb);
|
||||
}
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
goto end;
|
||||
} else if (bsxa->namelen == sizeof(EA_PROP_COMPRESSION) - 1 && RtlCompareMemory(bsxa->data, EA_PROP_COMPRESSION, sizeof(EA_PROP_COMPRESSION) - 1) == sizeof(EA_PROP_COMPRESSION) - 1) {
|
||||
|
|
|
@ -4498,7 +4498,7 @@ NTSTATUS write_file2(device_extension* Vcb, PIRP Irp, LARGE_INTEGER offset, void
|
|||
ExFreePool(data);
|
||||
} else {
|
||||
if (write_irp && Irp->MdlAddress && no_buf) {
|
||||
BOOL locked = Irp->MdlAddress->MdlFlags & MDL_PAGES_LOCKED;
|
||||
BOOL locked = Irp->MdlAddress->MdlFlags & (MDL_PAGES_LOCKED | MDL_PARTIAL);
|
||||
|
||||
if (!locked) {
|
||||
Status = STATUS_SUCCESS;
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
The following FSD are shared with: https://github.com/maharmstone/btrfs.
|
||||
|
||||
reactos/drivers/filesystems/btrfs # Synced to 1.2.1
|
||||
reactos/drivers/filesystems/btrfs # Synced to 1.3
|
||||
reactos/dll/shellext/shellbtrfs # Synced to 1.1
|
||||
reactos/sdk/lib/fslib/btrfslib # Synced to 1.2.1
|
||||
reactos/sdk/lib/fslib/btrfslib # Synced to 1.3
|
||||
|
||||
The following FSD are shared with: http://www.ext2fsd.com/
|
||||
|
||||
|
|
Loading…
Reference in a new issue