21#if (NTDDI_VERSION >= NTDDI_WIN10)
24#define FileIdInformation (enum _FILE_INFORMATION_CLASS)59
25#define FileHardLinkFullIdInformation (enum _FILE_INFORMATION_CLASS)62
26#define FileDispositionInformationEx (enum _FILE_INFORMATION_CLASS)64
27#define FileRenameInformationEx (enum _FILE_INFORMATION_CLASS)65
28#define FileStatInformation (enum _FILE_INFORMATION_CLASS)68
29#define FileStatLxInformation (enum _FILE_INFORMATION_CLASS)70
30#define FileCaseSensitiveInformation (enum _FILE_INFORMATION_CLASS)71
31#define FileLinkInformationEx (enum _FILE_INFORMATION_CLASS)72
32#define FileStorageReserveIdInformation (enum _FILE_INFORMATION_CLASS)74
73#define LX_FILE_METADATA_HAS_UID 0x01
74#define LX_FILE_METADATA_HAS_GID 0x02
75#define LX_FILE_METADATA_HAS_MODE 0x04
76#define LX_FILE_METADATA_HAS_DEVICE_ID 0x08
77#define LX_FILE_CASE_SENSITIVE_DIR 0x10
120#define FILE_RENAME_REPLACE_IF_EXISTS 0x001
121#define FILE_RENAME_POSIX_SEMANTICS 0x002
122#define FILE_RENAME_SUPPRESS_PIN_STATE_INHERITANCE 0x004
123#define FILE_RENAME_SUPPRESS_STORAGE_RESERVE_INHERITANCE 0x008
124#define FILE_RENAME_NO_INCREASE_AVAILABLE_SPACE 0x010
125#define FILE_RENAME_NO_DECREASE_AVAILABLE_SPACE 0x020
126#define FILE_RENAME_IGNORE_READONLY_ATTRIBUTE 0x040
127#define FILE_RENAME_FORCE_RESIZE_TARGET_SR 0x080
128#define FILE_RENAME_FORCE_RESIZE_SOURCE_SR 0x100
130#define FILE_DISPOSITION_DELETE 0x1
131#define FILE_DISPOSITION_POSIX_SEMANTICS 0x2
132#define FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK 0x4
133#define FILE_DISPOSITION_ON_CLOSE 0x8
135#define FILE_LINK_REPLACE_IF_EXISTS 0x001
136#define FILE_LINK_POSIX_SEMANTICS 0x002
137#define FILE_LINK_SUPPRESS_STORAGE_RESERVE_INHERITANCE 0x008
138#define FILE_LINK_NO_INCREASE_AVAILABLE_SPACE 0x010
139#define FILE_LINK_NO_DECREASE_AVAILABLE_SPACE 0x020
140#define FILE_LINK_IGNORE_READONLY_ATTRIBUTE 0x040
141#define FILE_LINK_FORCE_RESIZE_TARGET_SR 0x080
142#define FILE_LINK_FORCE_RESIZE_SOURCE_SR 0x100
146#define FILE_RENAME_INFORMATION_EX FILE_RENAME_INFORMATION
147#define FILE_LINK_INFORMATION_EX FILE_LINK_INFORMATION
177#define FILE_RENAME_REPLACE_IF_EXISTS 0x001
178#define FILE_RENAME_POSIX_SEMANTICS 0x002
179#define FILE_RENAME_IGNORE_READONLY_ATTRIBUTE 0x040
181#define FILE_DISPOSITION_DELETE 0x1
182#define FILE_DISPOSITION_POSIX_SEMANTICS 0x2
183#define FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK 0x4
185#define FILE_LINK_REPLACE_IF_EXISTS 0x001
186#define FILE_LINK_POSIX_SEMANTICS 0x002
187#define FILE_LINK_IGNORE_READONLY_ATTRIBUTE 0x040
196 bool inode_item_changed =
false;
200 if (fileref && fileref->
parent)
203 ERR(
"stream did not have fileref\n");
209 ERR(
"ccb was NULL\n");
218 WARN(
"attempted to set FILE_ATTRIBUTE_DIRECTORY on non-directory\n");
254 inode_item_changed =
true;
264 inode_item_changed =
true;
274 inode_item_changed =
true;
284 inode_item_changed =
true;
323 fcb->
subvol->root_item.ctransid =
Vcb->superblock.generation;
330 fcb->
subvol->root_item.flags &= ~BTRFS_SUBVOL_READONLY;
333 inode_item_changed =
true;
338 if (inode_item_changed) {
385 ERR(
"no fileref for stream\n");
395 TRACE(
"not allowing readonly file to be deleted\n");
401 WARN(
"not allowing \\$Root to be deleted\n");
408 TRACE(
"directory not empty\n");
415 TRACE(
"trying to delete file which is being mapped as an image\n");
451 if (
c->open_count > 0)
472 ERR(
"out of memory\n");
496 ERR(
"out of memory\n");
510 ERR(
"out of memory\n");
527 ERR(
"out of memory\n");
538 while (le != &oldfcb->
extents) {
545 ERR(
"out of memory\n");
553 if (
ext2->datalen > 0)
556 ext2->unique =
false;
557 ext2->ignore =
false;
558 ext2->inserted =
true;
573 ERR(
"out of memory\n");
595 ERR(
"out of memory\n");
601 hl2->index = hl->
index;
603 hl2->name.Length = hl2->name.MaximumLength = hl->
name.
Length;
606 if (!hl2->name.Buffer) {
607 ERR(
"out of memory\n");
615 hl2->utf8.Length = hl2->utf8.MaximumLength = hl->
utf8.
Length;
618 if (!hl2->utf8.Buffer) {
619 ERR(
"out of memory\n");
638 ERR(
"out of memory\n");
651 ERR(
"out of memory\n");
662 while (le != &oldfcb->
xattrs) {
671 ERR(
"out of memory\n");
717 ERR(
"open_fileref_child returned %08lx\n",
Status);
724 ERR(
"out of memory\n");
755 if (dc2->
hash >> 24 ==
c)
764 c =
dc->hash_uc >> 24;
793 ERR(
"out of memory\n");
822 ERR(
"SeAssignSecurity returned %08lx\n",
Status);
828 ERR(
"SeAssignSecurity returned NULL security descriptor\n");
834 ERR(
"RtlGetOwnerSecurityDescriptor returned %08lx\n",
Status);
849 fcb->
Header.ValidDataLength.QuadPart = 0;
861 ERR(
"out of memory\n");
869 ERR(
"out of memory\n");
875 acquire_fcb_lock_exclusive(
Vcb);
879 release_fcb_lock(
Vcb);
965 acquire_fcb_lock_exclusive(
fileref->fcb->Vcb);
970 ERR(
"out of memory\n");
995 ERR(
"add_children_to_move_list returned %08lx\n",
Status);
1022 ERR(
"duplicate_fcb returned %08lx\n",
Status);
1092 ERR(
"get_chunk_from_address(%I64x) failed\n", ed2->
address);
1098 ERR(
"update_changed_extent_ref returned %08lx\n",
Status);
1168 fileref->fcb->subvol->root_item.ctransid =
fileref->fcb->Vcb->superblock.generation;
1176 bool name_changed =
false;
1182 ERR(
"out of memory\n");
1192 ERR(
"create_directory_fcb returned %08lx\n",
Status);
1213 name_changed =
true;
1218 ERR(
"out of memory\n");
1271 ERR(
"out of memory\n");
1281 ERR(
"out of memory\n");
1291 ERR(
"RtlUpcaseUnicodeString returned %08lx\n",
Status);
1326 TRACE(
"me->fileref->parent->fcb->inode_item.st_size (inode %I64x) was %I64x\n", me->
fileref->
parent->fcb->inode, me->
fileref->
parent->fcb->inode_item.st_size);
1328 TRACE(
"me->fileref->parent->fcb->inode_item.st_size (inode %I64x) now %I64x\n", me->
fileref->
parent->fcb->inode, me->
fileref->
parent->fcb->inode_item.st_size);
1372 ERR(
"delete_fileref returned %08lx\n",
Status);
1380 ERR(
"out of memory\n");
1391 ERR(
"out of memory\n");
1402 ERR(
"out of memory\n");
1428 ERR(
"delete_fileref returned %08lx\n",
Status);
1436 destdir->
fcb->
subvol->root_item.ctransid = destdir->
fcb->
Vcb->superblock.generation;
1463 fileref->fcb->subvol->fcbs_version++;
1465 release_fcb_lock(
fileref->fcb->Vcb);
1495 if (dc2->
hash >
dc->hash) {
1512 if (dc2->
hash >
dc->hash)
1516 c =
dc->hash_uc >> 24;
1570 WARN(
"trying to rename stream on readonly file\n");
1575 WARN(
"insufficient permissions\n");
1587 WARN(
"trying to overwrite open file\n");
1592 WARN(
"can only overwrite existing stream if it is zero-length\n");
1598 ERR(
"out of memory\n");
1630 fileref->fcb->inode_item_changed =
true;
1663 fileref->fcb->extents_changed =
true;
1671 if (
fileref->fcb->adsxattr.Buffer) {
1673 fileref->fcb->adsxattr.Length =
fileref->fcb->adsxattr.MaximumLength = 0;
1680 fileref->fcb->adsdata.Length =
fileref->fcb->adsdata.MaximumLength = 0;
1682 acquire_fcb_lock_exclusive(
Vcb);
1692 release_fcb_lock(
Vcb);
1755 ERR(
"out of memory\n");
1774 ERR(
"add_extent_to_fcb returned %08lx\n",
Status);
1784 ERR(
"out of memory\n");
1802 ERR(
"do_write_file returned %08lx\n",
Status);
1812 fileref->fcb->inode_item_changed =
true;
1817 if (
dc->utf8.Buffer)
1820 if (
dc->name.Buffer)
1823 if (
dc->name_uc.Buffer)
1838 dummyfcb->
ads =
true;
1841 acquire_fcb_lock_exclusive(
Vcb);
1844 dummyfcb->
subvol->fcbs_version++;
1845 release_fcb_lock(
Vcb);
1869 static const WCHAR datasuf[] =
L":$DATA";
1870 static const char xapref[] =
"user.";
1873 ERR(
"fileref not set\n");
1878 ERR(
"fileref->parent not set\n");
1883 WARN(
"filename too short\n");
1888 WARN(
"destination filename must begin with a colon\n");
1893 WARN(
"insufficient permissions\n");
1901 if (
fn.Length >=
sizeof(datasuf) -
sizeof(
WCHAR) &&
1903 fn.Length -=
sizeof(datasuf) -
sizeof(
WCHAR);
1910 WARN(
"invalid stream name %.*S\n", (
int)(
fn.Length /
sizeof(
WCHAR)),
fn.Buffer);
1915 WARN(
"trying to rename stream on readonly file\n");
1934 WARN(
"trying to overwrite open file\n");
1940 WARN(
"can only overwrite existing stream if it is zero-length\n");
1947 ERR(
"delete_fileref returned %08lx\n",
Status);
1952 ERR(
"open_fileref_child returned %08lx\n",
Status);
1964 ERR(
"out of memory\n");
1978 ERR(
"out of memory\n");
2002 ERR(
"out of memory\n");
2015 WARN(
"cannot rename as data too long\n");
2026 WARN(
"cannot rename as data too long\n");
2036 ERR(
"RtlUpcaseUnicodeString returned %08lx\n",
Status);
2047 ERR(
"out of memory\n");
2062 dummyfcb->
ads =
true;
2065 acquire_fcb_lock_exclusive(
Vcb);
2068 dummyfcb->
subvol->fcbs_version++;
2069 release_fcb_lock(
Vcb);
2079 fileref->dc->name_uc = utf16uc;
2085 fileref->fcb->adsmaxlen = newmaxlen;
2116 static const WCHAR datasuf[] =
L":$DATA";
2117 static const char xapref[] =
"user.";
2120 ERR(
"fileref not set\n");
2125 WARN(
"filename too short\n");
2130 WARN(
"destination filename must begin with a colon\n");
2135 WARN(
"insufficient permissions\n");
2146 if (
fn.Length >=
sizeof(datasuf) -
sizeof(
WCHAR) &&
2148 fn.Length -=
sizeof(datasuf) -
sizeof(
WCHAR);
2150 if (
fn.Length == 0) {
2151 WARN(
"not allowing overwriting file with itself\n");
2157 WARN(
"invalid stream name %.*S\n", (
int)(
fn.Length /
sizeof(
WCHAR)),
fn.Buffer);
2162 WARN(
"trying to rename stream on readonly file\n");
2181 WARN(
"trying to overwrite open file\n");
2187 WARN(
"can only overwrite existing stream if it is zero-length\n");
2194 ERR(
"delete_fileref returned %08lx\n",
Status);
2199 ERR(
"open_fileref_child returned %08lx\n",
Status);
2211 ERR(
"out of memory\n");
2225 ERR(
"out of memory\n");
2249 ERR(
"out of memory\n");
2262 WARN(
"cannot rename as data too long\n");
2273 WARN(
"cannot rename as data too long\n");
2283 ERR(
"RtlUpcaseUnicodeString returned %08lx\n",
Status);
2292 if (
fileref->fcb->inode_item.st_size > 0) {
2299 ERR(
"out of memory\n");
2310 ERR(
"out of memory\n");
2321 ERR(
"short read\n");
2335 ERR(
"out of memory\n");
2352 ERR(
"duplicate_fcb returned %08lx\n",
Status);
2367 if (!dummyfileref) {
2368 ERR(
"out of memory\n");
2385 dummyfileref->
fcb = dummyfcb;
2392 if (
fileref->fcb->inode_item.st_size > 0) {
2396 ERR(
"excise_extents returned %08lx\n",
Status);
2411 dummyfcb->
Header.AllocationSize.QuadPart = 0;
2412 dummyfcb->
Header.FileSize.QuadPart = 0;
2413 dummyfcb->
Header.ValidDataLength.QuadPart = 0;
2420 le =
fileref->fcb->extents.Flink;
2421 while (le != &
fileref->fcb->extents) {
2445 if (
fileref->fcb->subvol->fcbs_ptrs[dummyfcb->
hash >> 24] == &
fileref->fcb->list_entry)
2468 fr->
parent = dummyfileref;
2480 dummyfileref->
dc->
fileref = dummyfileref;
2499 dc->name_uc = utf16uc;
2505 fileref->parent = dummyfileref;
2511 fileref->fcb->adsmaxlen = newmaxlen;
2533 ULONG fnlen, utf8len, origutf8len;
2552 TRACE(
"tfo = %p\n", tfo);
2562 ERR(
"no fileref set and no directory given\n");
2568 while (fnlen > 0 && (fri->
FileName[fnlen - 1] ==
'/' || fri->
FileName[fnlen - 1] ==
'\\')) {
2575 for (
i = fnlen - 1;
i >= 0;
i--) {
2589 WARN(
"not allowing \\$Root to be renamed\n");
2608 }
else if (fnlen >= 1 &&
fn[0] ==
':') {
2633 origutf8len =
fileref->dc->utf8.Length;
2642 ERR(
"out of memory\n");
2651 if (tfo && tfo->FsContext2) {
2652 struct _ccb* relatedccb = tfo->FsContext2;
2654 related = relatedccb->
fileref;
2664 TRACE(
"destination file already exists\n");
2670 }
else if (
fileref == oldfileref) {
2674 WARN(
"trying to overwrite open file\n");
2678 WARN(
"trying to overwrite readonly file\n");
2682 WARN(
"trying to overwrite directory\n");
2698 ERR(
"open_fileref returned %08lx\n",
Status);
2703 if (related->fcb ==
Vcb->dummy_fcb) {
2713 TRACE(
"SeAccessCheck failed, returning %08lx\n",
Status);
2720 WARN(
"trying to rename file with open children\n");
2731 TRACE(
"SeAccessCheck failed, returning %08lx\n",
Status);
2738 oldfileref->delete_on_close =
true;
2739 oldfileref->posix_delete =
true;
2744 ERR(
"delete_fileref returned %08lx\n",
Status);
2752 ERR(
"move_across_subvols returned %08lx\n",
Status);
2760 ULONG reqlen, oldutf8len;
2766 ERR(
"fileref_get_filename returned %08lx\n",
Status);
2772 ERR(
"out of memory\n");
2781 ERR(
"fileref_get_filename returned %08lx\n",
Status);
2791 ERR(
"out of memory\n");
2813 ERR(
"out of memory\n");
2825 ERR(
"out of memory\n");
2837 ERR(
"RtlUpcaseUnicodeString returned %08lx\n",
Status);
2857 ERR(
"fileref_get_filename returned %08lx\n",
Status);
2864 ERR(
"out of memory\n");
2874 ERR(
"fileref_get_filename returned %08lx\n",
Status);
2896 related->fcb->inode_item.transid =
Vcb->superblock.generation;
2897 TRACE(
"related->fcb->inode_item.st_size (inode %I64x) was %I64x\n", related->fcb->inode, related->fcb->inode_item.st_size);
2898 related->fcb->inode_item.st_size = related->fcb->inode_item.st_size + (2 *
utf8.Length) - (2* oldutf8len);
2899 TRACE(
"related->fcb->inode_item.st_size (inode %I64x) now %I64x\n", related->fcb->inode, related->fcb->inode_item.st_size);
2900 related->fcb->inode_item.sequence++;
2901 related->fcb->inode_item.st_ctime =
now;
2902 related->fcb->inode_item.st_mtime =
now;
2904 related->fcb->inode_item_changed =
true;
2933 fr2->deleted =
true;
2938 if (!fr2->oldutf8.Buffer) {
2940 if (!fr2->oldutf8.Buffer) {
2941 ERR(
"out of memory\n");
2952 fr2->fcb->fileref = fr2;
2987 ERR(
"out of memory\n");
2997 ERR(
"out of memory\n");
3007 ERR(
"RtlUpcaseUnicodeString returned %08lx\n",
Status);
3018 if (
IsListEmpty(&related->fcb->dir_children_index))
3040 ERR(
"out of memory\n");
3045 hl->
parent = related->fcb->inode;
3052 ERR(
"out of memory\n");
3064 ERR(
"out of memory\n");
3082 if (hl->
parent == fr2->parent->fcb->inode && hl->
index == fr2->oldindex) {
3116 related->fcb->inode_item.transid =
Vcb->superblock.generation;
3117 TRACE(
"related->fcb->inode_item.st_size (inode %I64x) was %I64x\n", related->fcb->inode, related->fcb->inode_item.st_size);
3118 related->fcb->inode_item.st_size += 2 * utf8len;
3119 TRACE(
"related->fcb->inode_item.st_size (inode %I64x) now %I64x\n", related->fcb->inode, related->fcb->inode_item.st_size);
3120 related->fcb->inode_item.sequence++;
3121 related->fcb->inode_item.st_ctime =
now;
3122 related->fcb->inode_item.st_mtime =
now;
3124 related->fcb->inode_item_changed =
true;
3129 fr2->parent->fcb->inode_item.transid =
Vcb->superblock.generation;
3130 TRACE(
"fr2->parent->fcb->inode_item.st_size (inode %I64x) was %I64x\n", fr2->parent->fcb->inode, fr2->parent->fcb->inode_item.st_size);
3131 fr2->parent->fcb->inode_item.st_size -= 2 * origutf8len;
3132 TRACE(
"fr2->parent->fcb->inode_item.st_size (inode %I64x) now %I64x\n", fr2->parent->fcb->inode, fr2->parent->fcb->inode_item.st_size);
3133 fr2->parent->fcb->inode_item.sequence++;
3134 fr2->parent->fcb->inode_item.st_ctime =
now;
3135 fr2->parent->fcb->inode_item.st_mtime =
now;
3139 fr2->parent->fcb->inode_item_changed =
true;
3177 ERR(
"no fileref for stream\n");
3181 if (end < fcb->adsdata.Length) {
3185 TRACE(
"truncating stream to %x bytes\n",
end);
3189 TRACE(
"extending stream to %x bytes\n",
end);