ReactOS 0.4.15-dev-7788-g1ad9096
fileinfo.c
Go to the documentation of this file.
1/* Copyright (c) Mark Harmstone 2016-17
2 *
3 * This file is part of WinBtrfs.
4 *
5 * WinBtrfs is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public Licence as published by
7 * the Free Software Foundation, either version 3 of the Licence, or
8 * (at your option) any later version.
9 *
10 * WinBtrfs is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public Licence for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public Licence
16 * along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
17
18#include "btrfs_drv.h"
19#include "crc32c.h"
20
21#if (NTDDI_VERSION >= NTDDI_WIN10)
22// not currently in mingw - introduced with Windows 10
23#ifndef _MSC_VER
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
33
34typedef struct _FILE_ID_INFORMATION {
38
39typedef struct _FILE_STAT_INFORMATION {
52
72
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
78
80 union {
83 };
88
92
94 union {
97 };
102
106
113
119
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
129
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
134
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
143
144#else
145
146#define FILE_RENAME_INFORMATION_EX FILE_RENAME_INFORMATION
147#define FILE_LINK_INFORMATION_EX FILE_LINK_INFORMATION
148
149#endif
150#endif
151
152#ifdef __REACTOS__
153typedef struct _FILE_RENAME_INFORMATION_EX {
154 union {
156 ULONG Flags;
157 };
160 WCHAR FileName[1];
162
164 ULONG Flags;
166
167typedef struct _FILE_LINK_INFORMATION_EX {
168 union {
170 ULONG Flags;
171 };
174 WCHAR FileName[1];
176
177#define FILE_RENAME_REPLACE_IF_EXISTS 0x001
178#define FILE_RENAME_POSIX_SEMANTICS 0x002
179#define FILE_RENAME_IGNORE_READONLY_ATTRIBUTE 0x040
180
181#define FILE_DISPOSITION_DELETE 0x1
182#define FILE_DISPOSITION_POSIX_SEMANTICS 0x2
183#define FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK 0x4
184
185#define FILE_LINK_REPLACE_IF_EXISTS 0x001
186#define FILE_LINK_POSIX_SEMANTICS 0x002
187#define FILE_LINK_IGNORE_READONLY_ATTRIBUTE 0x040
188#endif
189
191 FILE_BASIC_INFORMATION* fbi = Irp->AssociatedIrp.SystemBuffer;
192 fcb* fcb = FileObject->FsContext;
193 ccb* ccb = FileObject->FsContext2;
194 file_ref* fileref = ccb ? ccb->fileref : NULL;
195 ULONG defda, filter = 0;
196 bool inode_item_changed = false;
198
199 if (fcb->ads) {
200 if (fileref && fileref->parent)
201 fcb = fileref->parent->fcb;
202 else {
203 ERR("stream did not have fileref\n");
205 }
206 }
207
208 if (!ccb) {
209 ERR("ccb was NULL\n");
211 }
212
213 TRACE("file = %p, attributes = %lx\n", FileObject, fbi->FileAttributes);
214
216
218 WARN("attempted to set FILE_ATTRIBUTE_DIRECTORY on non-directory\n");
220 goto end;
221 }
222
226 goto end;
227 }
228
229 // don't allow readonly subvol to be made r/w if send operation running on it
230 if (fcb->inode == SUBVOL_ROOT_INODE && fcb->subvol->root_item.flags & BTRFS_SUBVOL_READONLY &&
231 fcb->subvol->send_ops > 0) {
233 goto end;
234 }
235
236 // times of -2 are some sort of undocumented behaviour to do with LXSS
237
238 if (fbi->CreationTime.QuadPart == -2)
239 fbi->CreationTime.QuadPart = 0;
240
241 if (fbi->LastAccessTime.QuadPart == -2)
242 fbi->LastAccessTime.QuadPart = 0;
243
244 if (fbi->LastWriteTime.QuadPart == -2)
245 fbi->LastWriteTime.QuadPart = 0;
246
247 if (fbi->ChangeTime.QuadPart == -2)
248 fbi->ChangeTime.QuadPart = 0;
249
250 if (fbi->CreationTime.QuadPart == -1)
252 else if (fbi->CreationTime.QuadPart != 0) {
254 inode_item_changed = true;
256
258 }
259
260 if (fbi->LastAccessTime.QuadPart == -1)
262 else if (fbi->LastAccessTime.QuadPart != 0) {
264 inode_item_changed = true;
266
268 }
269
270 if (fbi->LastWriteTime.QuadPart == -1)
271 ccb->user_set_write_time = true;
272 else if (fbi->LastWriteTime.QuadPart != 0) {
274 inode_item_changed = true;
276
277 ccb->user_set_write_time = true;
278 }
279
280 if (fbi->ChangeTime.QuadPart == -1)
282 else if (fbi->ChangeTime.QuadPart != 0) {
284 inode_item_changed = true;
285 // no filter for this
286
288 }
289
290 // FileAttributes == 0 means don't set - undocumented, but seen in fastfat
291 if (fbi->FileAttributes != 0) {
294
295 fbi->FileAttributes &= ~FILE_ATTRIBUTE_NORMAL;
296
297 defda = get_file_attributes(Vcb, fcb->subvol, fcb->inode, fcb->type, fileref && fileref->dc && fileref->dc->name.Length >= sizeof(WCHAR) && fileref->dc->name.Buffer[0] == '.',
298 true, Irp);
299
302 else if (fcb->type == BTRFS_TYPE_SYMLINK)
304
305 fcb->atts_changed = true;
306
309
310 if (defda == fbi->FileAttributes)
311 fcb->atts_deleted = true;
313 fcb->atts_deleted = true;
314
315 fcb->atts = fbi->FileAttributes;
316
319
322
323 fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
324 fcb->subvol->root_item.ctime = now;
325
326 if (fcb->inode == SUBVOL_ROOT_INODE) {
328 fcb->subvol->root_item.flags |= BTRFS_SUBVOL_READONLY;
329 else
330 fcb->subvol->root_item.flags &= ~BTRFS_SUBVOL_READONLY;
331 }
332
333 inode_item_changed = true;
334
336 }
337
338 if (inode_item_changed) {
339 fcb->inode_item.transid = Vcb->superblock.generation;
341 fcb->inode_item_changed = true;
342
344 }
345
346 if (filter != 0)
348
350
351end:
353
354 return Status;
355}
356
358 fcb* fcb = FileObject->FsContext;
359 ccb* ccb = FileObject->FsContext2;
360 file_ref* fileref = ccb ? ccb->fileref : NULL;
363
364 if (!fileref)
366
367 if (ex) {
368 FILE_DISPOSITION_INFORMATION_EX* fdi = Irp->AssociatedIrp.SystemBuffer;
369
370 flags = fdi->Flags;
371 } else {
372 FILE_DISPOSITION_INFORMATION* fdi = Irp->AssociatedIrp.SystemBuffer;
373
375 }
376
378
379 TRACE("changing delete_on_close to %s for fcb %p\n", flags & FILE_DISPOSITION_DELETE ? "true" : "false", fcb);
380
381 if (fcb->ads) {
382 if (fileref->parent)
383 atts = fileref->parent->fcb->atts;
384 else {
385 ERR("no fileref for stream\n");
387 goto end;
388 }
389 } else
390 atts = fcb->atts;
391
392 TRACE("atts = %lx\n", atts);
393
395 TRACE("not allowing readonly file to be deleted\n");
397 goto end;
398 }
399
401 WARN("not allowing \\$Root to be deleted\n");
403 goto end;
404 }
405
406 // FIXME - can we skip this bit for subvols?
407 if (fcb->type == BTRFS_TYPE_DIRECTORY && fcb->inode_item.st_size > 0 && (!fileref || fileref->fcb != Vcb->dummy_fcb)) {
408 TRACE("directory not empty\n");
410 goto end;
411 }
412
413 if (!MmFlushImageSection(&fcb->nonpaged->segment_object, MmFlushForDelete)) {
415 TRACE("trying to delete file which is being mapped as an image\n");
417 goto end;
418 }
419 }
420
422
423 FileObject->DeletePending = flags & FILE_DISPOSITION_DELETE;
424
426 ccb->fileref->posix_delete = true;
427
429
430end:
432
433 // send notification that directory is about to be deleted
435 FsRtlNotifyFullChangeDirectory(Vcb->NotifySync, &Vcb->DirNotifyList, FileObject->FsContext,
436 NULL, false, false, 0, NULL, NULL, NULL);
437 }
438
439 return Status;
440}
441
443 LIST_ENTRY* le = fileref->children.Flink;
444
445 if (IsListEmpty(&fileref->children))
446 return false;
447
448 while (le != &fileref->children) {
450
451 if (c->open_count > 0)
452 return true;
453
454 if (has_open_children(c))
455 return true;
456
457 le = le->Flink;
458 }
459
460 return false;
461}
462
463static NTSTATUS duplicate_fcb(fcb* oldfcb, fcb** pfcb) {
464 device_extension* Vcb = oldfcb->Vcb;
465 fcb* fcb;
466 LIST_ENTRY* le;
467
468 // FIXME - we can skip a lot of this if the inode is about to be deleted
469
470 fcb = create_fcb(Vcb, PagedPool); // FIXME - what if we duplicate the paging file?
471 if (!fcb) {
472 ERR("out of memory\n");
474 }
475
476 fcb->Vcb = Vcb;
477
478 fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
479 fcb->Header.AllocationSize = oldfcb->Header.AllocationSize;
480 fcb->Header.FileSize = oldfcb->Header.FileSize;
481 fcb->Header.ValidDataLength = oldfcb->Header.ValidDataLength;
482
483 fcb->type = oldfcb->type;
484
485 if (oldfcb->ads) {
486 fcb->ads = true;
487 fcb->adshash = oldfcb->adshash;
488 fcb->adsmaxlen = oldfcb->adsmaxlen;
489
490 if (oldfcb->adsxattr.Buffer && oldfcb->adsxattr.Length > 0) {
491 fcb->adsxattr.Length = oldfcb->adsxattr.Length;
494
495 if (!fcb->adsxattr.Buffer) {
496 ERR("out of memory\n");
497 free_fcb(fcb);
499 }
500
503 }
504
505 if (oldfcb->adsdata.Buffer && oldfcb->adsdata.Length > 0) {
508
509 if (!fcb->adsdata.Buffer) {
510 ERR("out of memory\n");
511 free_fcb(fcb);
513 }
514
516 }
517
518 goto end;
519 }
520
521 RtlCopyMemory(&fcb->inode_item, &oldfcb->inode_item, sizeof(INODE_ITEM));
522 fcb->inode_item_changed = true;
523
524 if (oldfcb->sd && RtlLengthSecurityDescriptor(oldfcb->sd) > 0) {
526 if (!fcb->sd) {
527 ERR("out of memory\n");
528 free_fcb(fcb);
530 }
531
533 }
534
535 fcb->atts = oldfcb->atts;
536
537 le = oldfcb->extents.Flink;
538 while (le != &oldfcb->extents) {
540
541 if (!ext->ignore) {
542 extent* ext2 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
543
544 if (!ext2) {
545 ERR("out of memory\n");
546 free_fcb(fcb);
548 }
549
550 ext2->offset = ext->offset;
551 ext2->datalen = ext->datalen;
552
553 if (ext2->datalen > 0)
554 RtlCopyMemory(&ext2->extent_data, &ext->extent_data, ext2->datalen);
555
556 ext2->unique = false;
557 ext2->ignore = false;
558 ext2->inserted = true;
559
560 if (ext->csum) {
561 ULONG len;
562 EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ext->extent_data.data;
563
564 if (ext->extent_data.compression == BTRFS_COMPRESSION_NONE)
565 len = (ULONG)ed2->num_bytes;
566 else
567 len = (ULONG)ed2->size;
568
569 len = (len * sizeof(uint32_t)) >> Vcb->sector_shift;
570
572 if (!ext2->csum) {
573 ERR("out of memory\n");
574 free_fcb(fcb);
576 }
577
578 RtlCopyMemory(ext2->csum, ext->csum, len);
579 } else
580 ext2->csum = NULL;
581
582 InsertTailList(&fcb->extents, &ext2->list_entry);
583 }
584
585 le = le->Flink;
586 }
587
588 le = oldfcb->hardlinks.Flink;
589 while (le != &oldfcb->hardlinks) {
591
593
594 if (!hl2) {
595 ERR("out of memory\n");
596 free_fcb(fcb);
598 }
599
600 hl2->parent = hl->parent;
601 hl2->index = hl->index;
602
603 hl2->name.Length = hl2->name.MaximumLength = hl->name.Length;
604 hl2->name.Buffer = ExAllocatePoolWithTag(PagedPool, hl2->name.MaximumLength, ALLOC_TAG);
605
606 if (!hl2->name.Buffer) {
607 ERR("out of memory\n");
608 ExFreePool(hl2);
609 free_fcb(fcb);
611 }
612
613 RtlCopyMemory(hl2->name.Buffer, hl->name.Buffer, hl->name.Length);
614
615 hl2->utf8.Length = hl2->utf8.MaximumLength = hl->utf8.Length;
616 hl2->utf8.Buffer = ExAllocatePoolWithTag(PagedPool, hl2->utf8.MaximumLength, ALLOC_TAG);
617
618 if (!hl2->utf8.Buffer) {
619 ERR("out of memory\n");
620 ExFreePool(hl2->name.Buffer);
621 ExFreePool(hl2);
622 free_fcb(fcb);
624 }
625
626 RtlCopyMemory(hl2->utf8.Buffer, hl->utf8.Buffer, hl->utf8.Length);
627
628 InsertTailList(&fcb->hardlinks, &hl2->list_entry);
629
630 le = le->Flink;
631 }
632
633 if (oldfcb->reparse_xattr.Buffer && oldfcb->reparse_xattr.Length > 0) {
635
637 if (!fcb->reparse_xattr.Buffer) {
638 ERR("out of memory\n");
639 free_fcb(fcb);
641 }
642
644 }
645
646 if (oldfcb->ea_xattr.Buffer && oldfcb->ea_xattr.Length > 0) {
648
650 if (!fcb->ea_xattr.Buffer) {
651 ERR("out of memory\n");
652 free_fcb(fcb);
654 }
655
657 }
658
660
661 le = oldfcb->xattrs.Flink;
662 while (le != &oldfcb->xattrs) {
664
665 if (xa->valuelen > 0) {
666 xattr* xa2;
667
669
670 if (!xa2) {
671 ERR("out of memory\n");
672 free_fcb(fcb);
674 }
675
676 xa2->namelen = xa->namelen;
677 xa2->valuelen = xa->valuelen;
678 xa2->dirty = xa->dirty;
679 memcpy(xa2->data, xa->data, xa->namelen + xa->valuelen);
680
682 }
683
684 le = le->Flink;
685 }
686
687end:
688 *pfcb = fcb;
689
690 return STATUS_SUCCESS;
691}
692
693typedef struct _move_entry {
700
703 LIST_ENTRY* le;
704
705 ExAcquireResourceSharedLite(&me->fileref->fcb->nonpaged->dir_children_lock, true);
706
708
709 while (le != &me->fileref->fcb->dir_children_index) {
710 dir_child* dc = CONTAINING_RECORD(le, dir_child, list_entry_index);
711 file_ref* fr;
712 move_entry* me2;
713
714 Status = open_fileref_child(Vcb, me->fileref, &dc->name, true, true, dc->index == 0 ? true : false, PagedPool, &fr, Irp);
715
716 if (!NT_SUCCESS(Status)) {
717 ERR("open_fileref_child returned %08lx\n", Status);
718 ExReleaseResourceLite(&me->fileref->fcb->nonpaged->dir_children_lock);
719 return Status;
720 }
721
723 if (!me2) {
724 ERR("out of memory\n");
725 ExReleaseResourceLite(&me->fileref->fcb->nonpaged->dir_children_lock);
727 }
728
729 me2->fileref = fr;
730 me2->dummyfcb = NULL;
731 me2->dummyfileref = NULL;
732 me2->parent = me;
733
735
736 le = le->Flink;
737 }
738
739 ExReleaseResourceLite(&me->fileref->fcb->nonpaged->dir_children_lock);
740
741 return STATUS_SUCCESS;
742}
743
745 uint8_t c;
746
747 c = dc->hash >> 24;
748
749 if (fcb->hash_ptrs[c] == &dc->list_entry_hash) {
750 if (dc->list_entry_hash.Flink == &fcb->dir_children_hash)
751 fcb->hash_ptrs[c] = NULL;
752 else {
753 dir_child* dc2 = CONTAINING_RECORD(dc->list_entry_hash.Flink, dir_child, list_entry_hash);
754
755 if (dc2->hash >> 24 == c)
756 fcb->hash_ptrs[c] = &dc2->list_entry_hash;
757 else
758 fcb->hash_ptrs[c] = NULL;
759 }
760 }
761
762 RemoveEntryList(&dc->list_entry_hash);
763
764 c = dc->hash_uc >> 24;
765
766 if (fcb->hash_ptrs_uc[c] == &dc->list_entry_hash_uc) {
767 if (dc->list_entry_hash_uc.Flink == &fcb->dir_children_hash_uc)
769 else {
770 dir_child* dc2 = CONTAINING_RECORD(dc->list_entry_hash_uc.Flink, dir_child, list_entry_hash_uc);
771
772 if (dc2->hash_uc >> 24 == c)
774 else
776 }
777 }
778
779 RemoveEntryList(&dc->list_entry_hash_uc);
780}
781
784 fcb* fcb;
786 PSID owner;
787 BOOLEAN defaulted;
790
792 if (!fcb) {
793 ERR("out of memory\n");
795 }
796
799
800 fcb->Vcb = Vcb;
801
802 fcb->subvol = r;
803 fcb->inode = InterlockedIncrement64(&r->lastinode);
804 fcb->hash = calc_crc32c(0xffffffff, (uint8_t*)&fcb->inode, sizeof(uint64_t));
806
807 fcb->inode_item.generation = Vcb->superblock.generation;
808 fcb->inode_item.transid = Vcb->superblock.generation;
810 fcb->inode_item.st_mode = __S_IFDIR | inherit_mode(parfcb, true);
813
814 fcb->atts = get_file_attributes(Vcb, fcb->subvol, fcb->inode, fcb->type, false, true, NULL);
815
816 SeCaptureSubjectContext(&subjcont);
817
818 Status = SeAssignSecurity(parfcb->sd, NULL, (void**)&fcb->sd, true, &subjcont, IoGetFileObjectGenericMapping(), PagedPool);
819
820 if (!NT_SUCCESS(Status)) {
821 reap_fcb(fcb);
822 ERR("SeAssignSecurity returned %08lx\n", Status);
823 return Status;
824 }
825
826 if (!fcb->sd) {
827 reap_fcb(fcb);
828 ERR("SeAssignSecurity returned NULL security descriptor\n");
830 }
831
832 Status = RtlGetOwnerSecurityDescriptor(fcb->sd, &owner, &defaulted);
833 if (!NT_SUCCESS(Status)) {
834 ERR("RtlGetOwnerSecurityDescriptor returned %08lx\n", Status);
836 fcb->sd_dirty = true;
837 } else {
840 }
841
842 find_gid(fcb, parfcb, &subjcont);
843
844 fcb->inode_item_changed = true;
845
846 fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
847 fcb->Header.AllocationSize.QuadPart = 0;
848 fcb->Header.FileSize.QuadPart = 0;
849 fcb->Header.ValidDataLength.QuadPart = 0;
850
851 fcb->created = true;
852
855
858
860 if (!fcb->hash_ptrs) {
861 ERR("out of memory\n");
863 }
864
865 RtlZeroMemory(fcb->hash_ptrs, sizeof(LIST_ENTRY*) * 256);
866
868 if (!fcb->hash_ptrs_uc) {
869 ERR("out of memory\n");
871 }
872
873 RtlZeroMemory(fcb->hash_ptrs_uc, sizeof(LIST_ENTRY*) * 256);
874
875 acquire_fcb_lock_exclusive(Vcb);
877 InsertTailList(&Vcb->all_fcbs, &fcb->list_entry_all);
878 r->fcbs_version++;
879 release_fcb_lock(Vcb);
880
882
883 *pfcb = fcb;
884
885 return STATUS_SUCCESS;
886}
887
889 LIST_ENTRY* lastle = NULL;
891
892 if (fcb->subvol->fcbs_ptrs[hash >> 24]) {
893 LIST_ENTRY* le = fcb->subvol->fcbs_ptrs[hash >> 24];
894
895 while (le != &fcb->subvol->fcbs) {
896 struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
897
898 if (fcb2->hash > hash) {
899 lastle = le->Blink;
900 break;
901 }
902
903 le = le->Flink;
904 }
905 }
906
907 if (!lastle) {
908 uint8_t c = hash >> 24;
909
910 if (c != 0xff) {
911 uint8_t d = c + 1;
912
913 do {
914 if (fcb->subvol->fcbs_ptrs[d]) {
915 lastle = fcb->subvol->fcbs_ptrs[d]->Blink;
916 break;
917 }
918
919 d++;
920 } while (d != 0);
921 }
922 }
923
924 if (lastle) {
925 InsertHeadList(lastle, &fcb->list_entry);
926
927 if (lastle == &fcb->subvol->fcbs || (CONTAINING_RECORD(lastle, struct _fcb, list_entry)->hash >> 24) != (hash >> 24))
928 fcb->subvol->fcbs_ptrs[hash >> 24] = &fcb->list_entry;
929 } else {
931
932 if (fcb->list_entry.Blink == &fcb->subvol->fcbs || (CONTAINING_RECORD(fcb->list_entry.Blink, struct _fcb, list_entry)->hash >> 24) != (hash >> 24))
933 fcb->subvol->fcbs_ptrs[hash >> 24] = &fcb->list_entry;
934 }
935}
936
938 uint8_t c = fcb->hash >> 24;
939
940 if (fcb->subvol->fcbs_ptrs[c] == &fcb->list_entry) {
941 if (fcb->list_entry.Flink != &fcb->subvol->fcbs && (CONTAINING_RECORD(fcb->list_entry.Flink, struct _fcb, list_entry)->hash >> 24) == c)
942 fcb->subvol->fcbs_ptrs[c] = fcb->list_entry.Flink;
943 else
944 fcb->subvol->fcbs_ptrs[c] = NULL;
945 }
946
948}
949
953 move_entry* me;
956 file_ref* origparent;
957
958 // FIXME - make sure me->dummyfileref and me->dummyfcb get freed properly
959
961
964
965 acquire_fcb_lock_exclusive(fileref->fcb->Vcb);
966
968
969 if (!me) {
970 ERR("out of memory\n");
972 goto end;
973 }
974
975 origparent = fileref->parent;
976
977 me->fileref = fileref;
979 me->dummyfcb = NULL;
980 me->dummyfileref = NULL;
981 me->parent = NULL;
982
984
985 le = move_list.Flink;
986 while (le != &move_list) {
988
989 ExAcquireResourceSharedLite(me->fileref->fcb->Header.Resource, true);
990
991 if (!me->fileref->fcb->ads && me->fileref->fcb->subvol == origparent->fcb->subvol) {
993
994 if (!NT_SUCCESS(Status)) {
995 ERR("add_children_to_move_list returned %08lx\n", Status);
996 ExReleaseResourceLite(me->fileref->fcb->Header.Resource);
997 goto end;
998 }
999 }
1000
1001 ExReleaseResourceLite(me->fileref->fcb->Header.Resource);
1002
1003 le = le->Flink;
1004 }
1005
1007
1008 // loop through list and create new inodes
1009
1010 le = move_list.Flink;
1011 while (le != &move_list) {
1013
1014 if (me->fileref->fcb->inode != SUBVOL_ROOT_INODE && me->fileref->fcb != fileref->fcb->Vcb->dummy_fcb) {
1015 if (!me->dummyfcb) {
1016 ULONG defda;
1017
1018 ExAcquireResourceExclusiveLite(me->fileref->fcb->Header.Resource, true);
1019
1020 Status = duplicate_fcb(me->fileref->fcb, &me->dummyfcb);
1021 if (!NT_SUCCESS(Status)) {
1022 ERR("duplicate_fcb returned %08lx\n", Status);
1023 ExReleaseResourceLite(me->fileref->fcb->Header.Resource);
1024 goto end;
1025 }
1026
1027 me->dummyfcb->subvol = me->fileref->fcb->subvol;
1028 me->dummyfcb->inode = me->fileref->fcb->inode;
1029 me->dummyfcb->hash = me->fileref->fcb->hash;
1030
1031 if (!me->dummyfcb->ads) {
1032 me->dummyfcb->sd_dirty = me->fileref->fcb->sd_dirty;
1038 }
1039
1040 me->dummyfcb->created = me->fileref->fcb->created;
1041 me->dummyfcb->deleted = me->fileref->fcb->deleted;
1043
1044 if (!me->fileref->fcb->ads) {
1045 LIST_ENTRY* le2;
1046
1047 me->fileref->fcb->subvol = destdir->fcb->subvol;
1048 me->fileref->fcb->inode = InterlockedIncrement64(&destdir->fcb->subvol->lastinode);
1049 me->fileref->fcb->hash = calc_crc32c(0xffffffff, (uint8_t*)&me->fileref->fcb->inode, sizeof(uint64_t));
1050 me->fileref->fcb->inode_item.st_nlink = 1;
1051
1052 defda = get_file_attributes(me->fileref->fcb->Vcb, me->fileref->fcb->subvol, me->fileref->fcb->inode,
1053 me->fileref->fcb->type, me->fileref->dc && me->fileref->dc->name.Length >= sizeof(WCHAR) && me->fileref->dc->name.Buffer[0] == '.',
1054 true, Irp);
1055
1056 me->fileref->fcb->sd_dirty = !!me->fileref->fcb->sd;
1057 me->fileref->fcb->atts_changed = defda != me->fileref->fcb->atts;
1062 me->fileref->fcb->inode_item_changed = true;
1063
1064 le2 = me->fileref->fcb->xattrs.Flink;
1065 while (le2 != &me->fileref->fcb->xattrs) {
1067
1068 xa->dirty = true;
1069
1070 le2 = le2->Flink;
1071 }
1072
1073 if (le == move_list.Flink) { // first entry
1074 me->fileref->fcb->inode_item.transid = me->fileref->fcb->Vcb->superblock.generation;
1076
1079 }
1080
1081 le2 = me->fileref->fcb->extents.Flink;
1082 while (le2 != &me->fileref->fcb->extents) {
1084
1085 if (!ext->ignore && (ext->extent_data.type == EXTENT_TYPE_REGULAR || ext->extent_data.type == EXTENT_TYPE_PREALLOC)) {
1086 EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ext->extent_data.data;
1087
1088 if (ed2->size != 0) {
1090
1091 if (!c) {
1092 ERR("get_chunk_from_address(%I64x) failed\n", ed2->address);
1093 } else {
1094 Status = update_changed_extent_ref(me->fileref->fcb->Vcb, c, ed2->address, ed2->size, me->fileref->fcb->subvol->id, me->fileref->fcb->inode,
1095 ext->offset - ed2->offset, 1, me->fileref->fcb->inode_item.flags & BTRFS_INODE_NODATASUM, false, Irp);
1096
1097 if (!NT_SUCCESS(Status)) {
1098 ERR("update_changed_extent_ref returned %08lx\n", Status);
1099 ExReleaseResourceLite(me->fileref->fcb->Header.Resource);
1100 goto end;
1101 }
1102 }
1103
1104 }
1105 }
1106
1107 le2 = le2->Flink;
1108 }
1109
1113 } else {
1114 me->fileref->fcb->subvol = me->parent->fileref->fcb->subvol;
1115 me->fileref->fcb->inode = me->parent->fileref->fcb->inode;
1116 me->fileref->fcb->hash = me->parent->fileref->fcb->hash;
1117
1118 // put stream after parent in FCB list
1119 InsertHeadList(&me->parent->fileref->fcb->list_entry, &me->fileref->fcb->list_entry);
1120 }
1121
1122 me->fileref->fcb->created = true;
1123
1124 InsertTailList(&me->fileref->fcb->Vcb->all_fcbs, &me->dummyfcb->list_entry_all);
1125
1126 while (!IsListEmpty(&me->fileref->fcb->hardlinks)) {
1128
1129 if (hl->name.Buffer)
1130 ExFreePool(hl->name.Buffer);
1131
1132 if (hl->utf8.Buffer)
1133 ExFreePool(hl->utf8.Buffer);
1134
1135 ExFreePool(hl);
1136 }
1137
1138 me->fileref->fcb->inode_item_changed = true;
1140
1141 if ((!me->dummyfcb->ads && me->dummyfcb->inode_item.st_nlink > 1) || (me->dummyfcb->ads && me->parent->dummyfcb->inode_item.st_nlink > 1)) {
1142 LIST_ENTRY* le2 = le->Flink;
1143
1144 while (le2 != &move_list) {
1146
1147 if (me2->fileref->fcb == me->fileref->fcb && !me2->fileref->fcb->ads) {
1148 me2->dummyfcb = me->dummyfcb;
1150 }
1151
1152 le2 = le2->Flink;
1153 }
1154 }
1155
1156 ExReleaseResourceLite(me->fileref->fcb->Header.Resource);
1157 } else {
1158 ExAcquireResourceExclusiveLite(me->fileref->fcb->Header.Resource, true);
1160 me->fileref->fcb->inode_item_changed = true;
1161 ExReleaseResourceLite(me->fileref->fcb->Header.Resource);
1162 }
1163 }
1164
1165 le = le->Flink;
1166 }
1167
1168 fileref->fcb->subvol->root_item.ctransid = fileref->fcb->Vcb->superblock.generation;
1169 fileref->fcb->subvol->root_item.ctime = now;
1170
1171 // loop through list and create new filerefs
1172
1173 le = move_list.Flink;
1174 while (le != &move_list) {
1175 hardlink* hl;
1176 bool name_changed = false;
1177
1179
1180 me->dummyfileref = create_fileref(fileref->fcb->Vcb);
1181 if (!me->dummyfileref) {
1182 ERR("out of memory\n");
1184 goto end;
1185 }
1186
1187 if (me->fileref->fcb == me->fileref->fcb->Vcb->dummy_fcb) {
1188 root* r = me->parent ? me->parent->fileref->fcb->subvol : destdir->fcb->subvol;
1189
1190 Status = create_directory_fcb(me->fileref->fcb->Vcb, r, me->fileref->parent->fcb, &me->fileref->fcb);
1191 if (!NT_SUCCESS(Status)) {
1192 ERR("create_directory_fcb returned %08lx\n", Status);
1193 goto end;
1194 }
1195
1196 me->fileref->dc->key.obj_id = me->fileref->fcb->inode;
1198
1199 me->dummyfileref->fcb = me->fileref->fcb->Vcb->dummy_fcb;
1200 } else if (me->fileref->fcb->inode == SUBVOL_ROOT_INODE) {
1201 me->dummyfileref->fcb = me->fileref->fcb;
1202
1203 me->fileref->fcb->subvol->parent = le == move_list.Flink ? destdir->fcb->subvol->id : me->parent->fileref->fcb->subvol->id;
1204 } else
1205 me->dummyfileref->fcb = me->dummyfcb;
1206
1208
1209 me->dummyfileref->oldutf8 = me->fileref->oldutf8;
1210 me->dummyfileref->oldindex = me->fileref->dc->index;
1211
1212 if (le == move_list.Flink && (me->fileref->dc->utf8.Length != utf8->Length || RtlCompareMemory(me->fileref->dc->utf8.Buffer, utf8->Buffer, utf8->Length) != utf8->Length))
1213 name_changed = true;
1214
1215 if (!me->dummyfileref->oldutf8.Buffer) {
1217 if (!me->dummyfileref->oldutf8.Buffer) {
1218 ERR("out of memory\n");
1220 goto end;
1221 }
1222
1224
1226 }
1227
1229 me->dummyfileref->deleted = me->fileref->deleted;
1230
1231 me->dummyfileref->created = me->fileref->created;
1232 me->fileref->created = true;
1233
1234 me->dummyfileref->parent = me->parent ? me->parent->dummyfileref : origparent;
1236
1237 ExAcquireResourceExclusiveLite(&me->dummyfileref->parent->fcb->nonpaged->dir_children_lock, true);
1239 ExReleaseResourceLite(&me->dummyfileref->parent->fcb->nonpaged->dir_children_lock);
1240
1243
1244 if (!me->parent) {
1246
1248
1249 if (me->fileref->dc) {
1250 // remove from old parent
1251 ExAcquireResourceExclusiveLite(&me->fileref->parent->fcb->nonpaged->dir_children_lock, true);
1254 ExReleaseResourceLite(&me->fileref->parent->fcb->nonpaged->dir_children_lock);
1255
1256 me->fileref->parent->fcb->inode_item.st_size -= me->fileref->dc->utf8.Length * 2;
1257 me->fileref->parent->fcb->inode_item.transid = me->fileref->fcb->Vcb->superblock.generation;
1258 me->fileref->parent->fcb->inode_item.sequence++;
1259 me->fileref->parent->fcb->inode_item.st_ctime = now;
1260 me->fileref->parent->fcb->inode_item.st_mtime = now;
1261 me->fileref->parent->fcb->inode_item_changed = true;
1262 mark_fcb_dirty(me->fileref->parent->fcb);
1263
1264 if (name_changed) {
1268
1270 if (!me->fileref->dc->utf8.Buffer) {
1271 ERR("out of memory\n");
1273 goto end;
1274 }
1275
1276 me->fileref->dc->utf8.Length = me->fileref->dc->utf8.MaximumLength = utf8->Length;
1277 RtlCopyMemory(me->fileref->dc->utf8.Buffer, utf8->Buffer, utf8->Length);
1278
1280 if (!me->fileref->dc->name.Buffer) {
1281 ERR("out of memory\n");
1283 goto end;
1284 }
1285
1286 me->fileref->dc->name.Length = me->fileref->dc->name.MaximumLength = fnus->Length;
1287 RtlCopyMemory(me->fileref->dc->name.Buffer, fnus->Buffer, fnus->Length);
1288
1289 Status = RtlUpcaseUnicodeString(&fileref->dc->name_uc, &fileref->dc->name, true);
1290 if (!NT_SUCCESS(Status)) {
1291 ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
1292 goto end;
1293 }
1294
1295 me->fileref->dc->hash = calc_crc32c(0xffffffff, (uint8_t*)me->fileref->dc->name.Buffer, me->fileref->dc->name.Length);
1296 me->fileref->dc->hash_uc = calc_crc32c(0xffffffff, (uint8_t*)me->fileref->dc->name_uc.Buffer, me->fileref->dc->name_uc.Length);
1297 }
1298
1299 if (me->fileref->dc->key.obj_type == TYPE_INODE_ITEM)
1300 me->fileref->dc->key.obj_id = me->fileref->fcb->inode;
1301
1302 // add to new parent
1303
1304 ExAcquireResourceExclusiveLite(&destdir->fcb->nonpaged->dir_children_lock, true);
1305
1306 if (IsListEmpty(&destdir->fcb->dir_children_index))
1307 me->fileref->dc->index = 2;
1308 else {
1309 dir_child* dc2 = CONTAINING_RECORD(destdir->fcb->dir_children_index.Blink, dir_child, list_entry_index);
1310
1311 me->fileref->dc->index = max(2, dc2->index + 1);
1312 }
1313
1316 ExReleaseResourceLite(&destdir->fcb->nonpaged->dir_children_lock);
1317 }
1318
1320 me->fileref->parent = destdir;
1321
1322 ExAcquireResourceExclusiveLite(&me->fileref->parent->fcb->nonpaged->dir_children_lock, true);
1323 InsertTailList(&me->fileref->parent->children, &me->fileref->list_entry);
1324 ExReleaseResourceLite(&me->fileref->parent->fcb->nonpaged->dir_children_lock);
1325
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);
1327 me->fileref->parent->fcb->inode_item.st_size += me->fileref->dc->utf8.Length * 2;
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);
1329 me->fileref->parent->fcb->inode_item.transid = me->fileref->fcb->Vcb->superblock.generation;
1330 me->fileref->parent->fcb->inode_item.sequence++;
1331 me->fileref->parent->fcb->inode_item.st_ctime = now;
1332 me->fileref->parent->fcb->inode_item.st_mtime = now;
1333 me->fileref->parent->fcb->inode_item_changed = true;
1334 mark_fcb_dirty(me->fileref->parent->fcb);
1335 } else {
1336 if (me->fileref->dc) {
1337 ExAcquireResourceExclusiveLite(&me->fileref->parent->fcb->nonpaged->dir_children_lock, true);
1339
1340 if (!me->fileref->fcb->ads)
1342
1343 ExReleaseResourceLite(&me->fileref->parent->fcb->nonpaged->dir_children_lock);
1344
1345 ExAcquireResourceExclusiveLite(&me->parent->fileref->fcb->nonpaged->dir_children_lock, true);
1346
1347 if (me->fileref->fcb->ads)
1348 InsertHeadList(&me->parent->fileref->fcb->dir_children_index, &me->fileref->dc->list_entry_index);
1349 else {
1350 if (me->fileref->fcb->inode != SUBVOL_ROOT_INODE)
1351 me->fileref->dc->key.obj_id = me->fileref->fcb->inode;
1352
1353 if (IsListEmpty(&me->parent->fileref->fcb->dir_children_index))
1354 me->fileref->dc->index = 2;
1355 else {
1356 dir_child* dc2 = CONTAINING_RECORD(me->parent->fileref->fcb->dir_children_index.Blink, dir_child, list_entry_index);
1357
1358 me->fileref->dc->index = max(2, dc2->index + 1);
1359 }
1360
1361 InsertTailList(&me->parent->fileref->fcb->dir_children_index, &me->fileref->dc->list_entry_index);
1362 insert_dir_child_into_hash_lists(me->parent->fileref->fcb, me->fileref->dc);
1363 }
1364
1365 ExReleaseResourceLite(&me->parent->fileref->fcb->nonpaged->dir_children_lock);
1366 }
1367 }
1368
1369 if (!me->dummyfileref->fcb->ads) {
1371 if (!NT_SUCCESS(Status)) {
1372 ERR("delete_fileref returned %08lx\n", Status);
1373 goto end;
1374 }
1375 }
1376
1377 if (me->fileref->fcb->inode_item.st_nlink > 1) {
1379 if (!hl) {
1380 ERR("out of memory\n");
1382 goto end;
1383 }
1384
1385 hl->parent = me->fileref->parent->fcb->inode;
1386 hl->index = me->fileref->dc->index;
1387
1388 hl->utf8.Length = hl->utf8.MaximumLength = me->fileref->dc->utf8.Length;
1390 if (!hl->utf8.Buffer) {
1391 ERR("out of memory\n");
1393 ExFreePool(hl);
1394 goto end;
1395 }
1396
1398
1399 hl->name.Length = hl->name.MaximumLength = me->fileref->dc->name.Length;
1401 if (!hl->name.Buffer) {
1402 ERR("out of memory\n");
1404 ExFreePool(hl->utf8.Buffer);
1405 ExFreePool(hl);
1406 goto end;
1407 }
1408
1410
1412 }
1413
1415
1416 le = le->Flink;
1417 }
1418
1419 // loop through, and only mark streams as deleted if their parent inodes are also deleted
1420
1421 le = move_list.Flink;
1422 while (le != &move_list) {
1424
1425 if (me->dummyfileref->fcb->ads && me->parent->dummyfileref->fcb->deleted) {
1427 if (!NT_SUCCESS(Status)) {
1428 ERR("delete_fileref returned %08lx\n", Status);
1429 goto end;
1430 }
1431 }
1432
1433 le = le->Flink;
1434 }
1435
1436 destdir->fcb->subvol->root_item.ctransid = destdir->fcb->Vcb->superblock.generation;
1437 destdir->fcb->subvol->root_item.ctime = now;
1438
1443
1445
1446end:
1447 while (!IsListEmpty(&move_list)) {
1450
1451 if (me->dummyfcb)
1452 free_fcb(me->dummyfcb);
1453
1454 if (me->dummyfileref)
1456
1457 free_fileref(me->fileref);
1458
1459 ExFreePool(me);
1460 }
1461
1462 destdir->fcb->subvol->fcbs_version++;
1463 fileref->fcb->subvol->fcbs_version++;
1464
1465 release_fcb_lock(fileref->fcb->Vcb);
1466
1467 return Status;
1468}
1469
1471 bool inserted;
1472 LIST_ENTRY* le;
1473 uint8_t c, d;
1474
1475 c = dc->hash >> 24;
1476
1477 inserted = false;
1478
1479 d = c;
1480 do {
1481 le = fcb->hash_ptrs[d];
1482
1483 if (d == 0)
1484 break;
1485
1486 d--;
1487 } while (!le);
1488
1489 if (!le)
1491
1492 while (le != &fcb->dir_children_hash) {
1493 dir_child* dc2 = CONTAINING_RECORD(le, dir_child, list_entry_hash);
1494
1495 if (dc2->hash > dc->hash) {
1496 InsertHeadList(le->Blink, &dc->list_entry_hash);
1497 inserted = true;
1498 break;
1499 }
1500
1501 le = le->Flink;
1502 }
1503
1504 if (!inserted)
1505 InsertTailList(&fcb->dir_children_hash, &dc->list_entry_hash);
1506
1507 if (!fcb->hash_ptrs[c])
1508 fcb->hash_ptrs[c] = &dc->list_entry_hash;
1509 else {
1510 dir_child* dc2 = CONTAINING_RECORD(fcb->hash_ptrs[c], dir_child, list_entry_hash);
1511
1512 if (dc2->hash > dc->hash)
1513 fcb->hash_ptrs[c] = &dc->list_entry_hash;
1514 }
1515
1516 c = dc->hash_uc >> 24;
1517
1518 inserted = false;
1519
1520 d = c;
1521 do {
1522 le = fcb->hash_ptrs_uc[d];
1523
1524 if (d == 0)
1525 break;
1526
1527 d--;
1528 } while (!le);
1529
1530 if (!le)
1532
1533 while (le != &fcb->dir_children_hash_uc) {
1534 dir_child* dc2 = CONTAINING_RECORD(le, dir_child, list_entry_hash_uc);
1535
1536 if (dc2->hash_uc > dc->hash_uc) {
1537 InsertHeadList(le->Blink, &dc->list_entry_hash_uc);
1538 inserted = true;
1539 break;
1540 }
1541
1542 le = le->Flink;
1543 }
1544
1545 if (!inserted)
1546 InsertTailList(&fcb->dir_children_hash_uc, &dc->list_entry_hash_uc);
1547
1548 if (!fcb->hash_ptrs_uc[c])
1549 fcb->hash_ptrs_uc[c] = &dc->list_entry_hash_uc;
1550 else {
1551 dir_child* dc2 = CONTAINING_RECORD(fcb->hash_ptrs_uc[c], dir_child, list_entry_hash_uc);
1552
1553 if (dc2->hash_uc > dc->hash_uc)
1554 fcb->hash_ptrs_uc[c] = &dc->list_entry_hash_uc;
1555 }
1556}
1557
1561 file_ref* ofr;
1563 dir_child* dc;
1564 fcb* dummyfcb;
1565
1566 if (fileref->fcb->type != BTRFS_TYPE_FILE)
1568
1570 WARN("trying to rename stream on readonly file\n");
1571 return STATUS_ACCESS_DENIED;
1572 }
1573
1574 if (Irp->RequestorMode == UserMode && ccb && !(ccb->access & DELETE)) {
1575 WARN("insufficient permissions\n");
1576 return STATUS_ACCESS_DENIED;
1577 }
1578
1579 if (!(flags & FILE_RENAME_REPLACE_IF_EXISTS)) // file will always exist
1581
1582 // FIXME - POSIX overwrites of stream?
1583
1584 ofr = fileref->parent;
1585
1586 if (ofr->open_count > 0) {
1587 WARN("trying to overwrite open file\n");
1588 return STATUS_ACCESS_DENIED;
1589 }
1590
1591 if (ofr->fcb->inode_item.st_size > 0) {
1592 WARN("can only overwrite existing stream if it is zero-length\n");
1594 }
1595
1596 dummyfcb = create_fcb(Vcb, PagedPool);
1597 if (!dummyfcb) {
1598 ERR("out of memory\n");
1600 }
1601
1602 // copy parent fcb onto this one
1603
1604 fileref->fcb->subvol = ofr->fcb->subvol;
1605 fileref->fcb->inode = ofr->fcb->inode;
1606 fileref->fcb->hash = ofr->fcb->hash;
1607 fileref->fcb->type = ofr->fcb->type;
1608 fileref->fcb->inode_item = ofr->fcb->inode_item;
1609
1610 fileref->fcb->sd = ofr->fcb->sd;
1611 ofr->fcb->sd = NULL;
1612
1613 fileref->fcb->deleted = ofr->fcb->deleted;
1614 fileref->fcb->atts = ofr->fcb->atts;
1615
1616 fileref->fcb->reparse_xattr = ofr->fcb->reparse_xattr;
1617 ofr->fcb->reparse_xattr.Buffer = NULL;
1619
1620 fileref->fcb->ea_xattr = ofr->fcb->ea_xattr;
1621 ofr->fcb->ea_xattr.Buffer = NULL;
1622 ofr->fcb->ea_xattr.Length = ofr->fcb->ea_xattr.MaximumLength = 0;
1623
1624 fileref->fcb->ealen = ofr->fcb->ealen;
1625
1626 while (!IsListEmpty(&ofr->fcb->hardlinks)) {
1627 InsertTailList(&fileref->fcb->hardlinks, RemoveHeadList(&ofr->fcb->hardlinks));
1628 }
1629
1630 fileref->fcb->inode_item_changed = true;
1631 fileref->fcb->prop_compression = ofr->fcb->prop_compression;
1632
1633 while (!IsListEmpty(&ofr->fcb->xattrs)) {
1634 InsertTailList(&fileref->fcb->xattrs, RemoveHeadList(&ofr->fcb->xattrs));
1635 }
1636
1637 fileref->fcb->marked_as_orphan = ofr->fcb->marked_as_orphan;
1638 fileref->fcb->case_sensitive = ofr->fcb->case_sensitive;
1639 fileref->fcb->case_sensitive_set = ofr->fcb->case_sensitive_set;
1640
1641 while (!IsListEmpty(&ofr->fcb->dir_children_index)) {
1642 InsertTailList(&fileref->fcb->dir_children_index, RemoveHeadList(&ofr->fcb->dir_children_index));
1643 }
1644
1645 while (!IsListEmpty(&ofr->fcb->dir_children_hash)) {
1646 InsertTailList(&fileref->fcb->dir_children_hash, RemoveHeadList(&ofr->fcb->dir_children_hash));
1647 }
1648
1649 while (!IsListEmpty(&ofr->fcb->dir_children_hash_uc)) {
1650 InsertTailList(&fileref->fcb->dir_children_hash_uc, RemoveHeadList(&ofr->fcb->dir_children_hash_uc));
1651 }
1652
1653 fileref->fcb->hash_ptrs = ofr->fcb->hash_ptrs;
1654 fileref->fcb->hash_ptrs_uc = ofr->fcb->hash_ptrs_uc;
1655
1656 ofr->fcb->hash_ptrs = NULL;
1657 ofr->fcb->hash_ptrs_uc = NULL;
1658
1659 fileref->fcb->sd_dirty = ofr->fcb->sd_dirty;
1660 fileref->fcb->sd_deleted = ofr->fcb->sd_deleted;
1661 fileref->fcb->atts_changed = ofr->fcb->atts_changed;
1662 fileref->fcb->atts_deleted = ofr->fcb->atts_deleted;
1663 fileref->fcb->extents_changed = true;
1664 fileref->fcb->reparse_xattr_changed = ofr->fcb->reparse_xattr_changed;
1665 fileref->fcb->ea_changed = ofr->fcb->ea_changed;
1666 fileref->fcb->prop_compression_changed = ofr->fcb->prop_compression_changed;
1667 fileref->fcb->xattrs_changed = ofr->fcb->xattrs_changed;
1668 fileref->fcb->created = ofr->fcb->created;
1669 fileref->fcb->ads = false;
1670
1671 if (fileref->fcb->adsxattr.Buffer) {
1672 ExFreePool(fileref->fcb->adsxattr.Buffer);
1673 fileref->fcb->adsxattr.Length = fileref->fcb->adsxattr.MaximumLength = 0;
1674 fileref->fcb->adsxattr.Buffer = NULL;
1675 }
1676
1677 adsdata = fileref->fcb->adsdata;
1678
1679 fileref->fcb->adsdata.Buffer = NULL;
1680 fileref->fcb->adsdata.Length = fileref->fcb->adsdata.MaximumLength = 0;
1681
1682 acquire_fcb_lock_exclusive(Vcb);
1683
1684 RemoveEntryList(&fileref->fcb->list_entry);
1685 InsertHeadList(ofr->fcb->list_entry.Blink, &fileref->fcb->list_entry);
1686
1687 if (fileref->fcb->subvol->fcbs_ptrs[fileref->fcb->hash >> 24] == &ofr->fcb->list_entry)
1688 fileref->fcb->subvol->fcbs_ptrs[fileref->fcb->hash >> 24] = &fileref->fcb->list_entry;
1689
1691
1692 release_fcb_lock(Vcb);
1693
1694 ofr->fcb->list_entry.Flink = ofr->fcb->list_entry.Blink = NULL;
1695
1696 mark_fcb_dirty(fileref->fcb);
1697
1698 // mark old parent fcb so it gets ignored by flush_fcb
1699 ofr->fcb->created = true;
1700 ofr->fcb->deleted = true;
1701
1702 mark_fcb_dirty(ofr->fcb);
1703
1704 // copy parent fileref onto this one
1705
1706 fileref->oldutf8 = ofr->oldutf8;
1707 ofr->oldutf8.Buffer = NULL;
1708 ofr->oldutf8.Length = ofr->oldutf8.MaximumLength = 0;
1709
1710 fileref->oldindex = ofr->oldindex;
1711 fileref->delete_on_close = ofr->delete_on_close;
1712 fileref->posix_delete = ofr->posix_delete;
1713 fileref->deleted = ofr->deleted;
1714 fileref->created = ofr->created;
1715
1716 fileref->parent = ofr->parent;
1717
1718 RemoveEntryList(&fileref->list_entry);
1719 InsertHeadList(ofr->list_entry.Blink, &fileref->list_entry);
1721 ofr->list_entry.Flink = ofr->list_entry.Blink = NULL;
1722
1723 while (!IsListEmpty(&ofr->children)) {
1725
1726 free_fileref(fr->parent);
1727
1728 fr->parent = fileref;
1729 InterlockedIncrement(&fileref->refcount);
1730
1731 InsertTailList(&fileref->children, &fr->list_entry);
1732 }
1733
1734 dc = fileref->dc;
1735
1736 fileref->dc = ofr->dc;
1737 fileref->dc->fileref = fileref;
1738
1740
1741 // mark old parent fileref so it gets ignored by flush_fileref
1742 ofr->created = true;
1743 ofr->deleted = true;
1744
1745 // write file data
1746
1747 fileref->fcb->inode_item.st_size = adsdata.Length;
1748
1749 if (adsdata.Length > 0) {
1750 bool make_inline = adsdata.Length <= Vcb->options.max_inline;
1751
1752 if (make_inline) {
1754 if (!ed) {
1755 ERR("out of memory\n");
1757 reap_fcb(dummyfcb);
1759 }
1760
1761 ed->generation = Vcb->superblock.generation;
1767
1769
1771
1773 if (!NT_SUCCESS(Status)) {
1774 ERR("add_extent_to_fcb returned %08lx\n", Status);
1775 ExFreePool(ed);
1776 reap_fcb(dummyfcb);
1777 return Status;
1778 }
1779
1780 ExFreePool(ed);
1781 } else if (adsdata.Length & (Vcb->superblock.sector_size - 1)) {
1782 char* newbuf = ExAllocatePoolWithTag(PagedPool, (uint16_t)sector_align(adsdata.Length, Vcb->superblock.sector_size), ALLOC_TAG);
1783 if (!newbuf) {
1784 ERR("out of memory\n");
1786 reap_fcb(dummyfcb);
1788 }
1789
1791 RtlZeroMemory(newbuf + adsdata.Length, (uint16_t)(sector_align(adsdata.Length, Vcb->superblock.sector_size) - adsdata.Length));
1792
1794
1795 adsdata.Buffer = newbuf;
1796 adsdata.Length = adsdata.MaximumLength = (uint16_t)sector_align(adsdata.Length, Vcb->superblock.sector_size);
1797 }
1798
1799 if (!make_inline) {
1801 if (!NT_SUCCESS(Status)) {
1802 ERR("do_write_file returned %08lx\n", Status);
1804 reap_fcb(dummyfcb);
1805 return Status;
1806 }
1807
1809 }
1810
1811 fileref->fcb->inode_item.st_blocks = adsdata.Length;
1812 fileref->fcb->inode_item_changed = true;
1813 }
1814
1815 RemoveEntryList(&dc->list_entry_index);
1816
1817 if (dc->utf8.Buffer)
1818 ExFreePool(dc->utf8.Buffer);
1819
1820 if (dc->name.Buffer)
1821 ExFreePool(dc->name.Buffer);
1822
1823 if (dc->name_uc.Buffer)
1824 ExFreePool(dc->name_uc.Buffer);
1825
1826 ExFreePool(dc);
1827
1828 // FIXME - csums?
1829
1830 // add dummy deleted xattr with old name
1831
1832 dummyfcb->Vcb = Vcb;
1833 dummyfcb->subvol = fileref->fcb->subvol;
1834 dummyfcb->inode = fileref->fcb->inode;
1835 dummyfcb->hash = fileref->fcb->hash;
1836 dummyfcb->adsxattr = fileref->fcb->adsxattr;
1837 dummyfcb->adshash = fileref->fcb->adshash;
1838 dummyfcb->ads = true;
1839 dummyfcb->deleted = true;
1840
1841 acquire_fcb_lock_exclusive(Vcb);
1842 add_fcb_to_subvol(dummyfcb);
1843 InsertTailList(&Vcb->all_fcbs, &dummyfcb->list_entry_all);
1844 dummyfcb->subvol->fcbs_version++;
1845 release_fcb_lock(Vcb);
1846
1847 // FIXME - dummyfileref as well?
1848
1849 mark_fcb_dirty(dummyfcb);
1850
1851 free_fcb(dummyfcb);
1852
1853 return STATUS_SUCCESS;
1854}
1855
1860 file_ref* sf = NULL;
1861 uint16_t newmaxlen;
1862 ULONG utf8len;
1863 ANSI_STRING utf8;
1864 UNICODE_STRING utf16, utf16uc;
1867 fcb* dummyfcb;
1868
1869 static const WCHAR datasuf[] = L":$DATA";
1870 static const char xapref[] = "user.";
1871
1872 if (!fileref) {
1873 ERR("fileref not set\n");
1875 }
1876
1877 if (!fileref->parent) {
1878 ERR("fileref->parent not set\n");
1880 }
1881
1882 if (fri->FileNameLength < sizeof(WCHAR)) {
1883 WARN("filename too short\n");
1885 }
1886
1887 if (fri->FileName[0] != ':') {
1888 WARN("destination filename must begin with a colon\n");
1890 }
1891
1892 if (Irp->RequestorMode == UserMode && ccb && !(ccb->access & DELETE)) {
1893 WARN("insufficient permissions\n");
1894 return STATUS_ACCESS_DENIED;
1895 }
1896
1897 fn.Buffer = &fri->FileName[1];
1898 fn.Length = fn.MaximumLength = (USHORT)(fri->FileNameLength - sizeof(WCHAR));
1899
1900 // remove :$DATA suffix
1901 if (fn.Length >= sizeof(datasuf) - sizeof(WCHAR) &&
1902 RtlCompareMemory(&fn.Buffer[(fn.Length - sizeof(datasuf) + sizeof(WCHAR))/sizeof(WCHAR)], datasuf, sizeof(datasuf) - sizeof(WCHAR)) == sizeof(datasuf) - sizeof(WCHAR))
1903 fn.Length -= sizeof(datasuf) - sizeof(WCHAR);
1904
1905 if (fn.Length == 0)
1907
1908 Status = check_file_name_valid(&fn, false, true);
1909 if (!NT_SUCCESS(Status)) {
1910 WARN("invalid stream name %.*S\n", (int)(fn.Length / sizeof(WCHAR)), fn.Buffer);
1911 return Status;
1912 }
1913
1915 WARN("trying to rename stream on readonly file\n");
1916 return STATUS_ACCESS_DENIED;
1917 }
1918
1919 Status = open_fileref_child(Vcb, fileref->parent, &fn, fileref->parent->fcb->case_sensitive, true, true, PagedPool, &sf, Irp);
1921 if (Status == STATUS_SUCCESS) {
1922 if (fileref == sf || sf->deleted) {
1923 free_fileref(sf);
1924 sf = NULL;
1925 } else {
1928 goto end;
1929 }
1930
1931 // FIXME - POSIX overwrites of stream?
1932
1933 if (sf->open_count > 0) {
1934 WARN("trying to overwrite open file\n");
1936 goto end;
1937 }
1938
1939 if (sf->fcb->adsdata.Length > 0) {
1940 WARN("can only overwrite existing stream if it is zero-length\n");
1942 goto end;
1943 }
1944
1945 Status = delete_fileref(sf, NULL, false, Irp, rollback);
1946 if (!NT_SUCCESS(Status)) {
1947 ERR("delete_fileref returned %08lx\n", Status);
1948 goto end;
1949 }
1950 }
1951 } else {
1952 ERR("open_fileref_child returned %08lx\n", Status);
1953 goto end;
1954 }
1955 }
1956
1957 Status = utf16_to_utf8(NULL, 0, &utf8len, fn.Buffer, fn.Length);
1958 if (!NT_SUCCESS(Status))
1959 goto end;
1960
1961 utf8.MaximumLength = utf8.Length = (uint16_t)utf8len;
1963 if (!utf8.Buffer) {
1964 ERR("out of memory\n");
1966 goto end;
1967 }
1968
1969 Status = utf16_to_utf8(utf8.Buffer, utf8len, &utf8len, fn.Buffer, fn.Length);
1970 if (!NT_SUCCESS(Status)) {
1971 ExFreePool(utf8.Buffer);
1972 goto end;
1973 }
1974
1975 adsxattr.Length = adsxattr.MaximumLength = sizeof(xapref) - 1 + utf8.Length;
1977 if (!adsxattr.Buffer) {
1978 ERR("out of memory\n");
1980 ExFreePool(utf8.Buffer);
1981 goto end;
1982 }
1983
1984 RtlCopyMemory(adsxattr.Buffer, xapref, sizeof(xapref) - 1);
1985 RtlCopyMemory(&adsxattr.Buffer[sizeof(xapref) - 1], utf8.Buffer, utf8.Length);
1986
1987 // don't allow if it's one of our reserved names
1988
1994 ExFreePool(utf8.Buffer);
1996 goto end;
1997 }
1998
1999 utf16.Length = utf16.MaximumLength = fn.Length;
2001 if (!utf16.Buffer) {
2002 ERR("out of memory\n");
2004 ExFreePool(utf8.Buffer);
2006 goto end;
2007 }
2008
2009 RtlCopyMemory(utf16.Buffer, fn.Buffer, fn.Length);
2010
2011 newmaxlen = Vcb->superblock.node_size - sizeof(tree_header) - sizeof(leaf_node) -
2012 offsetof(DIR_ITEM, name[0]);
2013
2014 if (newmaxlen < adsxattr.Length) {
2015 WARN("cannot rename as data too long\n");
2017 ExFreePool(utf8.Buffer);
2018 ExFreePool(utf16.Buffer);
2020 goto end;
2021 }
2022
2023 newmaxlen -= adsxattr.Length;
2024
2025 if (newmaxlen < fileref->fcb->adsdata.Length) {
2026 WARN("cannot rename as data too long\n");
2028 ExFreePool(utf8.Buffer);
2029 ExFreePool(utf16.Buffer);
2031 goto end;
2032 }
2033
2034 Status = RtlUpcaseUnicodeString(&utf16uc, &fn, true);
2035 if (!NT_SUCCESS(Status)) {
2036 ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
2037 ExFreePool(utf8.Buffer);
2038 ExFreePool(utf16.Buffer);
2040 goto end;
2041 }
2042
2043 // add dummy deleted xattr with old name
2044
2045 dummyfcb = create_fcb(Vcb, PagedPool);
2046 if (!dummyfcb) {
2047 ERR("out of memory\n");
2049 ExFreePool(utf8.Buffer);
2050 ExFreePool(utf16.Buffer);
2051 ExFreePool(utf16uc.Buffer);
2053 goto end;
2054 }
2055
2056 dummyfcb->Vcb = Vcb;
2057 dummyfcb->subvol = fileref->fcb->subvol;
2058 dummyfcb->inode = fileref->fcb->inode;
2059 dummyfcb->hash = fileref->fcb->hash;
2060 dummyfcb->adsxattr = fileref->fcb->adsxattr;
2061 dummyfcb->adshash = fileref->fcb->adshash;
2062 dummyfcb->ads = true;
2063 dummyfcb->deleted = true;
2064
2065 acquire_fcb_lock_exclusive(Vcb);
2066 add_fcb_to_subvol(dummyfcb);
2067 InsertTailList(&Vcb->all_fcbs, &dummyfcb->list_entry_all);
2068 dummyfcb->subvol->fcbs_version++;
2069 release_fcb_lock(Vcb);
2070
2071 mark_fcb_dirty(dummyfcb);
2072
2073 free_fcb(dummyfcb);
2074
2075 // change fcb values
2076
2077 fileref->dc->utf8 = utf8;
2078 fileref->dc->name = utf16;
2079 fileref->dc->name_uc = utf16uc;
2080
2082
2083 fileref->fcb->adsxattr = adsxattr;
2084 fileref->fcb->adshash = crc32;
2085 fileref->fcb->adsmaxlen = newmaxlen;
2086
2087 fileref->fcb->created = true;
2088
2089 mark_fcb_dirty(fileref->fcb);
2090
2092
2093end:
2094 if (sf)
2095 free_fileref(sf);
2096
2097 return Status;
2098}
2099
2104 file_ref* sf = NULL;
2105 uint16_t newmaxlen;
2106 ULONG utf8len;
2107 ANSI_STRING utf8;
2108 UNICODE_STRING utf16, utf16uc;
2111 fcb* dummyfcb;
2112 file_ref* dummyfileref;
2113 dir_child* dc;
2114 LIST_ENTRY* le;
2115
2116 static const WCHAR datasuf[] = L":$DATA";
2117 static const char xapref[] = "user.";
2118
2119 if (!fileref) {
2120 ERR("fileref not set\n");
2122 }
2123
2124 if (fri->FileNameLength < sizeof(WCHAR)) {
2125 WARN("filename too short\n");
2127 }
2128
2129 if (fri->FileName[0] != ':') {
2130 WARN("destination filename must begin with a colon\n");
2132 }
2133
2134 if (Irp->RequestorMode == UserMode && ccb && !(ccb->access & DELETE)) {
2135 WARN("insufficient permissions\n");
2136 return STATUS_ACCESS_DENIED;
2137 }
2138
2139 if (fileref->fcb->type != BTRFS_TYPE_FILE)
2141
2142 fn.Buffer = &fri->FileName[1];
2143 fn.Length = fn.MaximumLength = (USHORT)(fri->FileNameLength - sizeof(WCHAR));
2144
2145 // remove :$DATA suffix
2146 if (fn.Length >= sizeof(datasuf) - sizeof(WCHAR) &&
2147 RtlCompareMemory(&fn.Buffer[(fn.Length - sizeof(datasuf) + sizeof(WCHAR))/sizeof(WCHAR)], datasuf, sizeof(datasuf) - sizeof(WCHAR)) == sizeof(datasuf) - sizeof(WCHAR))
2148 fn.Length -= sizeof(datasuf) - sizeof(WCHAR);
2149
2150 if (fn.Length == 0) {
2151 WARN("not allowing overwriting file with itself\n");
2153 }
2154
2155 Status = check_file_name_valid(&fn, false, true);
2156 if (!NT_SUCCESS(Status)) {
2157 WARN("invalid stream name %.*S\n", (int)(fn.Length / sizeof(WCHAR)), fn.Buffer);
2158 return Status;
2159 }
2160
2162 WARN("trying to rename stream on readonly file\n");
2163 return STATUS_ACCESS_DENIED;
2164 }
2165
2166 Status = open_fileref_child(Vcb, fileref, &fn, fileref->fcb->case_sensitive, true, true, PagedPool, &sf, Irp);
2168 if (Status == STATUS_SUCCESS) {
2169 if (fileref == sf || sf->deleted) {
2170 free_fileref(sf);
2171 sf = NULL;
2172 } else {
2175 goto end;
2176 }
2177
2178 // FIXME - POSIX overwrites of stream?
2179
2180 if (sf->open_count > 0) {
2181 WARN("trying to overwrite open file\n");
2183 goto end;
2184 }
2185
2186 if (sf->fcb->adsdata.Length > 0) {
2187 WARN("can only overwrite existing stream if it is zero-length\n");
2189 goto end;
2190 }
2191
2192 Status = delete_fileref(sf, NULL, false, Irp, rollback);
2193 if (!NT_SUCCESS(Status)) {
2194 ERR("delete_fileref returned %08lx\n", Status);
2195 goto end;
2196 }
2197 }
2198 } else {
2199 ERR("open_fileref_child returned %08lx\n", Status);
2200 goto end;
2201 }
2202 }
2203
2204 Status = utf16_to_utf8(NULL, 0, &utf8len, fn.Buffer, fn.Length);
2205 if (!NT_SUCCESS(Status))
2206 goto end;
2207
2208 utf8.MaximumLength = utf8.Length = (uint16_t)utf8len;
2210 if (!utf8.Buffer) {
2211 ERR("out of memory\n");
2213 goto end;
2214 }
2215
2216 Status = utf16_to_utf8(utf8.Buffer, utf8len, &utf8len, fn.Buffer, fn.Length);
2217 if (!NT_SUCCESS(Status)) {
2218 ExFreePool(utf8.Buffer);
2219 goto end;
2220 }
2221
2222 adsxattr.Length = adsxattr.MaximumLength = sizeof(xapref) - 1 + utf8.Length;
2224 if (!adsxattr.Buffer) {
2225 ERR("out of memory\n");
2227 ExFreePool(utf8.Buffer);
2228 goto end;
2229 }
2230
2231 RtlCopyMemory(adsxattr.Buffer, xapref, sizeof(xapref) - 1);
2232 RtlCopyMemory(&adsxattr.Buffer[sizeof(xapref) - 1], utf8.Buffer, utf8.Length);
2233
2234 // don't allow if it's one of our reserved names
2235
2241 ExFreePool(utf8.Buffer);
2243 goto end;
2244 }
2245
2246 utf16.Length = utf16.MaximumLength = fn.Length;
2248 if (!utf16.Buffer) {
2249 ERR("out of memory\n");
2251 ExFreePool(utf8.Buffer);
2253 goto end;
2254 }
2255
2256 RtlCopyMemory(utf16.Buffer, fn.Buffer, fn.Length);
2257
2258 newmaxlen = Vcb->superblock.node_size - sizeof(tree_header) - sizeof(leaf_node) -
2259 offsetof(DIR_ITEM, name[0]);
2260
2261 if (newmaxlen < adsxattr.Length) {
2262 WARN("cannot rename as data too long\n");
2264 ExFreePool(utf8.Buffer);
2265 ExFreePool(utf16.Buffer);
2267 goto end;
2268 }
2269
2270 newmaxlen -= adsxattr.Length;
2271
2272 if (newmaxlen < fileref->fcb->inode_item.st_size) {
2273 WARN("cannot rename as data too long\n");
2275 ExFreePool(utf8.Buffer);
2276 ExFreePool(utf16.Buffer);
2278 goto end;
2279 }
2280
2281 Status = RtlUpcaseUnicodeString(&utf16uc, &fn, true);
2282 if (!NT_SUCCESS(Status)) {
2283 ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
2284 ExFreePool(utf8.Buffer);
2285 ExFreePool(utf16.Buffer);
2287 goto end;
2288 }
2289
2290 // read existing file data
2291
2292 if (fileref->fcb->inode_item.st_size > 0) {
2293 ULONG bytes_read;
2294
2295 adsdata.Length = adsdata.MaximumLength = (uint16_t)fileref->fcb->inode_item.st_size;
2296
2298 if (!adsdata.Buffer) {
2299 ERR("out of memory\n");
2301 ExFreePool(utf8.Buffer);
2302 ExFreePool(utf16.Buffer);
2303 ExFreePool(utf16uc.Buffer);
2305 goto end;
2306 }
2307
2308 Status = read_file(fileref->fcb, (uint8_t*)adsdata.Buffer, 0, adsdata.Length, &bytes_read, Irp);
2309 if (!NT_SUCCESS(Status)) {
2310 ERR("out of memory\n");
2312 ExFreePool(utf8.Buffer);
2313 ExFreePool(utf16.Buffer);
2314 ExFreePool(utf16uc.Buffer);
2317 goto end;
2318 }
2319
2320 if (bytes_read < fileref->fcb->inode_item.st_size) {
2321 ERR("short read\n");
2323 ExFreePool(utf8.Buffer);
2324 ExFreePool(utf16.Buffer);
2325 ExFreePool(utf16uc.Buffer);
2328 goto end;
2329 }
2330 } else
2332
2334 if (!dc) {
2335 ERR("out of memory\n");
2337 ExFreePool(utf8.Buffer);
2338 ExFreePool(utf16.Buffer);
2339 ExFreePool(utf16uc.Buffer);
2341
2342 if (adsdata.Buffer)
2344
2345 goto end;
2346 }
2347
2348 // add dummy deleted fcb with old name
2349
2350 Status = duplicate_fcb(fileref->fcb, &dummyfcb);
2351 if (!NT_SUCCESS(Status)) {
2352 ERR("duplicate_fcb returned %08lx\n", Status);
2353 ExFreePool(utf8.Buffer);
2354 ExFreePool(utf16.Buffer);
2355 ExFreePool(utf16uc.Buffer);
2357
2358 if (adsdata.Buffer)
2360
2361 ExFreePool(dc);
2362
2363 goto end;
2364 }
2365
2366 dummyfileref = create_fileref(Vcb);
2367 if (!dummyfileref) {
2368 ERR("out of memory\n");
2370 ExFreePool(utf8.Buffer);
2371 ExFreePool(utf16.Buffer);
2372 ExFreePool(utf16uc.Buffer);
2374
2375 if (adsdata.Buffer)
2377
2378 ExFreePool(dc);
2379
2380 reap_fcb(dummyfcb);
2381
2382 goto end;
2383 }
2384
2385 dummyfileref->fcb = dummyfcb;
2386
2387 dummyfcb->Vcb = Vcb;
2388 dummyfcb->subvol = fileref->fcb->subvol;
2389 dummyfcb->inode = fileref->fcb->inode;
2390 dummyfcb->hash = fileref->fcb->hash;
2391
2392 if (fileref->fcb->inode_item.st_size > 0) {
2393 Status = excise_extents(Vcb, dummyfcb, 0, sector_align(fileref->fcb->inode_item.st_size, Vcb->superblock.sector_size),
2394 Irp, rollback);
2395 if (!NT_SUCCESS(Status)) {
2396 ERR("excise_extents returned %08lx\n", Status);
2397 ExFreePool(utf8.Buffer);
2398 ExFreePool(utf16.Buffer);
2399 ExFreePool(utf16uc.Buffer);
2402 ExFreePool(dc);
2403
2404 reap_fileref(Vcb, dummyfileref);
2405 reap_fcb(dummyfcb);
2406
2407 goto end;
2408 }
2409
2410 dummyfcb->inode_item.st_size = 0;
2411 dummyfcb->Header.AllocationSize.QuadPart = 0;
2412 dummyfcb->Header.FileSize.QuadPart = 0;
2413 dummyfcb->Header.ValidDataLength.QuadPart = 0;
2414 }
2415
2416 dummyfcb->hash_ptrs = fileref->fcb->hash_ptrs;
2417 dummyfcb->hash_ptrs_uc = fileref->fcb->hash_ptrs_uc;
2418 dummyfcb->created = fileref->fcb->created;
2419
2420 le = fileref->fcb->extents.Flink;
2421 while (le != &fileref->fcb->extents) {
2423
2424 ext->ignore = true;
2425
2426 le = le->Flink;
2427 }
2428
2429 while (!IsListEmpty(&fileref->fcb->dir_children_index)) {
2430 InsertTailList(&dummyfcb->dir_children_index, RemoveHeadList(&fileref->fcb->dir_children_index));
2431 }
2432
2433 while (!IsListEmpty(&fileref->fcb->dir_children_hash)) {
2434 InsertTailList(&dummyfcb->dir_children_hash, RemoveHeadList(&fileref->fcb->dir_children_hash));
2435 }
2436
2437 while (!IsListEmpty(&fileref->fcb->dir_children_hash_uc)) {
2438 InsertTailList(&dummyfcb->dir_children_hash_uc, RemoveHeadList(&fileref->fcb->dir_children_hash_uc));
2439 }
2440
2441 InsertTailList(&Vcb->all_fcbs, &dummyfcb->list_entry_all);
2442
2443 InsertHeadList(fileref->fcb->list_entry.Blink, &dummyfcb->list_entry);
2444
2445 if (fileref->fcb->subvol->fcbs_ptrs[dummyfcb->hash >> 24] == &fileref->fcb->list_entry)
2446 fileref->fcb->subvol->fcbs_ptrs[dummyfcb->hash >> 24] = &dummyfcb->list_entry;
2447
2448 RemoveEntryList(&fileref->fcb->list_entry);
2449 fileref->fcb->list_entry.Flink = fileref->fcb->list_entry.Blink = NULL;
2450
2451 mark_fcb_dirty(dummyfcb);
2452
2453 // create dummy fileref
2454
2455 dummyfileref->oldutf8 = fileref->oldutf8;
2456 dummyfileref->oldindex = fileref->oldindex;
2457 dummyfileref->delete_on_close = fileref->delete_on_close;
2458 dummyfileref->posix_delete = fileref->posix_delete;
2459 dummyfileref->deleted = fileref->deleted;
2460 dummyfileref->created = fileref->created;
2461 dummyfileref->parent = fileref->parent;
2462
2463 while (!IsListEmpty(&fileref->children)) {
2465
2466 free_fileref(fr->parent);
2467
2468 fr->parent = dummyfileref;
2469 InterlockedIncrement(&dummyfileref->refcount);
2470
2471 InsertTailList(&dummyfileref->children, &fr->list_entry);
2472 }
2473
2474 InsertTailList(fileref->list_entry.Blink, &dummyfileref->list_entry);
2475
2476 RemoveEntryList(&fileref->list_entry);
2477 InsertTailList(&dummyfileref->children, &fileref->list_entry);
2478
2479 dummyfileref->dc = fileref->dc;
2480 dummyfileref->dc->fileref = dummyfileref;
2481
2482 mark_fileref_dirty(dummyfileref);
2483
2484 // change fcb values
2485
2486 fileref->fcb->hash_ptrs = NULL;
2487 fileref->fcb->hash_ptrs_uc = NULL;
2488
2489 fileref->fcb->ads = true;
2490
2491 fileref->oldutf8.Length = fileref->oldutf8.MaximumLength = 0;
2492 fileref->oldutf8.Buffer = NULL;
2493
2494 RtlZeroMemory(dc, sizeof(dir_child));
2495
2496 dc->utf8 = utf8;
2497 dc->name = utf16;
2498 dc->hash = calc_crc32c(0xffffffff, (uint8_t*)dc->name.Buffer, dc->name.Length);
2499 dc->name_uc = utf16uc;
2500 dc->hash_uc = calc_crc32c(0xffffffff, (uint8_t*)dc->name_uc.Buffer, dc->name_uc.Length);
2501 dc->fileref = fileref;
2502 InsertTailList(&dummyfcb->dir_children_index, &dc->list_entry_index);
2503
2504 fileref->dc = dc;
2505 fileref->parent = dummyfileref;
2506
2508
2509 fileref->fcb->adsxattr = adsxattr;
2510 fileref->fcb->adshash = crc32;
2511 fileref->fcb->adsmaxlen = newmaxlen;
2512 fileref->fcb->adsdata = adsdata;
2513
2514 fileref->fcb->created = true;
2515
2516 mark_fcb_dirty(fileref->fcb);
2517
2519
2520end:
2521 if (sf)
2522 free_fileref(sf);
2523
2524 return Status;
2525}
2526
2528 FILE_RENAME_INFORMATION_EX* fri = Irp->AssociatedIrp.SystemBuffer;
2529 fcb* fcb = FileObject->FsContext;
2530 ccb* ccb = FileObject->FsContext2;
2531 file_ref *fileref = ccb ? ccb->fileref : NULL, *oldfileref = NULL, *related = NULL, *fr2 = NULL;
2532 WCHAR* fn;
2533 ULONG fnlen, utf8len, origutf8len;
2534 UNICODE_STRING fnus;
2535 ANSI_STRING utf8;
2539 LIST_ENTRY rollback, *le;
2540 hardlink* hl;
2541 SECURITY_SUBJECT_CONTEXT subjcont;
2543 ULONG flags;
2544
2546
2547 if (ex)
2548 flags = fri->Flags;
2549 else
2551
2552 TRACE("tfo = %p\n", tfo);
2553 TRACE("Flags = %lx\n", flags);
2554 TRACE("RootDirectory = %p\n", fri->RootDirectory);
2555 TRACE("FileName = %.*S\n", (int)(fri->FileNameLength / sizeof(WCHAR)), fri->FileName);
2556
2557 fn = fri->FileName;
2558 fnlen = fri->FileNameLength / sizeof(WCHAR);
2559
2560 if (!tfo) {
2561 if (!fileref || !fileref->parent) {
2562 ERR("no fileref set and no directory given\n");
2564 }
2565 } else {
2566 LONG i;
2567
2568 while (fnlen > 0 && (fri->FileName[fnlen - 1] == '/' || fri->FileName[fnlen - 1] == '\\')) {
2569 fnlen--;
2570 }
2571
2572 if (fnlen == 0)
2574
2575 for (i = fnlen - 1; i >= 0; i--) {
2576 if (fri->FileName[i] == '\\' || fri->FileName[i] == '/') {
2577 fn = &fri->FileName[i+1];
2578 fnlen -= i + 1;
2579 break;
2580 }
2581 }
2582 }
2583
2584 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
2585 ExAcquireResourceExclusiveLite(&Vcb->fileref_lock, true);
2586 ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
2587
2589 WARN("not allowing \\$Root to be renamed\n");
2591 goto end;
2592 }
2593
2594 if (fcb->ads) {
2595 if (FileObject->SectionObjectPointer && FileObject->SectionObjectPointer->DataSectionObject) {
2597
2598 CcFlushCache(FileObject->SectionObjectPointer, NULL, 0, &iosb);
2599 if (!NT_SUCCESS(iosb.Status)) {
2600 ERR("CcFlushCache returned %08lx\n", iosb.Status);
2601 Status = iosb.Status;
2602 goto end;
2603 }
2604 }
2605
2607 goto end;
2608 } else if (fnlen >= 1 && fn[0] == ':') {
2609 if (FileObject->SectionObjectPointer && FileObject->SectionObjectPointer->DataSectionObject) {
2611
2612 CcFlushCache(FileObject->SectionObjectPointer, NULL, 0, &iosb);
2613 if (!NT_SUCCESS(iosb.Status)) {
2614 ERR("CcFlushCache returned %08lx\n", iosb.Status);
2615 Status = iosb.Status;
2616 goto end;
2617 }
2618 }
2619
2621 goto end;
2622 }
2623
2624 fnus.Buffer = fn;
2625 fnus.Length = fnus.MaximumLength = (uint16_t)(fnlen * sizeof(WCHAR));
2626
2627 TRACE("fnus = %.*S\n", (int)(fnus.Length / sizeof(WCHAR)), fnus.Buffer);
2628
2629 Status = check_file_name_valid(&fnus, false, false);
2630 if (!NT_SUCCESS(Status))
2631 goto end;
2632
2633 origutf8len = fileref->dc->utf8.Length;
2634
2635 Status = utf16_to_utf8(NULL, 0, &utf8len, fn, (ULONG)fnlen * sizeof(WCHAR));
2636 if (!NT_SUCCESS(Status))
2637 goto end;
2638
2639 utf8.MaximumLength = utf8.Length = (uint16_t)utf8len;
2641 if (!utf8.Buffer) {
2642 ERR("out of memory\n");
2644 goto end;
2645 }
2646
2647 Status = utf16_to_utf8(utf8.Buffer, utf8len, &utf8len, fn, (ULONG)fnlen * sizeof(WCHAR));
2648 if (!NT_SUCCESS(Status))
2649 goto end;
2650
2651 if (tfo && tfo->FsContext2) {
2652 struct _ccb* relatedccb = tfo->FsContext2;
2653
2654 related = relatedccb->fileref;
2656 } else if (fnus.Length >= sizeof(WCHAR) && fnus.Buffer[0] != '\\') {
2657 related = fileref->parent;
2659 }
2660
2661 Status = open_fileref(Vcb, &oldfileref, &fnus, related, false, NULL, NULL, PagedPool, ccb->case_sensitive, Irp);
2662
2663 if (NT_SUCCESS(Status)) {
2664 TRACE("destination file already exists\n");
2665
2666 if (fileref != oldfileref && !oldfileref->deleted) {
2669 goto end;
2670 } else if (fileref == oldfileref) {
2672 goto end;
2673 } else if (!(flags & FILE_RENAME_POSIX_SEMANTICS) && (oldfileref->open_count > 0 || has_open_children(oldfileref)) && !oldfileref->deleted) {
2674 WARN("trying to overwrite open file\n");
2676 goto end;
2677 } else if (!(flags & FILE_RENAME_IGNORE_READONLY_ATTRIBUTE) && oldfileref->fcb->atts & FILE_ATTRIBUTE_READONLY) {
2678 WARN("trying to overwrite readonly file\n");
2680 goto end;
2681 } else if (oldfileref->fcb->type == BTRFS_TYPE_DIRECTORY) {
2682 WARN("trying to overwrite directory\n");
2684 goto end;
2685 }
2686 }
2687
2688 if (fileref == oldfileref || oldfileref->deleted) {
2689 free_fileref(oldfileref);
2690 oldfileref = NULL;
2691 }
2692 }
2693
2694 if (!related) {
2695 Status = open_fileref(Vcb, &related, &fnus, NULL, true, NULL, NULL, PagedPool, ccb->case_sensitive, Irp);
2696
2697 if (!NT_SUCCESS(Status)) {
2698 ERR("open_fileref returned %08lx\n", Status);
2699 goto end;
2700 }
2701 }
2702
2703 if (related->fcb == Vcb->dummy_fcb) {
2705 goto end;
2706 }
2707
2708 SeCaptureSubjectContext(&subjcont);
2709
2710 if (!SeAccessCheck(related->fcb->sd, &subjcont, false, fcb->type == BTRFS_TYPE_DIRECTORY ? FILE_ADD_SUBDIRECTORY : FILE_ADD_FILE, 0, NULL,
2711 IoGetFileObjectGenericMapping(), Irp->RequestorMode, &access, &Status)) {
2712 SeReleaseSubjectContext(&subjcont);
2713 TRACE("SeAccessCheck failed, returning %08lx\n", Status);
2714 goto end;
2715 }
2716
2717 SeReleaseSubjectContext(&subjcont);
2718
2720 WARN("trying to rename file with open children\n");
2722 goto end;
2723 }
2724
2725 if (oldfileref) {
2726 SeCaptureSubjectContext(&subjcont);
2727
2728 if (!SeAccessCheck(oldfileref->fcb->sd, &subjcont, false, DELETE, 0, NULL,
2729 IoGetFileObjectGenericMapping(), Irp->RequestorMode, &access, &Status)) {
2730 SeReleaseSubjectContext(&subjcont);
2731 TRACE("SeAccessCheck failed, returning %08lx\n", Status);
2732 goto end;
2733 }
2734
2735 SeReleaseSubjectContext(&subjcont);
2736
2737 if (oldfileref->open_count > 0 && flags & FILE_RENAME_POSIX_SEMANTICS) {
2738 oldfileref->delete_on_close = true;
2739 oldfileref->posix_delete = true;
2740 }
2741
2742 Status = delete_fileref(oldfileref, NULL, oldfileref->open_count > 0 && flags & FILE_RENAME_POSIX_SEMANTICS, Irp, &rollback);
2743 if (!NT_SUCCESS(Status)) {
2744 ERR("delete_fileref returned %08lx\n", Status);
2745 goto end;
2746 }
2747 }
2748
2749 if (fileref->parent->fcb->subvol != related->fcb->subvol && (fileref->fcb->subvol == fileref->parent->fcb->subvol || fileref->fcb == Vcb->dummy_fcb)) {
2750 Status = move_across_subvols(fileref, ccb, related, &utf8, &fnus, Irp, &rollback);
2751 if (!NT_SUCCESS(Status)) {
2752 ERR("move_across_subvols returned %08lx\n", Status);
2753 }
2754 goto end;
2755 }
2756
2757 if (related == fileref->parent) { // keeping file in same directory
2758 UNICODE_STRING oldfn, newfn;
2759 USHORT name_offset;
2760 ULONG reqlen, oldutf8len;
2761
2762 oldfn.Length = oldfn.MaximumLength = 0;
2763
2764 Status = fileref_get_filename(fileref, &oldfn, &name_offset, &reqlen);
2766 ERR("fileref_get_filename returned %08lx\n", Status);
2767 goto end;
2768 }
2769
2771 if (!oldfn.Buffer) {
2772 ERR("out of memory\n");
2774 goto end;
2775 }
2776
2777 oldfn.MaximumLength = (uint16_t)reqlen;
2778
2779 Status = fileref_get_filename(fileref, &oldfn, &name_offset, &reqlen);
2780 if (!NT_SUCCESS(Status)) {
2781 ERR("fileref_get_filename returned %08lx\n", Status);
2782 ExFreePool(oldfn.Buffer);
2783 goto end;
2784 }
2785
2786 oldutf8len = fileref->dc->utf8.Length;
2787
2788 if (!fileref->created && !fileref->oldutf8.Buffer) {
2790 if (!fileref->oldutf8.Buffer) {
2791 ERR("out of memory\n");
2793 goto end;
2794 }
2795
2798 }
2799
2800 TRACE("renaming %.*S to %.*S\n", (int)(fileref->dc->name.Length / sizeof(WCHAR)), fileref->dc->name.Buffer, (int)(fnus.Length / sizeof(WCHAR)), fnus.Buffer);
2801
2803
2804 if (fileref->dc) {
2805 ExAcquireResourceExclusiveLite(&fileref->parent->fcb->nonpaged->dir_children_lock, true);
2806
2810
2812 if (!fileref->dc->utf8.Buffer) {
2813 ERR("out of memory\n");
2815 ExReleaseResourceLite(&fileref->parent->fcb->nonpaged->dir_children_lock);
2816 ExFreePool(oldfn.Buffer);
2817 goto end;
2818 }
2819
2822
2824 if (!fileref->dc->name.Buffer) {
2825 ERR("out of memory\n");
2827 ExReleaseResourceLite(&fileref->parent->fcb->nonpaged->dir_children_lock);
2828 ExFreePool(oldfn.Buffer);
2829 goto end;
2830 }
2831
2834
2836 if (!NT_SUCCESS(Status)) {
2837 ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
2838 ExReleaseResourceLite(&fileref->parent->fcb->nonpaged->dir_children_lock);
2839 ExFreePool(oldfn.Buffer);
2840 goto end;
2841 }
2842
2844
2847
2849
2850 ExReleaseResourceLite(&fileref->parent->fcb->nonpaged->dir_children_lock);
2851 }
2852
2853 newfn.Length = newfn.MaximumLength = 0;
2854
2855 Status = fileref_get_filename(fileref, &newfn, &name_offset, &reqlen);
2857 ERR("fileref_get_filename returned %08lx\n", Status);
2858 ExFreePool(oldfn.Buffer);
2859 goto end;
2860 }
2861
2863 if (!newfn.Buffer) {
2864 ERR("out of memory\n");
2866 ExFreePool(oldfn.Buffer);
2867 goto end;
2868 }
2869
2870 newfn.MaximumLength = (uint16_t)reqlen;
2871
2872 Status = fileref_get_filename(fileref, &newfn, &name_offset, &reqlen);
2873 if (!NT_SUCCESS(Status)) {
2874 ERR("fileref_get_filename returned %08lx\n", Status);
2875 ExFreePool(oldfn.Buffer);
2876 ExFreePool(newfn.Buffer);
2877 goto end;
2878 }
2879
2882
2883 if (fcb != Vcb->dummy_fcb && (fileref->parent->fcb->subvol == fcb->subvol || !is_subvol_readonly(fcb->subvol, Irp))) {
2884 fcb->inode_item.transid = Vcb->superblock.generation;
2886
2889
2890 fcb->inode_item_changed = true;
2892 }
2893
2894 // update parent's INODE_ITEM
2895
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;
2903
2904 related->fcb->inode_item_changed = true;
2905 mark_fcb_dirty(related->fcb);
2907
2908 FsRtlNotifyFilterReportChange(fcb->Vcb->NotifySync, &fcb->Vcb->DirNotifyList, (PSTRING)&oldfn, name_offset, NULL, NULL,
2910 FsRtlNotifyFilterReportChange(fcb->Vcb->NotifySync, &fcb->Vcb->DirNotifyList, (PSTRING)&newfn, name_offset, NULL, NULL,
2912
2913 ExFreePool(oldfn.Buffer);
2914 ExFreePool(newfn.Buffer);
2915
2917 goto end;
2918 }
2919
2920 // We move files by moving the existing fileref to the new directory, and
2921 // replacing it with a dummy fileref with the same original values, but marked as deleted.
2922
2924
2925 fr2 = create_fileref(Vcb);
2926
2927 fr2->fcb = fileref->fcb;
2928 fr2->fcb->refcount++;
2929
2930 fr2->oldutf8 = fileref->oldutf8;
2931 fr2->oldindex = fileref->dc->index;
2932 fr2->delete_on_close = fileref->delete_on_close;
2933 fr2->deleted = true;
2934 fr2->created = fileref->created;
2935 fr2->parent = fileref->parent;
2936 fr2->dc = NULL;
2937
2938 if (!fr2->oldutf8.Buffer) {
2939 fr2->oldutf8.Buffer = ExAllocatePoolWithTag(PagedPool, fileref->dc->utf8.Length, ALLOC_TAG);
2940 if (!fr2->oldutf8.Buffer) {
2941 ERR("out of memory\n");
2943 goto end;
2944 }
2945
2946 RtlCopyMemory(fr2->oldutf8.Buffer, fileref->dc->utf8.Buffer, fileref->dc->utf8.Length);
2947
2948 fr2->oldutf8.Length = fr2->oldutf8.MaximumLength = fileref->dc->utf8.Length;
2949 }
2950
2951 if (fr2->fcb->type == BTRFS_TYPE_DIRECTORY)
2952 fr2->fcb->fileref = fr2;
2953
2955 fileref->fcb->subvol->parent = related->fcb->subvol->id;
2956
2959 fileref->deleted = false;
2960 fileref->created = true;
2961 fileref->parent = related;
2962
2963 ExAcquireResourceExclusiveLite(&fileref->parent->fcb->nonpaged->dir_children_lock, true);
2964 InsertHeadList(&fileref->list_entry, &fr2->list_entry);
2966 ExReleaseResourceLite(&fileref->parent->fcb->nonpaged->dir_children_lock);
2967
2968 mark_fileref_dirty(fr2);
2970
2971 if (fileref->dc) {
2972 // remove from old parent
2973 ExAcquireResourceExclusiveLite(&fr2->parent->fcb->nonpaged->dir_children_lock, true);
2975 remove_dir_child_from_hash_lists(fr2->parent->fcb, fileref->dc);
2976 ExReleaseResourceLite(&fr2->parent->fcb->nonpaged->dir_children_lock);
2977
2978 if (fileref->dc->utf8.Length != utf8.Length || RtlCompareMemory(fileref->dc->utf8.Buffer, utf8.Buffer, utf8.Length) != utf8.Length) {
2979 // handle changed name
2980
2984
2986 if (!fileref->dc->utf8.Buffer) {
2987 ERR("out of memory\n");
2989 goto end;
2990 }
2991
2994
2996 if (!fileref->dc->name.Buffer) {
2997 ERR("out of memory\n");
2999 goto end;
3000 }
3001
3004
3006 if (!NT_SUCCESS(Status)) {
3007 ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
3008 goto end;
3009 }
3010
3013 }
3014
3015 // add to new parent
3016 ExAcquireResourceExclusiveLite(&related->fcb->nonpaged->dir_children_lock, true);
3017
3018 if (IsListEmpty(&related->fcb->dir_children_index))
3019 fileref->dc->index = 2;
3020 else {
3021 dir_child* dc2 = CONTAINING_RECORD(related->fcb->dir_children_index.Blink, dir_child, list_entry_index);
3022
3023 fileref->dc->index = max(2, dc2->index + 1);
3024 }
3025
3026 InsertTailList(&related->fcb->dir_children_index, &fileref->dc->list_entry_index);
3028 ExReleaseResourceLite(&related->fcb->nonpaged->dir_children_lock);
3029 }
3030
3031 ExAcquireResourceExclusiveLite(&related->fcb->nonpaged->dir_children_lock, true);
3032 InsertTailList(&related->children, &fileref->list_entry);
3033 ExReleaseResourceLite(&related->fcb->nonpaged->dir_children_lock);
3034
3035 if (fcb->inode_item.st_nlink > 1) {
3036 // add new hardlink entry to fcb
3037
3039 if (!hl) {
3040 ERR("out of memory\n");
3042 goto end;
3043 }
3044
3045 hl->parent = related->fcb->inode;
3046 hl->index = fileref->dc->index;
3047
3048 hl->name.Length = hl->name.MaximumLength = fnus.Length;
3050
3051 if (!hl->name.Buffer) {
3052 ERR("out of memory\n");
3053 ExFreePool(hl);
3055 goto end;
3056 }
3057
3058 RtlCopyMemory(hl->name.Buffer, fnus.Buffer, fnus.Length);
3059
3062
3063 if (!hl->utf8.Buffer) {
3064 ERR("out of memory\n");
3065 ExFreePool(hl->name.Buffer);
3066 ExFreePool(hl);
3068 goto end;
3069 }
3070
3072
3074 }
3075
3076 // delete old hardlink entry from fcb
3077
3078 le = fcb->hardlinks.Flink;
3079 while (le != &fcb->hardlinks) {
3081
3082 if (hl->parent == fr2->parent->fcb->inode && hl->index == fr2->oldindex) {
3084
3085 if (hl->utf8.Buffer)
3086 ExFreePool(hl->utf8.Buffer);
3087
3088 if (hl->name.Buffer)
3089 ExFreePool(hl->name.Buffer);
3090
3091 ExFreePool(hl);
3092 break;
3093 }
3094
3095 le = le->Flink;
3096 }
3097
3098 // update inode's INODE_ITEM
3099
3102
3103 if (fcb != Vcb->dummy_fcb && (fileref->parent->fcb->subvol == fcb->subvol || !is_subvol_readonly(fcb->subvol, Irp))) {
3104 fcb->inode_item.transid = Vcb->superblock.generation;
3106
3109
3110 fcb->inode_item_changed = true;
3112 }
3113
3114 // update new parent's INODE_ITEM
3115
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;
3123
3124 related->fcb->inode_item_changed = true;
3125 mark_fcb_dirty(related->fcb);
3126
3127 // update old parent's INODE_ITEM
3128
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;
3136
3137 free_fileref(fr2);
3138
3139 fr2->parent->fcb->inode_item_changed = true;
3140 mark_fcb_dirty(fr2->parent->fcb);
3141
3145
3147
3148end:
3149 if (oldfileref)
3150 free_fileref(oldfileref);
3151
3152 if (!NT_SUCCESS(Status) && related)
3153 free_fileref(related);
3154
3155 if (!NT_SUCCESS(Status) && fr2)
3156 free_fileref(fr2);
3157
3158 if (NT_SUCCESS(Status))
3160 else
3162
3163 ExReleaseResourceLite(fcb->Header.Resource);
3164 ExReleaseResourceLite(&Vcb->fileref_lock);
3165 ExReleaseResourceLite(&Vcb->tree_lock);
3166
3167 return Status;
3168}
3169
3173
3174 TRACE("setting new end to %x bytes (currently %x)\n", end, fcb->adsdata.Length);
3175
3176 if (!fileref || !fileref->parent) {
3177 ERR("no fileref for stream\n");
3178 return STATUS_INTERNAL_ERROR;
3179 }
3180
3181 if (end < fcb->adsdata.Length) {
3182 if (advance_only)
3183 return STATUS_SUCCESS;
3184
3185 TRACE("truncating stream to %x bytes\n", end);
3186
3187 fcb->adsdata.Length = end;
3188 } else if (end > fcb->adsdata.Length) {
3189 TRACE("extending stream to %x bytes\n", end);
3190
3191 if (end > fcb->adsmaxlen) {
3192 ERR("error - xattr too long (%u > %lu)\n", end, fcb->adsmaxlen);
3193 return STATUS_DISK_FULL;
3194 }
3195
3196 if (end > fcb->adsdata.MaximumLength) {
3198 if (!data) {
3199 ERR("out of memory\n");
3202 }
3203
3204 if (fcb->adsdata.Buffer) {
3207 }
3208
3211 }
3212
3214
3215 fcb->adsdata.Length = end;
3216 }
3217
3219
3220 fcb->Header.AllocationSize.QuadPart = end;
3221 fcb->Header.FileSize.QuadPart = end;
3222 fcb->Header.ValidDataLength.QuadPart = end;
3223
3226
3227 fileref->parent->fcb->inode_item.transid = Vcb->superblock.generation;
3228 fileref->parent->fcb->inode_item.sequence++;
3229 fileref->parent->fcb->inode_item.st_ctime = now;
3230
3231 fileref->parent->fcb->inode_item_changed = true;
3233
3234 fileref->parent->fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
3235 fileref->parent->fcb->subvol->root_item.ctime = now;
3236
3237 return STATUS_SUCCESS;
3238}
3239
3241 FILE_END_OF_FILE_INFORMATION* feofi = Irp->AssociatedIrp.SystemBuffer;
3242 fcb* fcb = FileObject->FsContext;
3243 ccb* ccb = FileObject->FsContext2;
3247 CC_FILE_SIZES ccfs;
3249 bool set_size = false;
3250 ULONG filter;
3251 uint64_t new_end_of_file;
3252
3253 if (!fileref) {
3254 ERR("fileref is NULL\n");
3256 }
3257
3259
3260 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
3261
3262 ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
3263
3264 if (fileref ? fileref->deleted : fcb->deleted) {
3266 goto end;
3267 }
3268
3269 if (fcb->ads) {
3270 if (feofi->EndOfFile.QuadPart > 0xffff) {
3272 goto end;
3273 }
3274
3275 if (feofi->EndOfFile.QuadPart < 0) {
3277 goto end;
3278 }
3279
3281
3282 if (NT_SUCCESS(Status)) {
3283 ccfs.AllocationSize = fcb->Header.AllocationSize;
3284 ccfs.FileSize = fcb->Header.FileSize;
3285 ccfs.ValidDataLength = fcb->Header.ValidDataLength;
3286 set_size = true;
3287 }
3288
3290
3291 if (!ccb->user_set_write_time) {
3293 win_time_to_unix(time, &fileref->parent->fcb->inode_item.st_mtime);
3295
3296 fileref->parent->fcb->inode_item_changed = true;
3298 }
3299
3301
3302 goto end;
3303 }
3304
3305 TRACE("file: %p\n", FileObject);
3306 TRACE("paging IO: %s\n", Irp->Flags & IRP_PAGING_IO ? "true" : "false");
3307 TRACE("FileObject: AllocationSize = %I64x, FileSize = %I64x, ValidDataLength = %I64x\n",
3308 fcb->Header.AllocationSize.QuadPart, fcb->Header.FileSize.QuadPart, fcb->Header.ValidDataLength.QuadPart);
3309
3310 new_end_of_file = feofi->EndOfFile.QuadPart;
3311
3312 /* The lazy writer sometimes tries to round files to the next page size through CcSetValidData -
3313 * ignore these. See fastfat!FatSetEndOfFileInfo, where Microsoft does the same as we're
3314 * doing below. */
3315 if (advance_only && new_end_of_file >= (uint64_t)fcb->Header.FileSize.QuadPart)
3316 new_end_of_file = fcb->Header.FileSize.QuadPart;
3317
3318 TRACE("setting new end to %I64x bytes (currently %I64x)\n", new_end_of_file, fcb->inode_item.st_size);
3319
3320 if (new_end_of_file < fcb->inode_item.st_size) {
3321 if (advance_only) {
3323 goto end;
3324 }
3325
3326 TRACE("truncating file to %I64x bytes\n", new_end_of_file);
3327
3328 if (!MmCanFileBeTruncated(&fcb->nonpaged->segment_object, &feofi->EndOfFile)) {
3330 goto end;
3331 }
3332
3333 Status = truncate_file(fcb, new_end_of_file, Irp, &rollback);
3334 if (!NT_SUCCESS(Status)) {
3335 ERR("error - truncate_file failed\n");
3336 goto end;
3337 }
3338 } else if (new_end_of_file > fcb->inode_item.st_size) {
3339 TRACE("extending file to %I64x bytes\n", new_end_of_file);
3340
3341 Status = extend_file(fcb, fileref, new_end_of_file, prealloc, NULL, &rollback);
3342 if (!NT_SUCCESS(Status)) {
3343 ERR("error - extend_file failed\n");
3344 goto end;
3345 }
3346 } else if (new_end_of_file == fcb->inode_item.st_size && advance_only) {
3348 goto end;
3349 }
3350
3351 ccfs.AllocationSize = fcb->Header.AllocationSize;
3352 ccfs.FileSize = fcb->Header.FileSize;
3353 ccfs.ValidDataLength = fcb->Header.ValidDataLength;
3354 set_size = true;
3355
3357
3358 if (!ccb->user_set_write_time) {
3362 }
3363
3364 fcb->inode_item_changed = true;
3367
3369
3370end:
3371 if (NT_SUCCESS(Status))
3373 else
3375
3376 ExReleaseResourceLite(fcb->Header.Resource);
3377
3378 if (set_size) {
3379 _SEH2_TRY {
3380 CcSetFileSizes(FileObject, &ccfs);
3383 } _SEH2_END;
3384
3385 if (!NT_SUCCESS(Status))
3386 ERR("CcSetFileSizes threw exception %08lx\n", Status);
3387 }
3388
3389 ExReleaseResourceLite(&Vcb->tree_lock);
3390
3391 return Status;
3392}
3393
3395 FILE_POSITION_INFORMATION* fpi = (FILE_POSITION_INFORMATION*)Irp->AssociatedIrp.SystemBuffer;
3396
3397 TRACE("setting the position on %p to %I64x\n", FileObject, fpi->CurrentByteOffset.QuadPart);
3398
3399 // FIXME - make sure aligned for FO_NO_INTERMEDIATE_BUFFERING
3400
3401 FileObject->CurrentByteOffset = fpi->CurrentByteOffset;
3402
3403 return STATUS_SUCCESS;
3404}
3405
3407 FILE_LINK_INFORMATION_EX* fli = Irp->AssociatedIrp.SystemBuffer;
3408 fcb *fcb = FileObject->FsContext, *tfofcb, *parfcb;
3409 ccb* ccb = FileObject->FsContext2;
3410 file_ref *fileref = ccb ? ccb->fileref : NULL, *oldfileref = NULL, *related = NULL, *fr2 = NULL;
3411 WCHAR* fn;
3412 ULONG fnlen, utf8len;
3413 UNICODE_STRING fnus;
3414 ANSI_STRING utf8;
3419 hardlink* hl;
3421 SECURITY_SUBJECT_CONTEXT subjcont;
3422 dir_child* dc = NULL;
3423 ULONG flags;
3424
3426
3427 // FIXME - check fli length
3428 // FIXME - don't ignore fli->RootDirectory
3429
3430 if (ex)
3431 flags = fli->Flags;
3432 else
3434
3435 TRACE("flags = %lx\n", flags);
3436 TRACE("RootDirectory = %p\n", fli->RootDirectory);
3437 TRACE("FileNameLength = %lx\n", fli->FileNameLength);
3438 TRACE("FileName = %.*S\n", (int)(fli->FileNameLength / sizeof(WCHAR)), fli->FileName);
3439
3440 fn = fli->FileName;
3441 fnlen = fli->FileNameLength / sizeof(WCHAR);
3442
3443 if (!tfo) {
3444 if (!fileref || !fileref->parent) {
3445 ERR("no fileref set and no directory given\n");
3447 }
3448
3449 parfcb = fileref->parent->fcb;
3450 tfofcb = NULL;
3451 } else {
3452 LONG i;
3453
3454 tfofcb = tfo->FsContext;
3455 parfcb = tfofcb;
3456
3457 while (fnlen > 0 && (fli->FileName[fnlen - 1] == '/' || fli->FileName[fnlen - 1] == '\\')) {
3458 fnlen--;
3459 }
3460
3461 if (fnlen == 0)
3463
3464 for (i = fnlen - 1; i >= 0; i--) {
3465 if (fli->FileName[i] == '\\' || fli->FileName[i] == '/') {
3466 fn = &fli->FileName[i+1];
3467 fnlen = (fli->FileNameLength / sizeof(WCHAR)) - i - 1;
3468 break;
3469 }
3470 }
3471 }
3472
3473 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
3474 ExAcquireResourceExclusiveLite(&Vcb->fileref_lock, true);
3475 ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
3476
3477 if (fcb->type == BTRFS_TYPE_DIRECTORY) {
3478 WARN("tried to create hard link on directory\n");
3480 goto end;
3481 }
3482
3483 if (fcb->ads) {
3484 WARN("tried to create hard link on stream\n");
3486 goto end;
3487 }
3488
3489 if (fcb->inode_item.st_nlink >= 65535) {
3491 goto end;
3492 }
3493
3494 fnus.Buffer = fn;
3495 fnus.Length = fnus.MaximumLength = (uint16_t)(fnlen * sizeof(WCHAR));
3496
3497 TRACE("fnus = %.*S\n", (int)(fnus.Length / sizeof(WCHAR)), fnus.Buffer);
3498
3499 Status = check_file_name_valid(&fnus, false, false);
3500 if (!NT_SUCCESS(Status))
3501 goto end;
3502
3503 Status = utf16_to_utf8(NULL, 0, &utf8len, fn, (ULONG)fnlen * sizeof(WCHAR));
3504 if (!NT_SUCCESS(Status))
3505 goto end;
3506
3507 utf8.MaximumLength = utf8.Length = (uint16_t)utf8len;
3509 if (!utf8.Buffer) {
3510 ERR("out of memory\n");
3512 goto end;
3513 }
3514
3515 Status = utf16_to_utf8(utf8.Buffer, utf8len, &utf8len, fn, (ULONG)fnlen * sizeof(WCHAR));
3516 if (!NT_SUCCESS(Status))
3517 goto end;
3518
3519 if (tfo && tfo->FsContext2) {
3520 struct _ccb* relatedccb = tfo->FsContext2;
3521
3522 related = relatedccb->fileref;
3524 }
3525
3526 Status = open_fileref(Vcb, &oldfileref, &fnus, related, false, NULL, NULL, PagedPool, ccb->case_sensitive, Irp);
3527
3528 if (NT_SUCCESS(Status)) {
3529 if (!oldfileref->deleted) {
3530 WARN("destination file already exists\n");
3531
3534 goto end;
3535 } else if (fileref == oldfileref) {
3537 goto end;
3538 } else if (!(flags & FILE_LINK_POSIX_SEMANTICS) && (oldfileref->open_count > 0 || has_open_children(oldfileref)) && !oldfileref->deleted) {
3539 WARN("trying to overwrite open file\n");
3541 goto end;
3542 } else if (!(flags & FILE_LINK_IGNORE_READONLY_ATTRIBUTE) && oldfileref->fcb->atts & FILE_ATTRIBUTE_READONLY) {
3543 WARN("trying to overwrite readonly file\n");
3545 goto end;
3546 } else if (oldfileref->fcb->type == BTRFS_TYPE_DIRECTORY) {
3547 WARN("trying to overwrite directory\n");
3549 goto end;
3550 }
3551 } else {
3552 free_fileref(oldfileref);
3553 oldfileref = NULL;
3554 }
3555 }
3556
3557 if (!related) {
3558 Status = open_fileref(Vcb, &related, &fnus, NULL, true, NULL, NULL, PagedPool, ccb->case_sensitive, Irp);
3559
3560 if (!NT_SUCCESS(Status)) {
3561 ERR("open_fileref returned %08lx\n", Status);
3562 goto end;
3563 }
3564 }
3565
3566 SeCaptureSubjectContext(&subjcont);
3567
3568 if (!SeAccessCheck(related->fcb->sd, &subjcont, false, FILE_ADD_FILE, 0, NULL,
3569 IoGetFileObjectGenericMapping(), Irp->RequestorMode, &access, &Status)) {
3570 SeReleaseSubjectContext(&subjcont);
3571 TRACE("SeAccessCheck failed, returning %08lx\n", Status);
3572 goto end;
3573 }
3574
3575 SeReleaseSubjectContext(&subjcont);
3576
3577 if (fcb->subvol != parfcb->subvol) {
3578 WARN("can't create hard link over subvolume boundary\n");
3580 goto end;
3581 }
3582
3583 if (oldfileref) {
3584 SeCaptureSubjectContext(&subjcont);
3585
3586 if (!SeAccessCheck(oldfileref->fcb->sd, &subjcont, false, DELETE, 0, NULL,
3587 IoGetFileObjectGenericMapping(), Irp->RequestorMode, &access, &Status)) {
3588 SeReleaseSubjectContext(&subjcont);
3589 TRACE("SeAccessCheck failed, returning %08lx\n", Status);
3590 goto end;
3591 }
3592
3593 SeReleaseSubjectContext(&subjcont);
3594
3595 if (oldfileref->open_count > 0 && flags & FILE_RENAME_POSIX_SEMANTICS) {
3596 oldfileref->delete_on_close = true;
3597 oldfileref->posix_delete = true;
3598 }
3599
3600 Status = delete_fileref(oldfileref, NULL, oldfileref->open_count > 0 && flags & FILE_RENAME_POSIX_SEMANTICS, Irp, &rollback);
3601 if (!NT_SUCCESS(Status)) {
3602 ERR("delete_fileref returned %08lx\n", Status);
3603 goto end;
3604 }
3605 }
3606
3607 fr2 = create_fileref(Vcb);
3608
3609 fr2->fcb = fcb;
3610 fcb->refcount++;
3611
3612 fr2->created = true;
3613 fr2->parent = related;
3614
3615 Status = add_dir_child(related->fcb, fcb->inode, false, &utf8, &fnus, fcb->type, &dc);
3616 if (!NT_SUCCESS(Status))
3617 WARN("add_dir_child returned %08lx\n", Status);
3618
3619 fr2->dc = dc;
3620 dc->fileref = fr2;
3621
3622 ExAcquireResourceExclusiveLite(&related->fcb->nonpaged->dir_children_lock, true);
3623 InsertTailList(&related->children, &fr2->list_entry);
3624 ExReleaseResourceLite(&related->fcb->nonpaged->dir_children_lock);
3625
3626 // add hardlink for existing fileref, if it's not there already
3627 if (IsListEmpty(&fcb->hardlinks)) {
3629 if (!hl) {
3630 ERR("out of memory\n");
3632 goto end;
3633 }
3634
3635 hl->parent = fileref->parent->fcb->inode;
3636 hl->index = fileref->dc->index;
3637
3638 hl->name.Length = hl->name.MaximumLength = fnus.Length;
3640
3641 if (!hl->name.Buffer) {
3642 ERR("out of memory\n");
3643 ExFreePool(hl);
3645 goto end;
3646 }
3647
3648 RtlCopyMemory(hl->name.Buffer, fnus.Buffer, fnus.Length);
3649
3652
3653 if (!hl->utf8.Buffer) {
3654 ERR("out of memory\n");
3655 ExFreePool(hl->name.Buffer);
3656 ExFreePool(hl);
3658 goto end;
3659 }
3660
3662
3664 }
3665
3667 if (!hl) {
3668 ERR("out of memory\n");
3670 goto end;
3671 }
3672
3673 hl->parent = related->fcb->inode;
3674 hl->index = dc->index;
3675
3676 hl->name.Length = hl->name.MaximumLength = fnus.Length;
3678
3679 if (!hl->name.Buffer) {
3680 ERR("out of memory\n");
3681 ExFreePool(hl);
3683 goto end;
3684 }
3685
3686 RtlCopyMemory(hl->name.Buffer, fnus.Buffer, fnus.Length);
3687
3688 hl->utf8.Length = hl->utf8.MaximumLength = utf8.Length;
3690
3691 if (!hl->utf8.Buffer) {
3692 ERR("out of memory\n");
3693 ExFreePool(hl->name.Buffer);
3694 ExFreePool(hl);
3696 goto end;
3697 }
3698
3699 RtlCopyMemory(hl->utf8.Buffer, utf8.Buffer, utf8.Length);
3700 ExFreePool(utf8.Buffer);
3701
3703
3704 mark_fileref_dirty(fr2);
3705 free_fileref(fr2);
3706
3707 // update inode's INODE_ITEM
3708
3711
3712 fcb->inode_item.transid = Vcb->superblock.generation;
3715
3718
3719 fcb->inode_item_changed = true;
3721
3722 // update parent's INODE_ITEM
3723
3724 parfcb->inode_item.transid = Vcb->superblock.generation;
3725 TRACE("parfcb->inode_item.st_size (inode %I64x) was %I64x\n", parfcb->inode, parfcb->inode_item.st_size);
3726 parfcb->inode_item.st_size += 2 * utf8len;
3727 TRACE("parfcb->inode_item.st_size (inode %I64x) now %I64x\n", parfcb->inode, parfcb->inode_item.st_size);
3728 parfcb->inode_item.sequence++;
3729 parfcb->inode_item.st_ctime = now;
3730
3731 parfcb->inode_item_changed = true;
3732 mark_fcb_dirty(parfcb);
3733
3735
3737
3738end:
3739 if (oldfileref)
3740 free_fileref(oldfileref);
3741
3742 if (!NT_SUCCESS(Status) && related)
3743 free_fileref(related);
3744
3745 if (!NT_SUCCESS(Status) && fr2)
3746 free_fileref(fr2);
3747
3748 if (NT_SUCCESS(Status))
3750 else
3752
3753 ExReleaseResourceLite(fcb->Header.Resource);
3754 ExReleaseResourceLite(&Vcb->fileref_lock);
3755 ExReleaseResourceLite(&Vcb->tree_lock);
3756
3757 return Status;
3758}
3759
3761 FILE_VALID_DATA_LENGTH_INFORMATION* fvdli = Irp->AssociatedIrp.SystemBuffer;
3763 fcb* fcb = FileObject->FsContext;
3764 ccb* ccb = FileObject->FsContext2;
3768 CC_FILE_SIZES ccfs;
3770 bool set_size = false;
3771 ULONG filter;
3772
3773 if (IrpSp->Parameters.SetFile.Length < sizeof(FILE_VALID_DATA_LENGTH_INFORMATION)) {
3774 ERR("input buffer length was %lu, expected %Iu\n", IrpSp->Parameters.SetFile.Length, sizeof(FILE_VALID_DATA_LENGTH_INFORMATION));
3776 }
3777
3778 if (!fileref) {
3779 ERR("fileref is NULL\n");
3781 }
3782
3784
3785 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
3786
3787 ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
3788
3791 goto end;
3792 }
3793
3794 if (fvdli->ValidDataLength.QuadPart <= fcb->Header.ValidDataLength.QuadPart || fvdli->ValidDataLength.QuadPart > fcb->Header.FileSize.QuadPart) {
3795 TRACE("invalid VDL of %I64u (current VDL = %I64u, file size = %I64u)\n", fvdli->ValidDataLength.QuadPart,
3796 fcb->Header.ValidDataLength.QuadPart, fcb->Header.FileSize.QuadPart);
3798 goto end;
3799 }
3800
3801 if (fileref ? fileref->deleted : fcb->deleted) {
3803 goto end;
3804 }
3805
3806 // This function doesn't really do anything - the fsctl can only increase the value of ValidDataLength,
3807 // and we set it to the max anyway.
3808
3809 ccfs.AllocationSize = fcb->Header.AllocationSize;
3810 ccfs.FileSize = fcb->Header.FileSize;
3811 ccfs.ValidDataLength = fvdli->ValidDataLength;
3812 set_size = true;
3813
3815
3816 if (!ccb->user_set_write_time) {
3820 }
3821
3822 fcb->inode_item_changed = true;
3824
3826
3828
3829end:
3830 if (NT_SUCCESS(Status))
3832 else
3834
3835 ExReleaseResourceLite(fcb->Header.Resource);
3836
3837 if (set_size) {
3838 _SEH2_TRY {
3839 CcSetFileSizes(FileObject, &ccfs);
3842 } _SEH2_END;
3843
3844 if (!NT_SUCCESS(Status))
3845 ERR("CcSetFileSizes threw exception %08lx\n", Status);
3846 else
3847 fcb->Header.AllocationSize = ccfs.AllocationSize;
3848 }
3849
3850 ExReleaseResourceLite(&Vcb->tree_lock);
3851
3852 return Status;
3853}
3854
3855#ifndef __REACTOS__
3857 FILE_CASE_SENSITIVE_INFORMATION* fcsi = (FILE_CASE_SENSITIVE_INFORMATION*)Irp->AssociatedIrp.SystemBuffer;
3859
3860 if (IrpSp->Parameters.FileSystemControl.InputBufferLength < sizeof(FILE_CASE_SENSITIVE_INFORMATION))
3862
3864
3865 if (!FileObject)
3867
3868 fcb* fcb = FileObject->FsContext;
3869
3870 if (!fcb)
3872
3873 if (!(fcb->atts & FILE_ATTRIBUTE_DIRECTORY)) {
3874 WARN("cannot set case-sensitive flag on anything other than directory\n");
3876 }
3877
3878 ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, true);
3879
3882
3883 ExReleaseResourceLite(&fcb->Vcb->tree_lock);
3884
3885 return STATUS_SUCCESS;
3886}
3887#endif
3888
3891NTSTATUS __stdcall drv_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
3894 device_extension* Vcb = DeviceObject->DeviceExtension;
3895 fcb* fcb = IrpSp->FileObject->FsContext;
3896 ccb* ccb = IrpSp->FileObject->FsContext2;
3897 bool top_level;
3898
3900
3901 top_level = is_top_level(Irp);
3902
3903 Irp->IoStatus.Information = 0;
3904
3905 if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
3907 goto end;
3908 } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
3910 goto end;
3911 }
3912
3913 if (!(Vcb->Vpb->Flags & VPB_MOUNTED)) {
3915 goto end;
3916 }
3917
3918 if (Vcb->readonly && IrpSp->Parameters.SetFile.FileInformationClass != FilePositionInformation) {
3920 goto end;
3921 }
3922
3923 if (!fcb) {
3924 ERR("no fcb\n");
3926 goto end;
3927 }
3928
3929 if (!ccb) {
3930 ERR("no ccb\n");
3932 goto end;
3933 }
3934
3935 if (fcb != Vcb->dummy_fcb && is_subvol_readonly(fcb->subvol, Irp) && IrpSp->Parameters.SetFile.FileInformationClass != FilePositionInformation &&
3936#ifndef __REACTOS__
3937 (fcb->inode != SUBVOL_ROOT_INODE || (IrpSp->Parameters.SetFile.FileInformationClass != FileBasicInformation && IrpSp->Parameters.SetFile.FileInformationClass != FileRenameInformation && IrpSp->Parameters.SetFile.FileInformationClass != FileRenameInformationEx))) {
3938#else
3939 (fcb->inode != SUBVOL_ROOT_INODE || (IrpSp->Parameters.SetFile.FileInformationClass != FileBasicInformation && IrpSp->Parameters.SetFile.FileInformationClass != FileRenameInformation))) {
3940#endif
3942 goto end;
3943 }
3944
3946
3947 TRACE("set information\n");
3948
3950
3951 switch (IrpSp->Parameters.SetFile.FileInformationClass) {
3953 {
3954 TRACE("FileAllocationInformation\n");
3955
3956 if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_WRITE_DATA)) {
3957 WARN("insufficient privileges\n");
3959 break;
3960 }
3961
3963 break;
3964 }
3965
3967 {
3968 TRACE("FileBasicInformation\n");
3969
3970 if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_WRITE_ATTRIBUTES)) {
3971 WARN("insufficient privileges\n");
3973 break;
3974 }
3975
3977
3978 break;
3979 }
3980
3982 {
3983 TRACE("FileDispositionInformation\n");
3984
3985 if (Irp->RequestorMode == UserMode && !(ccb->access & DELETE)) {
3986 WARN("insufficient privileges\n");
3988 break;
3989 }
3990
3992
3993 break;
3994 }
3995
3997 {
3998 TRACE("FileEndOfFileInformation\n");
3999
4000 if (Irp->RequestorMode == UserMode && !(ccb->access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
4001 WARN("insufficient privileges\n");
4003 break;
4004 }
4005
4006 Status = set_end_of_file_information(Vcb, Irp, IrpSp->FileObject, IrpSp->Parameters.SetFile.AdvanceOnly, false);
4007
4008 break;
4009 }
4010
4012 TRACE("FileLinkInformation\n");
4013 Status = set_link_information(Vcb, Irp, IrpSp->FileObject, IrpSp->Parameters.SetFile.FileObject, false);
4014 break;
4015
4017 TRACE("FilePositionInformation\n");
4019 break;
4020
4022 TRACE("FileRenameInformation\n");
4023 Status = set_rename_information(Vcb, Irp, IrpSp->FileObject, IrpSp->Parameters.SetFile.FileObject, false);
4024 break;
4025
4027 {
4028 TRACE("FileValidDataLengthInformation\n");
4029
4030 if (Irp->RequestorMode == UserMode && !(ccb->access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
4031 WARN("insufficient privileges\n");
4033 break;
4034 }
4035
4037
4038 break;
4039 }
4040
4041#ifndef __REACTOS__
4042#ifndef _MSC_VER
4043#pragma GCC diagnostic push
4044#pragma GCC diagnostic ignored "-Wswitch"
4045#endif
4047 {
4048 TRACE("FileDispositionInformationEx\n");
4049
4050 if (Irp->RequestorMode == UserMode && !(ccb->access & DELETE)) {
4051 WARN("insufficient privileges\n");
4053 break;
4054 }
4055
4057
4058 break;
4059 }
4060
4062 TRACE("FileRenameInformationEx\n");
4063 Status = set_rename_information(Vcb, Irp, IrpSp->FileObject, IrpSp->Parameters.SetFile.FileObject, true);
4064 break;
4065
4067 TRACE("FileLinkInformationEx\n");
4068 Status = set_link_information(Vcb, Irp, IrpSp->FileObject, IrpSp->Parameters.SetFile.FileObject, true);
4069 break;
4070
4072 TRACE("FileCaseSensitiveInformation\n");
4073
4074 if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_WRITE_ATTRIBUTES)) {
4075 WARN("insufficient privileges\n");
4077 break;
4078 }
4079
4081 break;
4082
4084 WARN("unimplemented FileInformationClass FileStorageReserveIdInformation\n");
4085 break;
4086
4087#ifndef _MSC_VER
4088#pragma GCC diagnostic pop
4089#endif
4090#endif
4091
4092 default:
4093 WARN("unknown FileInformationClass %u\n", IrpSp->Parameters.SetFile.FileInformationClass);
4094 }
4095
4096end:
4097 Irp->IoStatus.Status = Status;
4098
4099 TRACE("returning %08lx\n", Status);
4100
4102
4103 if (top_level)
4105
4107
4108 return Status;
4109}
4110
4113
4114 *length -= sizeof(FILE_BASIC_INFORMATION);
4115
4116 if (fcb == fcb->Vcb->dummy_fcb) {
4118
4120 fbi->CreationTime = fbi->LastAccessTime = fbi->LastWriteTime = fbi->ChangeTime = time;
4121 } else {
4126 }
4127
4128 if (fcb->ads) {
4129 if (!fileref || !fileref->parent) {
4130 ERR("no fileref for stream\n");
4131 return STATUS_INTERNAL_ERROR;
4132 } else
4133 fbi->FileAttributes = fileref->parent->fcb->atts == 0 ? FILE_ATTRIBUTE_NORMAL : fileref->parent->fcb->atts;
4134 } else
4136
4137 return STATUS_SUCCESS;
4138}
4139
4141 INODE_ITEM* ii;
4142
4143 if (*length < (LONG)sizeof(FILE_NETWORK_OPEN_INFORMATION)) {
4144 WARN("overflow\n");
4146 }
4147
4149
4151
4152 if (fcb->ads) {
4153 if (!fileref || !fileref->parent) {
4154 ERR("no fileref for stream\n");
4155 return STATUS_INTERNAL_ERROR;
4156 }
4157
4158 ii = &fileref->parent->fcb->inode_item;
4159 } else
4160 ii = &fcb->inode_item;
4161
4162 if (fcb == fcb->Vcb->dummy_fcb) {
4164
4166 fnoi->CreationTime = fnoi->LastAccessTime = fnoi->LastWriteTime = fnoi->ChangeTime = time;
4167 } else {
4172 }
4173
4174 if (fcb->ads) {
4176 fnoi->FileAttributes = fileref->parent->fcb->atts == 0 ? FILE_ATTRIBUTE_NORMAL : fileref->parent->fcb->atts;
4177 } else {
4181 }
4182
4183 return STATUS_SUCCESS;
4184}
4185
4188
4190
4191 if (fcb->ads) {
4192 if (!fileref || !fileref->parent) {
4193 ERR("no fileref for stream\n");
4194 return STATUS_INTERNAL_ERROR;
4195 }
4196
4198 fsi->NumberOfLinks = fileref->parent->fcb->inode_item.st_nlink;
4199 fsi->Directory = false;
4200 } else {
4205 }
4206
4207 TRACE("length = %I64u\n", fsi->EndOfFile.QuadPart);
4208
4209 fsi->DeletePending = fileref ? fileref->delete_on_close : false;
4210
4211 return STATUS_SUCCESS;
4212}
4213
4216
4218
4219 return STATUS_SUCCESS;
4220}
4221
4223 *length -= sizeof(FILE_EA_INFORMATION);
4224
4225 /* This value appears to be the size of the structure NTFS stores on disk, and not,
4226 * as might be expected, the size of FILE_FULL_EA_INFORMATION (which is what we store).
4227 * The formula is 4 bytes as a header, followed by 5 + NameLength + ValueLength for each
4228 * item. */
4229
4230 eai->EaSize = fcb->ealen;
4231
4232 return STATUS_SUCCESS;
4233}
4234
4237
4239
4240 fpi->CurrentByteOffset = FileObject->CurrentByteOffset;
4241
4242 return STATUS_SUCCESS;
4243}
4244
4246 file_ref* fr;
4248 ULONG reqlen = 0;
4249 USHORT offset;
4250 bool overflow = false;
4251
4252 // FIXME - we need a lock on filerefs' filepart
4253
4254 if (fileref == fileref->fcb->Vcb->root_fileref) {
4255 if (fn->MaximumLength >= sizeof(WCHAR)) {
4256 fn->Buffer[0] = '\\';
4257 fn->Length = sizeof(WCHAR);
4258
4259 if (name_offset)
4260 *name_offset = 0;
4261
4262 return STATUS_SUCCESS;
4263 } else {
4264 if (preqlen)
4265 *preqlen = sizeof(WCHAR);
4266 fn->Length = 0;
4267
4269 }
4270 }
4271
4272 fr = fileref;
4273 offset = 0;
4274
4275 while (fr->parent) {
4276 USHORT movelen;
4277
4278 if (!fr->dc)
4279 return STATUS_INTERNAL_ERROR;
4280
4281 if (!overflow) {
4282 if (fr->dc->name.Length + sizeof(WCHAR) + fn->Length > fn->MaximumLength)
4283 overflow = true;
4284 }
4285
4286 if (overflow)
4287 movelen = fn->MaximumLength - fr->dc->name.Length - sizeof(WCHAR);
4288 else
4289 movelen = fn->Length;
4290
4291 if ((!overflow || fn->MaximumLength > fr->dc->name.Length + sizeof(WCHAR)) && movelen > 0) {
4292 RtlMoveMemory(&fn->Buffer[(fr->dc->name.Length / sizeof(WCHAR)) + 1], fn->Buffer, movelen);
4293 offset += fr->dc->name.Length + sizeof(WCHAR);
4294 }
4295
4296 if (fn->MaximumLength >= sizeof(WCHAR)) {
4297 fn->Buffer[0] = fr->fcb->ads ? ':' : '\\';
4298 fn->Length += sizeof(WCHAR);
4299
4300 if (fn->MaximumLength > sizeof(WCHAR)) {
4301 RtlCopyMemory(&fn->Buffer[1], fr->dc->name.Buffer, min(fr->dc->name.Length, fn->MaximumLength - sizeof(WCHAR)));
4302 fn->Length += fr->dc->name.Length;
4303 }
4304
4305 if (fn->Length > fn->MaximumLength) {
4306 fn->Length = fn->MaximumLength;
4307 overflow = true;
4308 }
4309 }
4310
4311 reqlen += sizeof(WCHAR) + fr->dc->name.Length;
4312
4313 fr = fr->parent;
4314 }
4315
4316 offset += sizeof(WCHAR);
4317
4318 if (overflow) {
4319 if (preqlen)
4320 *preqlen = reqlen;
4322 } else {
4323 if (name_offset)
4324 *name_offset = offset;
4325
4327 }
4328
4329 return Status;
4330}
4331
4333 ULONG reqlen;
4336 static const WCHAR datasuf[] = {':','$','D','A','T','A',0};
4337 uint16_t datasuflen = sizeof(datasuf) - sizeof(WCHAR);
4338
4339 if (!fileref) {
4340 ERR("called without fileref\n");
4342 }
4343
4345
4346 TRACE("maximum length is %li\n", *length);
4347 fni->FileNameLength = 0;
4348
4349 fni->FileName[0] = 0;
4350
4351 fn.Buffer = fni->FileName;
4352 fn.Length = 0;
4353 fn.MaximumLength = (uint16_t)*length;
4354
4355 Status = fileref_get_filename(fileref, &fn, NULL, &reqlen);
4357 ERR("fileref_get_filename returned %08lx\n", Status);
4358 return Status;
4359 }
4360
4361 if (fcb->ads) {
4363 reqlen += datasuflen;
4364 else {
4365 if (fn.Length + datasuflen > fn.MaximumLength) {
4366 RtlCopyMemory(&fn.Buffer[fn.Length / sizeof(WCHAR)], datasuf, fn.MaximumLength - fn.Length);
4367 reqlen += datasuflen;
4369 } else {
4370 RtlCopyMemory(&fn.Buffer[fn.Length / sizeof(WCHAR)], datasuf, datasuflen);
4371 fn.Length += datasuflen;
4372 }
4373 }
4374 }
4375
4377 *length = -1;
4378 fni->FileNameLength = reqlen;
4379 TRACE("%.*S (truncated)\n", (int)(fn.Length / sizeof(WCHAR)), fn.Buffer);
4380 } else {
4381 *length -= fn.Length;
4382 fni->FileNameLength = fn.Length;
4383 TRACE("%.*S\n", (int)(fn.Length / sizeof(WCHAR)), fn.Buffer);
4384 }
4385
4386 return Status;
4387}
4388
4391
4392 if (fcb->ads) {
4393 if (!ccb->fileref || !ccb->fileref->parent) {
4394 ERR("no fileref for stream\n");
4395 return STATUS_INTERNAL_ERROR;
4396 }
4397
4398 ati->FileAttributes = ccb->fileref->parent->fcb->atts;
4399 } else
4400 ati->FileAttributes = fcb->atts;
4401
4403 ati->ReparseTag = 0;
4404 else
4406
4407 return STATUS_SUCCESS;
4408}
4409
4411 LONG reqsize;
4412 LIST_ENTRY* le;
4413 FILE_STREAM_INFORMATION *entry, *lastentry;
4415
4416 static const WCHAR datasuf[] = L":$DATA";
4417 UNICODE_STRING suf;
4418
4419 if (!fileref) {
4420 ERR("fileref was NULL\n");
4422 }
4423
4424 suf.Buffer = (WCHAR*)datasuf;
4425 suf.Length = suf.MaximumLength = sizeof(datasuf) - sizeof(WCHAR);
4426
4428 reqsize = sizeof(FILE_STREAM_INFORMATION) - sizeof(WCHAR) + suf.Length + sizeof(WCHAR);
4429 else
4430 reqsize = 0;
4431
4432 ExAcquireResourceSharedLite(&fileref->fcb->nonpaged->dir_children_lock, true);
4433
4435 while (le != &fileref->fcb->dir_children_index) {
4436 dir_child* dc = CONTAINING_RECORD(le, dir_child, list_entry_index);
4437
4438 if (dc->index == 0) {
4439 reqsize = (ULONG)sector_align(reqsize, sizeof(LONGLONG));
4440 reqsize += sizeof(FILE_STREAM_INFORMATION) - sizeof(WCHAR) + suf.Length + sizeof(WCHAR) + dc->name.Length;
4441 } else
4442 break;
4443
4444 le = le->Flink;
4445 }
4446
4447 TRACE("length = %li, reqsize = %lu\n", *length, reqsize);
4448
4449 if (reqsize > *length) {
4451 goto end;
4452 }
4453
4454 entry = fsi;
4455 lastentry = NULL;
4456
4458 ULONG off;
4459
4460 entry->NextEntryOffset = 0;
4461 entry->StreamNameLength = suf.Length + sizeof(WCHAR);
4462 entry->StreamSize.QuadPart = fileref->fcb->inode_item.st_size;
4463 entry->StreamAllocationSize.QuadPart = fcb_alloc_size(fileref->fcb);
4464
4465 entry->StreamName[0] = ':';
4466 RtlCopyMemory(&entry->StreamName[1], suf.Buffer, suf.Length);
4467
4468 off = (ULONG)sector_align(sizeof(FILE_STREAM_INFORMATION) - sizeof(WCHAR) + suf.Length + sizeof(WCHAR), sizeof(LONGLONG));
4469
4470 lastentry = entry;
4472 }
4473
4475 while (le != &fileref->fcb->dir_children_index) {
4476 dir_child* dc = CONTAINING_RECORD(le, dir_child, list_entry_index);
4477
4478 if (dc->index == 0) {
4479 ULONG off;
4480
4481 entry->NextEntryOffset = 0;
4482 entry->StreamNameLength = dc->name.Length + suf.Length + sizeof(WCHAR);
4483
4484 if (dc->fileref)
4485 entry->StreamSize.QuadPart = dc->fileref->fcb->adsdata.Length;
4486 else
4487 entry->StreamSize.QuadPart = dc->size;
4488
4489 entry->StreamAllocationSize.QuadPart = entry->StreamSize.QuadPart;
4490
4491 entry->StreamName[0] = ':';
4492
4493 RtlCopyMemory(&entry->StreamName[1], dc->name.Buffer, dc->name.Length);
4494 RtlCopyMemory(&entry->StreamName[1 + (dc->name.Length / sizeof(WCHAR))], suf.Buffer, suf.Length);
4495
4496 if (lastentry)
4497 lastentry->NextEntryOffset = (uint32_t)((uint8_t*)entry - (uint8_t*)lastentry);
4498
4499 off = (ULONG)sector_align(sizeof(FILE_STREAM_INFORMATION) - sizeof(WCHAR) + suf.Length + sizeof(WCHAR) + dc->name.Length, sizeof(LONGLONG));
4500
4501 lastentry = entry;
4503 } else
4504 break;
4505
4506 le = le->Flink;
4507 }
4508
4509 *length -= reqsize;
4510
4512
4513end:
4514 ExReleaseResourceLite(&fileref->fcb->nonpaged->dir_children_lock);
4515
4516 return Status;
4517}
4518
4519#ifndef __REACTOS__
4521 TRACE("FileStandardLinkInformation\n");
4522
4523 // FIXME - NumberOfAccessibleLinks should subtract open links which have been marked as delete_on_close
4524
4527 fsli->DeletePending = fileref ? fileref->delete_on_close : false;
4528 fsli->Directory = (!fcb->ads && fcb->type == BTRFS_TYPE_DIRECTORY) ? true : false;
4529
4531
4532 return STATUS_SUCCESS;
4533}
4534
4537 LIST_ENTRY* le;
4538 LONG bytes_needed;
4540 bool overflow = false;
4541 fcb* fcb = fileref->fcb;
4542 ULONG len;
4543
4544 if (fcb->ads)
4546
4549
4550 RtlZeroMemory(fli, *length);
4551
4552 bytes_needed = offsetof(FILE_LINKS_INFORMATION, Entry);
4553 len = bytes_needed;
4554 feli = NULL;
4555
4556 ExAcquireResourceSharedLite(fcb->Header.Resource, true);
4557
4558 if (fcb->inode == SUBVOL_ROOT_INODE) {
4559 ULONG namelen;
4560
4561 if (fcb == fcb->Vcb->root_fileref->fcb)
4562 namelen = sizeof(WCHAR);
4563 else
4565
4566 bytes_needed += sizeof(FILE_LINK_ENTRY_INFORMATION) - sizeof(WCHAR) + namelen;
4567
4568 if (bytes_needed > *length)
4569 overflow = true;
4570
4571 if (!overflow) {
4572 feli = &fli->Entry;
4573
4574 feli->NextEntryOffset = 0;
4575 feli->ParentFileId = 0; // we use an inode of 0 to mean the parent of a subvolume
4576
4577 if (fcb == fcb->Vcb->root_fileref->fcb) {
4578 feli->FileNameLength = 1;
4579 feli->FileName[0] = '.';
4580 } else {
4581 feli->FileNameLength = fileref->dc->name.Length / sizeof(WCHAR);
4583 }
4584
4585 fli->EntriesReturned++;
4586
4587 len = bytes_needed;
4588 }
4589 } else {
4590 ExAcquireResourceExclusiveLite(&fcb->Vcb->fileref_lock, true);
4591
4592 if (IsListEmpty(&fcb->hardlinks)) {
4593 if (!fileref->dc) {
4594 ExReleaseResourceLite(&fcb->Vcb->fileref_lock);
4596 goto end;
4597 }
4598
4599 bytes_needed += sizeof(FILE_LINK_ENTRY_INFORMATION) + fileref->dc->name.Length - sizeof(WCHAR);
4600
4601 if (bytes_needed > *length)
4602 overflow = true;
4603
4604 if (!overflow) {
4605 feli = &fli->Entry;
4606
4607 feli->NextEntryOffset = 0;
4608 feli->ParentFileId = fileref->parent->fcb->inode;
4609 feli->FileNameLength = fileref->dc->name.Length / sizeof(WCHAR);
4611
4612 fli->EntriesReturned++;
4613
4614 len = bytes_needed;
4615 }
4616 } else {
4617 le = fcb->hardlinks.Flink;
4618 while (le != &fcb->hardlinks) {
4620 file_ref* parfr;
4621
4622 TRACE("parent %I64x, index %I64x, name %.*S\n", hl->parent, hl->index, (int)(hl->name.Length / sizeof(WCHAR)), hl->name.Buffer);
4623
4624 Status = open_fileref_by_inode(fcb->Vcb, fcb->subvol, hl->parent, &parfr, Irp);
4625
4626 if (!NT_SUCCESS(Status)) {
4627 ERR("open_fileref_by_inode returned %08lx\n", Status);
4628 } else if (!parfr->deleted) {
4629 LIST_ENTRY* le2;
4630 bool found = false, deleted = false;
4632
4633 le2 = parfr->children.Flink;
4634 while (le2 != &parfr->children) {
4636
4637 if (fr2->dc && fr2->dc->index == hl->index) {
4638 found = true;
4639 deleted = fr2->deleted;
4640
4641 if (!deleted)
4642 fn = &fr2->dc->name;
4643
4644 break;
4645 }
4646
4647 le2 = le2->Flink;
4648 }
4649
4650 if (!found)
4651 fn = &hl->name;
4652
4653 if (!deleted) {
4654 TRACE("fn = %.*S (found = %u)\n", (int)(fn->Length / sizeof(WCHAR)), fn->Buffer, found);
4655
4656 if (feli)
4657 bytes_needed = (LONG)sector_align(bytes_needed, 8);
4658
4659 bytes_needed += sizeof(FILE_LINK_ENTRY_INFORMATION) + fn->Length - sizeof(WCHAR);
4660
4661 if (bytes_needed > *length)
4662 overflow = true;
4663
4664 if (!overflow) {
4665 if (feli) {
4666 feli->NextEntryOffset = (ULONG)sector_align(sizeof(FILE_LINK_ENTRY_INFORMATION) + ((feli->FileNameLength - 1) * sizeof(WCHAR)), 8);
4667 feli = (FILE_LINK_ENTRY_INFORMATION*)((uint8_t*)feli + feli->NextEntryOffset);
4668 } else
4669 feli = &fli->Entry;
4670
4671 feli->NextEntryOffset = 0;
4672 feli->ParentFileId = parfr->fcb->inode;
4673 feli->FileNameLength = fn->Length / sizeof(WCHAR);
4674 RtlCopyMemory(feli->FileName, fn->Buffer, fn->Length);
4675
4676 fli->EntriesReturned++;
4677
4678 len = bytes_needed;
4679 }
4680 }
4681
4682 free_fileref(parfr);
4683 }
4684
4685 le = le->Flink;
4686 }
4687 }
4688
4689 ExReleaseResourceLite(&fcb->Vcb->fileref_lock);
4690 }
4691
4692 fli->BytesNeeded = bytes_needed;
4693
4694 *length -= len;
4695
4697
4698end:
4699 ExReleaseResourceLite(fcb->Header.Resource);
4700
4701 return Status;
4702}
4703
4706 LIST_ENTRY* le;
4707 LONG bytes_needed;
4709 bool overflow = false;
4710 fcb* fcb = fileref->fcb;
4711 ULONG len;
4712
4713 if (fcb->ads)
4715
4718
4719 RtlZeroMemory(flfii, *length);
4720
4722 len = bytes_needed;
4723 flefii = NULL;
4724
4725 ExAcquireResourceSharedLite(fcb->Header.Resource, true);
4726
4727 if (fcb->inode == SUBVOL_ROOT_INODE) {
4728 ULONG namelen;
4729
4730 if (fcb == fcb->Vcb->root_fileref->fcb)
4731 namelen = sizeof(WCHAR);
4732 else
4734
4736
4737 if (bytes_needed > *length)
4738 overflow = true;
4739
4740 if (!overflow) {
4741 flefii = &flfii->Entry;
4742
4743 flefii->NextEntryOffset = 0;
4744
4745 if (fcb == fcb->Vcb->root_fileref->fcb) {
4746 RtlZeroMemory(&flefii->ParentFileId.Identifier[0], sizeof(FILE_ID_128));
4747 flefii->FileNameLength = 1;
4748 flefii->FileName[0] = '.';
4749 } else {
4750 RtlCopyMemory(&flefii->ParentFileId.Identifier[0], &fileref->parent->fcb->inode, sizeof(uint64_t));
4751 RtlCopyMemory(&flefii->ParentFileId.Identifier[sizeof(uint64_t)], &fileref->parent->fcb->subvol->id, sizeof(uint64_t));
4752
4753 flefii->FileNameLength = fileref->dc->name.Length / sizeof(WCHAR);
4755 }
4756
4757 flfii->EntriesReturned++;
4758
4759 len = bytes_needed;
4760 }
4761 } else {
4762 ExAcquireResourceExclusiveLite(&fcb->Vcb->fileref_lock, true);
4763
4764 if (IsListEmpty(&fcb->hardlinks)) {
4766
4767 if (bytes_needed > *length)
4768 overflow = true;
4769
4770 if (!overflow) {
4771 flefii = &flfii->Entry;
4772
4773 flefii->NextEntryOffset = 0;
4774
4775 RtlCopyMemory(&flefii->ParentFileId.Identifier[0], &fileref->parent->fcb->inode, sizeof(uint64_t));
4776 RtlCopyMemory(&flefii->ParentFileId.Identifier[sizeof(uint64_t)], &fileref->parent->fcb->subvol->id, sizeof(uint64_t));
4777
4778 flefii->FileNameLength = fileref->dc->name.Length / sizeof(WCHAR);
4780
4781 flfii->EntriesReturned++;
4782
4783 len = bytes_needed;
4784 }
4785 } else {
4786 le = fcb->hardlinks.Flink;
4787 while (le != &fcb->hardlinks) {
4789 file_ref* parfr;
4790
4791 TRACE("parent %I64x, index %I64x, name %.*S\n", hl->parent, hl->index, (int)(hl->name.Length / sizeof(WCHAR)), hl->name.Buffer);
4792
4793 Status = open_fileref_by_inode(fcb->Vcb, fcb->subvol, hl->parent, &parfr, Irp);
4794
4795 if (!NT_SUCCESS(Status)) {
4796 ERR("open_fileref_by_inode returned %08lx\n", Status);
4797 } else if (!parfr->deleted) {
4798 LIST_ENTRY* le2;
4799 bool found = false, deleted = false;
4801
4802 le2 = parfr->children.Flink;
4803 while (le2 != &parfr->children) {
4805
4806 if (fr2->dc->index == hl->index) {
4807 found = true;
4808 deleted = fr2->deleted;
4809
4810 if (!deleted)
4811 fn = &fr2->dc->name;
4812
4813 break;
4814 }
4815
4816 le2 = le2->Flink;
4817 }
4818
4819 if (!found)
4820 fn = &hl->name;
4821
4822 if (!deleted) {
4823 TRACE("fn = %.*S (found = %u)\n", (int)(fn->Length / sizeof(WCHAR)), fn->Buffer, found);
4824
4825 if (flefii)
4826 bytes_needed = (LONG)sector_align(bytes_needed, 8);
4827
4828 bytes_needed += offsetof(FILE_LINK_ENTRY_FULL_ID_INFORMATION, FileName[0]) + fn->Length;
4829
4830 if (bytes_needed > *length)
4831 overflow = true;
4832
4833 if (!overflow) {
4834 if (flefii) {
4836 flefii = (FILE_LINK_ENTRY_FULL_ID_INFORMATION*)((uint8_t*)flefii + flefii->NextEntryOffset);
4837 } else
4838 flefii = &flfii->Entry;
4839
4840 flefii->NextEntryOffset = 0;
4841
4842 RtlCopyMemory(&flefii->ParentFileId.Identifier[0], &parfr->fcb->inode, sizeof(uint64_t));
4843 RtlCopyMemory(&flefii->ParentFileId.Identifier[sizeof(uint64_t)], &parfr->fcb->subvol->id, sizeof(uint64_t));
4844
4845 flefii->FileNameLength = fn->Length / sizeof(WCHAR);
4846 RtlCopyMemory(flefii->FileName, fn->Buffer, fn->Length);
4847
4848 flfii->EntriesReturned++;
4849
4850 len = bytes_needed;
4851 }
4852 }
4853
4854 free_fileref(parfr);
4855 }
4856
4857 le = le->Flink;
4858 }
4859 }
4860
4861 ExReleaseResourceLite(&fcb->Vcb->fileref_lock);
4862 }
4863
4864 flfii->BytesNeeded = bytes_needed;
4865
4866 *length -= len;
4867
4869
4870 ExReleaseResourceLite(fcb->Header.Resource);
4871
4872 return Status;
4873}
4874
4876 RtlCopyMemory(&fii->VolumeSerialNumber, &fcb->Vcb->superblock.uuid.uuid[8], sizeof(uint64_t));
4877 RtlCopyMemory(&fii->FileId.Identifier[0], &fcb->inode, sizeof(uint64_t));
4878 RtlCopyMemory(&fii->FileId.Identifier[sizeof(uint64_t)], &fcb->subvol->id, sizeof(uint64_t));
4879
4880 *length -= sizeof(FILE_ID_INFORMATION);
4881
4882 return STATUS_SUCCESS;
4883}
4884
4886 INODE_ITEM* ii;
4887
4889
4890 if (fcb->ads)
4891 ii = &ccb->fileref->parent->fcb->inode_item;
4892 else
4893 ii = &fcb->inode_item;
4894
4895 if (fcb == fcb->Vcb->dummy_fcb) {
4897
4899 fsi->CreationTime = fsi->LastAccessTime = fsi->LastWriteTime = fsi->ChangeTime = time;
4900 } else {
4905 }
4906
4907 if (fcb->ads) {
4909 fsi->FileAttributes = ccb->fileref->parent->fcb->atts == 0 ? FILE_ATTRIBUTE_NORMAL : ccb->fileref->parent->fcb->atts;
4910 } else {
4914 }
4915
4916 if (fcb->type == BTRFS_TYPE_SOCKET)
4918 else if (fcb->type == BTRFS_TYPE_FIFO)
4920 else if (fcb->type == BTRFS_TYPE_CHARDEV)
4922 else if (fcb->type == BTRFS_TYPE_BLOCKDEV)
4925 fsi->ReparseTag = 0;
4926 else
4928
4931
4932 if (fcb->ads)
4933 fsi->NumberOfLinks = ccb->fileref->parent->fcb->inode_item.st_nlink;
4934 else
4936
4937 fsi->EffectiveAccess = ccb->access;
4938
4939 *length -= sizeof(FILE_STAT_INFORMATION);
4940
4941 return STATUS_SUCCESS;
4942}
4943
4945 INODE_ITEM* ii;
4946
4948
4949 if (fcb->ads)
4950 ii = &ccb->fileref->parent->fcb->inode_item;
4951 else
4952 ii = &fcb->inode_item;
4953
4954 if (fcb == fcb->Vcb->dummy_fcb) {
4956
4958 fsli->CreationTime = fsli->LastAccessTime = fsli->LastWriteTime = fsli->ChangeTime = time;
4959 } else {
4964 }
4965
4966 if (fcb->ads) {
4968 fsli->FileAttributes = ccb->fileref->parent->fcb->atts == 0 ? FILE_ATTRIBUTE_NORMAL : ccb->fileref->parent->fcb->atts;
4969 } else {
4973 }
4974
4975 if (fcb->type == BTRFS_TYPE_SOCKET)
4977 else if (fcb->type == BTRFS_TYPE_FIFO)
4979 else if (fcb->type == BTRFS_TYPE_CHARDEV)
4981 else if (fcb->type == BTRFS_TYPE_BLOCKDEV)
4983 else if (!(fsli->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
4984 fsli->ReparseTag = 0;
4985 else
4987
4990
4991 if (fcb->ads)
4992 fsli->NumberOfLinks = ccb->fileref->parent->fcb->inode_item.st_nlink;
4993 else
4995
4996 fsli->EffectiveAccess = ccb->access;
4998
4999 if (fcb->case_sensitive)
5001
5002 fsli->LxUid = ii->st_uid;
5003 fsli->LxGid = ii->st_gid;
5004 fsli->LxMode = ii->st_mode;
5005
5006 if (ii->st_mode & __S_IFBLK || ii->st_mode & __S_IFCHR) {
5007 fsli->LxDeviceIdMajor = (ii->st_rdev & 0xFFFFFFFFFFF00000) >> 20;
5008 fsli->LxDeviceIdMinor = (ii->st_rdev & 0xFFFFF);
5009 } else {
5010 fsli->LxDeviceIdMajor = 0;
5011 fsli->LxDeviceIdMinor = 0;
5012 }
5013
5014 *length -= sizeof(FILE_STAT_LX_INFORMATION);
5015
5016 return STATUS_SUCCESS;
5017}
5018
5021
5023
5024 return STATUS_SUCCESS;
5025}
5026
5027#endif // __REACTOS__
5028
5031
5032 memset(fci, 0, sizeof(FILE_COMPRESSION_INFORMATION));
5033
5034 if (fcb->ads)
5036 else if (!S_ISDIR(fcb->inode_item.st_mode))
5038
5039 return STATUS_SUCCESS;
5040}
5041
5044 LONG length = IrpSp->Parameters.QueryFile.Length;
5045 fcb* fcb = FileObject->FsContext;
5046 ccb* ccb = FileObject->FsContext2;
5049
5050 TRACE("(%p, %p, %p)\n", Vcb, FileObject, Irp);
5051 TRACE("fcb = %p\n", fcb);
5052
5053 if (fcb == Vcb->volume_fcb)
5055
5056 if (!ccb) {
5057 ERR("ccb is NULL\n");
5059 }
5060
5061 switch (IrpSp->Parameters.QueryFile.FileInformationClass) {
5062 case FileAllInformation:
5063 {
5064 FILE_ALL_INFORMATION* fai = Irp->AssociatedIrp.SystemBuffer;
5065 INODE_ITEM* ii;
5066
5067 TRACE("FileAllInformation\n");
5068
5069 if (Irp->RequestorMode != KernelMode && !(ccb->access & (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES))) {
5070 WARN("insufficient privileges\n");
5072 goto exit;
5073 }
5074
5075 if (fcb->ads) {
5076 if (!fileref || !fileref->parent) {
5077 ERR("no fileref for stream\n");
5079 goto exit;
5080 }
5081
5082 ii = &fileref->parent->fcb->inode_item;
5083 } else
5084 ii = &fcb->inode_item;
5085
5086 // Access, mode, and alignment are all filled in by the kernel
5087
5088 if (length > 0)
5090
5091 if (length > 0)
5093
5094 if (length > 0)
5096
5097 if (length > 0)
5099
5101
5102 if (length > 0)
5104
5105 length -= sizeof(FILE_MODE_INFORMATION);
5106
5108
5109 if (length > 0)
5111
5113
5114 break;
5115 }
5116
5118 {
5119 FILE_ATTRIBUTE_TAG_INFORMATION* ati = Irp->AssociatedIrp.SystemBuffer;
5120
5121 TRACE("FileAttributeTagInformation\n");
5122
5123 if (Irp->RequestorMode != KernelMode && !(ccb->access & (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES))) {
5124 WARN("insufficient privileges\n");
5126 goto exit;
5127 }
5128
5129 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
5131 ExReleaseResourceLite(&Vcb->tree_lock);
5132
5133 break;
5134 }
5135
5137 {
5138 FILE_BASIC_INFORMATION* fbi = Irp->AssociatedIrp.SystemBuffer;
5139 INODE_ITEM* ii;
5140
5141 TRACE("FileBasicInformation\n");
5142
5143 if (Irp->RequestorMode != KernelMode && !(ccb->access & (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES))) {
5144 WARN("insufficient privileges\n");
5146 goto exit;
5147 }
5148
5149 if (IrpSp->Parameters.QueryFile.Length < sizeof(FILE_BASIC_INFORMATION)) {
5150 WARN("overflow\n");
5152 goto exit;
5153 }
5154
5155 if (fcb->ads) {
5156 if (!fileref || !fileref->parent) {
5157 ERR("no fileref for stream\n");
5159 goto exit;
5160 }
5161
5162 ii = &fileref->parent->fcb->inode_item;
5163 } else
5164 ii = &fcb->inode_item;
5165
5167 break;
5168 }
5169
5171 {
5172 FILE_COMPRESSION_INFORMATION* fci = Irp->AssociatedIrp.SystemBuffer;
5173
5174 TRACE("FileCompressionInformation\n");
5175
5177 break;
5178 }
5179
5180 case FileEaInformation:
5181 {
5182 FILE_EA_INFORMATION* eai = Irp->AssociatedIrp.SystemBuffer;
5183
5184 TRACE("FileEaInformation\n");
5185
5187
5188 break;
5189 }
5190
5192 {
5193 FILE_INTERNAL_INFORMATION* fii = Irp->AssociatedIrp.SystemBuffer;
5194
5195 TRACE("FileInternalInformation\n");
5196
5198
5199 break;
5200 }
5201
5203 {
5204 FILE_NAME_INFORMATION* fni = Irp->AssociatedIrp.SystemBuffer;
5205
5206 TRACE("FileNameInformation\n");
5207
5209
5210 break;
5211 }
5212
5214 {
5215 FILE_NETWORK_OPEN_INFORMATION* fnoi = Irp->AssociatedIrp.SystemBuffer;
5216
5217 TRACE("FileNetworkOpenInformation\n");
5218
5219 if (Irp->RequestorMode != KernelMode && !(ccb->access & (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES))) {
5220 WARN("insufficient privileges\n");
5222 goto exit;
5223 }
5224
5226
5227 break;
5228 }
5229
5231 {
5232 FILE_POSITION_INFORMATION* fpi = Irp->AssociatedIrp.SystemBuffer;
5233
5234 TRACE("FilePositionInformation\n");
5235
5237
5238 break;
5239 }
5240
5242 {
5243 FILE_STANDARD_INFORMATION* fsi = Irp->AssociatedIrp.SystemBuffer;
5244
5245 TRACE("FileStandardInformation\n");
5246
5247 if (IrpSp->Parameters.QueryFile.Length < sizeof(FILE_STANDARD_INFORMATION)) {
5248 WARN("overflow\n");
5250 goto exit;
5251 }
5252
5254
5255 break;
5256 }
5257
5259 {
5260 FILE_STREAM_INFORMATION* fsi = Irp->AssociatedIrp.SystemBuffer;
5261
5262 TRACE("FileStreamInformation\n");
5263
5265
5266 break;
5267 }
5268
5269#if (NTDDI_VERSION >= NTDDI_VISTA)
5271 {
5272 FILE_LINKS_INFORMATION* fli = Irp->AssociatedIrp.SystemBuffer;
5273
5274 TRACE("FileHardLinkInformation\n");
5275
5276 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
5278 ExReleaseResourceLite(&Vcb->tree_lock);
5279
5280 break;
5281 }
5282
5284 {
5285 FILE_NAME_INFORMATION* fni = Irp->AssociatedIrp.SystemBuffer;
5286
5287 TRACE("FileNormalizedNameInformation\n");
5288
5290
5291 break;
5292 }
5293
5295 {
5296 FILE_STANDARD_LINK_INFORMATION* fsli = Irp->AssociatedIrp.SystemBuffer;
5297
5298 TRACE("FileStandardLinkInformation\n");
5299
5301
5302 break;
5303 }
5304
5306 TRACE("FileRemoteProtocolInformation\n");
5308 goto exit;
5309
5310#ifndef _MSC_VER
5311#pragma GCC diagnostic push
5312#pragma GCC diagnostic ignored "-Wswitch"
5313#endif
5314 case FileIdInformation:
5315 {
5316 FILE_ID_INFORMATION* fii = Irp->AssociatedIrp.SystemBuffer;
5317
5318 if (IrpSp->Parameters.QueryFile.Length < sizeof(FILE_ID_INFORMATION)) {
5319 WARN("overflow\n");
5321 goto exit;
5322 }
5323
5324 TRACE("FileIdInformation\n");
5325
5327
5328 break;
5329 }
5330
5332 {
5333 FILE_STAT_INFORMATION* fsi = Irp->AssociatedIrp.SystemBuffer;
5334
5335 if (IrpSp->Parameters.QueryFile.Length < sizeof(FILE_STAT_INFORMATION)) {
5336 WARN("overflow\n");
5338 goto exit;
5339 }
5340
5341 TRACE("FileStatInformation\n");
5342
5344
5345 break;
5346 }
5347
5349 {
5350 FILE_STAT_LX_INFORMATION* fsli = Irp->AssociatedIrp.SystemBuffer;
5351
5352 if (IrpSp->Parameters.QueryFile.Length < sizeof(FILE_STAT_LX_INFORMATION)) {
5353 WARN("overflow\n");
5355 goto exit;
5356 }
5357
5358 TRACE("FileStatLxInformation\n");
5359
5361
5362 break;
5363 }
5364
5366 {
5367 FILE_CASE_SENSITIVE_INFORMATION* fcsi = Irp->AssociatedIrp.SystemBuffer;
5368
5369 if (IrpSp->Parameters.QueryFile.Length < sizeof(FILE_CASE_SENSITIVE_INFORMATION)) {
5370 WARN("overflow\n");
5372 goto exit;
5373 }
5374
5375 TRACE("FileCaseSensitiveInformation\n");
5376
5378
5379 break;
5380 }
5381
5383 {
5384 FILE_LINKS_FULL_ID_INFORMATION* flfii = Irp->AssociatedIrp.SystemBuffer;
5385
5386 TRACE("FileHardLinkFullIdInformation\n");
5387
5388 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
5390 ExReleaseResourceLite(&Vcb->tree_lock);
5391
5392 break;
5393 }
5394#ifndef _MSC_VER
5395#pragma GCC diagnostic pop
5396#endif
5397#endif
5398
5399 default:
5400 WARN("unknown FileInformationClass %u\n", IrpSp->Parameters.QueryFile.FileInformationClass);
5402 goto exit;
5403 }
5404
5405 if (length < 0) {
5406 length = 0;
5408 }
5409
5410 Irp->IoStatus.Information = IrpSp->Parameters.QueryFile.Length - length;
5411
5412exit:
5413 TRACE("query_info returning %08lx\n", Status);
5414
5415 return Status;
5416}
5417
5420NTSTATUS __stdcall drv_query_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
5423 fcb* fcb;
5424 device_extension* Vcb = DeviceObject->DeviceExtension;
5425 bool top_level;
5426
5428
5429 top_level = is_top_level(Irp);
5430
5431 if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
5433 goto end;
5434 } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
5436 goto end;
5437 }
5438
5439 Irp->IoStatus.Information = 0;
5440
5441 TRACE("query information\n");
5442
5444
5445 fcb = IrpSp->FileObject->FsContext;
5446 TRACE("fcb = %p\n", fcb);
5447 TRACE("fcb->subvol = %p\n", fcb->subvol);
5448
5450
5451end:
5452 TRACE("returning %08lx\n", Status);
5453
5454 Irp->IoStatus.Status = Status;
5455
5457
5458 if (top_level)
5460
5462
5463 return Status;
5464}
5465
5470 bool top_level;
5471 device_extension* Vcb = DeviceObject->DeviceExtension;
5474 fcb* fcb;
5475 ccb* ccb;
5477 ULONG retlen = 0;
5478
5480
5481 TRACE("(%p, %p)\n", DeviceObject, Irp);
5482
5483 top_level = is_top_level(Irp);
5484
5485 if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
5487 goto end;
5488 } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
5490 goto end;
5491 }
5492
5494 if (!ffei) {
5495 ERR("could not get output buffer\n");
5497 goto end;
5498 }
5499
5500 if (!FileObject) {
5501 ERR("no file object\n");
5503 goto end;
5504 }
5505
5506 fcb = FileObject->FsContext;
5507
5508 if (!fcb) {
5509 ERR("no fcb\n");
5511 goto end;
5512 }
5513
5514 if (fcb == fcb->Vcb->volume_fcb) {
5516 goto end;
5517 }
5518
5519 ccb = FileObject->FsContext2;
5520
5521 if (!ccb) {
5522 ERR("no ccb\n");
5524 goto end;
5525 }
5526
5527 if (Irp->RequestorMode == UserMode && !(ccb->access & (FILE_READ_EA | FILE_WRITE_EA))) {
5528 WARN("insufficient privileges\n");
5530 goto end;
5531 }
5532
5533 if (fcb->ads)
5534 fcb = ccb->fileref->parent->fcb;
5535
5536 ExAcquireResourceSharedLite(fcb->Header.Resource, true);
5537
5538 if (fcb->ea_xattr.Length == 0) {
5540 goto end2;
5541 }
5542
5544
5545 if (IrpSp->Parameters.QueryEa.EaList) {
5548
5549 in = IrpSp->Parameters.QueryEa.EaList;
5550 do {
5551 STRING s;
5552
5553 s.Length = s.MaximumLength = in->EaNameLength;
5554 s.Buffer = in->EaName;
5555
5556 RtlUpperString(&s, &s);
5557
5558 if (in->NextEntryOffset == 0)
5559 break;
5560
5561 in = (FILE_GET_EA_INFORMATION*)(((uint8_t*)in) + in->NextEntryOffset);
5562 } while (true);
5563
5565 out = NULL;
5566
5567 do {
5568 bool found = false;
5569
5570 in = IrpSp->Parameters.QueryEa.EaList;
5571 do {
5572 if (in->EaNameLength == ea->EaNameLength &&
5573 RtlCompareMemory(in->EaName, ea->EaName, in->EaNameLength) == in->EaNameLength) {
5574 found = true;
5575 break;
5576 }
5577
5578 if (in->NextEntryOffset == 0)
5579 break;
5580
5581 in = (FILE_GET_EA_INFORMATION*)(((uint8_t*)in) + in->NextEntryOffset);
5582 } while (true);
5583
5584 if (found) {
5585 uint8_t padding = retlen % 4 > 0 ? (4 - (retlen % 4)) : 0;
5586
5587 if (offsetof(FILE_FULL_EA_INFORMATION, EaName[0]) + ea->EaNameLength + 1 + ea->EaValueLength > IrpSp->Parameters.QueryEa.Length - retlen - padding) {
5589 retlen = 0;
5590 goto end2;
5591 }
5592
5593 retlen += padding;
5594
5595 if (out) {
5596 out->NextEntryOffset = (ULONG)offsetof(FILE_FULL_EA_INFORMATION, EaName[0]) + out->EaNameLength + 1 + out->EaValueLength + padding;
5597 out = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)out) + out->NextEntryOffset);
5598 } else
5599 out = ffei;
5600
5601 out->NextEntryOffset = 0;
5602 out->Flags = ea->Flags;
5603 out->EaNameLength = ea->EaNameLength;
5604 out->EaValueLength = ea->EaValueLength;
5605 RtlCopyMemory(out->EaName, ea->EaName, ea->EaNameLength + ea->EaValueLength + 1);
5606
5607 retlen += (ULONG)offsetof(FILE_FULL_EA_INFORMATION, EaName[0]) + ea->EaNameLength + 1 + ea->EaValueLength;
5608
5610 break;
5611 }
5612
5613 if (ea->NextEntryOffset == 0)
5614 break;
5615
5616 ea = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)ea) + ea->NextEntryOffset);
5617 } while (true);
5618 } else {
5620 ULONG index;
5621
5623 // The index is 1-based
5624 if (IrpSp->Parameters.QueryEa.EaIndex == 0) {
5626 goto end2;
5627 } else
5628 index = IrpSp->Parameters.QueryEa.EaIndex - 1;
5629 } else if (IrpSp->Flags & SL_RESTART_SCAN)
5630 index = ccb->ea_index = 0;
5631 else
5632 index = ccb->ea_index;
5633
5635
5636 if (index > 0) {
5637 ULONG i;
5638
5639 for (i = 0; i < index; i++) {
5640 if (ea->NextEntryOffset == 0) { // last item
5642 goto end2;
5643 }
5644
5645 ea = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)ea) + ea->NextEntryOffset);
5646 }
5647 }
5648
5649 out = NULL;
5650
5651 do {
5652 uint8_t padding = retlen % 4 > 0 ? (4 - (retlen % 4)) : 0;
5653
5654 if (offsetof(FILE_FULL_EA_INFORMATION, EaName[0]) + ea->EaNameLength + 1 + ea->EaValueLength > IrpSp->Parameters.QueryEa.Length - retlen - padding) {
5656 goto end2;
5657 }
5658
5659 retlen += padding;
5660
5661 if (out) {
5662 out->NextEntryOffset = (ULONG)offsetof(FILE_FULL_EA_INFORMATION, EaName[0]) + out->EaNameLength + 1 + out->EaValueLength + padding;
5663 out = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)out) + out->NextEntryOffset);
5664 } else
5665 out = ffei;
5666
5667 out->NextEntryOffset = 0;
5668 out->Flags = ea->Flags;
5669 out->EaNameLength = ea->EaNameLength;
5670 out->EaValueLength = ea->EaValueLength;
5671 RtlCopyMemory(out->EaName, ea->EaName, ea->EaNameLength + ea->EaValueLength + 1);
5672
5673 retlen += (ULONG)offsetof(FILE_FULL_EA_INFORMATION, EaName[0]) + ea->EaNameLength + 1 + ea->EaValueLength;
5674
5675 if (!(IrpSp->Flags & SL_INDEX_SPECIFIED))
5676 ccb->ea_index++;
5677
5679 break;
5680
5681 ea = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)ea) + ea->NextEntryOffset);
5682 } while (true);
5683 }
5684
5685end2:
5686 ExReleaseResourceLite(fcb->Header.Resource);
5687
5688end:
5689 TRACE("returning %08lx\n", Status);
5690
5691 Irp->IoStatus.Status = Status;
5692 Irp->IoStatus.Information = NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW ? retlen : 0;
5693
5695
5696 if (top_level)
5698
5700
5701 return Status;
5702}
5703
5707 device_extension* Vcb = DeviceObject->DeviceExtension;
5709 bool top_level;
5712 fcb* fcb;
5713 ccb* ccb;
5716 ULONG offset;
5717 LIST_ENTRY ealist;
5718 ea_item* item;
5720 LIST_ENTRY* le;
5723
5725
5726 TRACE("(%p, %p)\n", DeviceObject, Irp);
5727
5728 top_level = is_top_level(Irp);
5729
5730 if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
5732 goto end;
5733 } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
5735 goto end;
5736 }
5737
5738 if (Vcb->readonly) {
5740 goto end;
5741 }
5742
5744 if (!ffei) {
5745 ERR("could not get output buffer\n");
5747 goto end;
5748 }
5749
5750 Status = IoCheckEaBufferValidity(ffei, IrpSp->Parameters.SetEa.Length, &offset);
5751 if (!NT_SUCCESS(Status)) {
5752 ERR("IoCheckEaBufferValidity returned %08lx (error at offset %lu)\n", Status, offset);
5753 goto end;
5754 }
5755
5756 if (!FileObject) {
5757 ERR("no file object\n");
5759 goto end;
5760 }
5761
5762 fcb = FileObject->FsContext;
5763
5764 if (!fcb) {
5765 ERR("no fcb\n");
5767 goto end;
5768 }
5769
5770 if (fcb == fcb->Vcb->volume_fcb) {
5772 goto end;
5773 }
5774
5775 ccb = FileObject->FsContext2;
5776
5777 if (!ccb) {
5778 ERR("no ccb\n");
5780 goto end;
5781 }
5782
5783 if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_WRITE_EA)) {
5784 WARN("insufficient privileges\n");
5786 goto end;
5787 }
5788
5789 if (fcb->ads) {
5791 fcb = fileref->fcb;
5792 } else
5793 fileref = ccb->fileref;
5794
5795 InitializeListHead(&ealist);
5796
5797 ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
5798
5799 if (fcb->ea_xattr.Length > 0) {
5801
5802 do {
5804 if (!item) {
5805 ERR("out of memory\n");
5807 goto end2;
5808 }
5809
5810 item->name.Length = item->name.MaximumLength = ea->EaNameLength;
5811 item->name.Buffer = ea->EaName;
5812
5813 item->value.Length = item->value.MaximumLength = ea->EaValueLength;
5814 item->value.Buffer = &ea->EaName[ea->EaNameLength + 1];
5815
5816 item->flags = ea->Flags;
5817
5818 InsertTailList(&ealist, &item->list_entry);
5819
5820 if (ea->NextEntryOffset == 0)
5821 break;
5822
5823 ea = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)ea) + ea->NextEntryOffset);
5824 } while (true);
5825 }
5826
5827 ea = ffei;
5828
5829 do {
5830 STRING s;
5831 bool found = false;
5832
5833 s.Length = s.MaximumLength = ea->EaNameLength;
5834 s.Buffer = ea->EaName;
5835
5836 RtlUpperString(&s, &s);
5837
5838 le = ealist.Flink;
5839 while (le != &ealist) {
5841
5842 if (item->name.Length == s.Length &&
5843 RtlCompareMemory(item->name.Buffer, s.Buffer, s.Length) == s.Length) {
5844 item->flags = ea->Flags;
5845 item->value.Length = item->value.MaximumLength = ea->EaValueLength;
5846 item->value.Buffer = &ea->EaName[ea->EaNameLength + 1];
5847 found = true;
5848 break;
5849 }
5850
5851 le = le->Flink;
5852 }
5853
5854 if (!found) {
5856 if (!item) {
5857 ERR("out of memory\n");
5859 goto end2;
5860 }
5861
5862 item->name.Length = item->name.MaximumLength = ea->EaNameLength;
5863 item->name.Buffer = ea->EaName;
5864
5865 item->value.Length = item->value.MaximumLength = ea->EaValueLength;
5866 item->value.Buffer = &ea->EaName[ea->EaNameLength + 1];
5867
5868 item->flags = ea->Flags;
5869
5870 InsertTailList(&ealist, &item->list_entry);
5871 }
5872
5873 if (ea->NextEntryOffset == 0)
5874 break;
5875
5876 ea = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)ea) + ea->NextEntryOffset);
5877 } while (true);
5878
5879 // remove entries with zero-length value
5880 le = ealist.Flink;
5881 while (le != &ealist) {
5882 LIST_ENTRY* le2 = le->Flink;
5883
5885
5886 if (item->value.Length == 0) {
5887 RemoveEntryList(&item->list_entry);
5889 }
5890
5891 le = le2;
5892 }
5893
5894 // handle LXSS values
5895 le = ealist.Flink;
5896 while (le != &ealist) {
5897 LIST_ENTRY* le2 = le->Flink;
5898
5900
5901 if (item->name.Length == sizeof(lxuid) - 1 && RtlCompareMemory(item->name.Buffer, lxuid, item->name.Length) == item->name.Length) {
5902 if (item->value.Length < sizeof(uint32_t)) {
5903 ERR("uid value was shorter than expected\n");
5905 goto end2;
5906 }
5907
5908 if (Irp->RequestorMode == KernelMode || ccb->access & FILE_WRITE_ATTRIBUTES) {
5909 RtlCopyMemory(&fcb->inode_item.st_uid, item->value.Buffer, sizeof(uint32_t));
5910 fcb->sd_dirty = true;
5911 fcb->sd_deleted = false;
5912 }
5913
5914 RemoveEntryList(&item->list_entry);
5916 } else if (item->name.Length == sizeof(lxgid) - 1 && RtlCompareMemory(item->name.Buffer, lxgid, item->name.Length) == item->name.Length) {
5917 if (item->value.Length < sizeof(uint32_t)) {
5918 ERR("gid value was shorter than expected\n");
5920 goto end2;
5921 }
5922
5923 if (Irp->RequestorMode == KernelMode || ccb->access & FILE_WRITE_ATTRIBUTES)
5924 RtlCopyMemory(&fcb->inode_item.st_gid, item->value.Buffer, sizeof(uint32_t));
5925
5926 RemoveEntryList(&item->list_entry);
5928 } else if (item->name.Length == sizeof(lxmod) - 1 && RtlCompareMemory(item->name.Buffer, lxmod, item->name.Length) == item->name.Length) {
5929 if (item->value.Length < sizeof(uint32_t)) {
5930 ERR("mode value was shorter than expected\n");
5932 goto end2;
5933 }
5934
5935 if (Irp->RequestorMode == KernelMode || ccb->access & FILE_WRITE_ATTRIBUTES) {
5937 uint32_t val;
5938
5939 RtlCopyMemory(&val, item->value.Buffer, sizeof(uint32_t));
5940
5941 fcb->inode_item.st_mode &= ~allowed;
5942 fcb->inode_item.st_mode |= val & allowed;
5943 }
5944
5945 RemoveEntryList(&item->list_entry);
5947 }
5948
5949 le = le2;
5950 }
5951
5952 if (IsListEmpty(&ealist)) {
5953 fcb->ealen = 0;
5954
5955 if (fcb->ea_xattr.Buffer)
5957
5960 } else {
5961 uint16_t size = 0;
5962 char *buf, *oldbuf;
5963
5964 le = ealist.Flink;
5965 while (le != &ealist) {
5967
5968 if (size % 4 > 0)
5969 size += 4 - (size % 4);
5970
5971 size += (uint16_t)offsetof(FILE_FULL_EA_INFORMATION, EaName[0]) + item->name.Length + 1 + item->value.Length;
5972
5973 le = le->Flink;
5974 }
5975
5977 if (!buf) {
5978 ERR("out of memory\n");
5980 goto end2;
5981 }
5982
5983 oldbuf = fcb->ea_xattr.Buffer;
5984
5987
5988 fcb->ealen = 4;
5989 ea = NULL;
5990
5991 le = ealist.Flink;
5992 while (le != &ealist) {
5994
5995 if (ea) {
5997
5998 if (ea->NextEntryOffset % 4 > 0)
5999 ea->NextEntryOffset += 4 - (ea->NextEntryOffset % 4);
6000
6001 ea = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)ea) + ea->NextEntryOffset);
6002 } else
6004
6005 ea->NextEntryOffset = 0;
6006 ea->Flags = item->flags;
6007 ea->EaNameLength = (UCHAR)item->name.Length;
6008 ea->EaValueLength = item->value.Length;
6009
6010 RtlCopyMemory(ea->EaName, item->name.Buffer, item->name.Length);
6011 ea->EaName[item->name.Length] = 0;
6012 RtlCopyMemory(&ea->EaName[item->name.Length + 1], item->value.Buffer, item->value.Length);
6013
6014 fcb->ealen += 5 + item->name.Length + item->value.Length;
6015
6016 le = le->Flink;
6017 }
6018
6019 if (oldbuf)
6020 ExFreePool(oldbuf);
6021 }
6022
6023 fcb->ea_changed = true;
6024
6027
6028 fcb->inode_item.transid = Vcb->superblock.generation;
6030
6033
6034 fcb->inode_item_changed = true;
6036
6038
6040
6041end2:
6042 ExReleaseResourceLite(fcb->Header.Resource);
6043
6044 while (!IsListEmpty(&ealist)) {
6045 le = RemoveHeadList(&ealist);
6046
6048
6050 }
6051
6052end:
6053 TRACE("returning %08lx\n", Status);
6054
6055 Irp->IoStatus.Status = Status;
6056 Irp->IoStatus.Information = 0;
6057
6059
6060 if (top_level)
6062
6064
6065 return Status;
6066}
unsigned char BOOLEAN
BOOLEAN NTAPI SeAccessCheck(_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext, _In_ BOOLEAN SubjectContextLocked, _In_ ACCESS_MASK DesiredAccess, _In_ ACCESS_MASK PreviouslyGrantedAccess, _Out_ PPRIVILEGE_SET *Privileges, _In_ PGENERIC_MAPPING GenericMapping, _In_ KPROCESSOR_MODE AccessMode, _Out_ PACCESS_MASK GrantedAccess, _Out_ PNTSTATUS AccessStatus)
Determines whether security access rights can be given to an object depending on the security descrip...
Definition: accesschk.c:1994
unsigned short int uint16_t
Definition: acefiex.h:54
static struct @1549 move_list[MOVE_LIST_SIZE]
#define InterlockedIncrement
Definition: armddk.h:53
LONG NTSTATUS
Definition: precomp.h:26
#define S_ISDIR(mode)
Definition: various.h:18
#define index(s, c)
Definition: various.h:29
static void set_size(float size)
Definition: wordpad.c:316
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
#define GID_NOBODY
Definition: btrfs_drv.h:91
#define VCB_TYPE_VOLUME
Definition: btrfs_drv.h:689
#define FILE_CS_FLAG_CASE_SENSITIVE_DIR
Definition: btrfs_drv.h:165
NTSTATUS read_file(fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp) __attribute__((nonnull(1
#define increase_fileref_refcount(fileref)
Definition: btrfs_drv.h:1739
#define InterlockedIncrement64(a)
Definition: btrfs_drv.h:143
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1365
#define EA_CASE_SENSITIVE
Definition: btrfs_drv.h:105
static __inline FAST_IO_POSSIBLE fast_io_possible(fcb *fcb)
Definition: btrfs_drv.h:1684
#define EA_EA
Definition: btrfs_drv.h:102
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
#define _Dispatch_type_(a)
Definition: btrfs_drv.h:204
#define UID_NOBODY
Definition: btrfs_drv.h:90
static const char lxgid[]
Definition: btrfs_drv.h:1288
#define IO_REPARSE_TAG_AF_UNIX
Definition: btrfs_drv.h:120
#define __S_IFDIR
Definition: btrfs_drv.h:1754
uint32_t sid_to_uid(PSID sid)
Definition: security.c:310
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:989
uint32_t inherit_mode(fcb *parfcb, bool is_dir)
Definition: create.c:1948
struct _fcb fcb
Definition: btrfs_drv.h:1364
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool prealloc
Definition: btrfs_drv.h:1364
#define VCB_TYPE_FS
Definition: btrfs_drv.h:687
NTSTATUS do_write_file(fcb *fcb, uint64_t start_data, uint64_t end_data, void *data, PIRP Irp, bool file_write, uint32_t irp_offset, LIST_ENTRY *rollback) __attribute__((nonnull(1
ULONG get_reparse_tag_fcb(fcb *fcb)
Definition: dirctrl.c:83
#define ALLOC_TAG
Definition: btrfs_drv.h:87
NTSTATUS open_fileref_child(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension *Vcb, _In_ file_ref *sf, _In_ PUNICODE_STRING name, _In_ bool case_sensitive, _In_ bool lastpart, _In_ bool streampart, _In_ POOL_TYPE pooltype, _Out_ file_ref **psf2, _In_opt_ PIRP Irp)
Definition: create.c:1459
static __inline uint64_t make_file_id(root *r, uint64_t inode)
Definition: btrfs_drv.h:1012
NTSTATUS open_fileref(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension *Vcb, _Out_ file_ref **pfr, _In_ PUNICODE_STRING fnus, _In_opt_ file_ref *related, _In_ bool parent, _Out_opt_ USHORT *parsed, _Out_opt_ ULONG *fn_offset, _In_ POOL_TYPE pooltype, _In_ bool case_sensitive, _In_opt_ PIRP Irp)
Definition: create.c:1690
static __inline POPLOCK fcb_oplock(fcb *fcb)
Definition: btrfs_drv.h:1677
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address) __attribute__((nonnull(1)))
NTSTATUS NTSTATUS NTSTATUS NTSTATUS extend_file(fcb *fcb, file_ref *fileref, uint64_t end, bool prealloc, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback) __attribute__((nonnull(1
void find_gid(struct _fcb *fcb, struct _fcb *parfcb, PSECURITY_SUBJECT_CONTEXT subjcont)
Definition: security.c:924
_In_ uint16_t _Out_ ULONG * atts
Definition: btrfs_drv.h:1107
#define EA_REPARSE
Definition: btrfs_drv.h:99
NTSTATUS NTSTATUS NTSTATUS truncate_file(fcb *fcb, uint64_t end, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
#define EA_DOSATTRIB
Definition: btrfs_drv.h:96
NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, root *subvol, uint64_t inode, file_ref **pfr, PIRP Irp)
Definition: create.c:4136
NTSTATUS bool void NTSTATUS add_extent_to_fcb(_In_ fcb *fcb, _In_ uint64_t offset, _In_reads_bytes_(edsize) EXTENT_DATA *ed, _In_ uint16_t edsize, _In_ bool unique, _In_opt_ _When_(return >=0, __drv_aliasesMem) void *csum, _In_ LIST_ENTRY *rollback) __attribute__((nonnull(1
static const char lxmod[]
Definition: btrfs_drv.h:1289
static const char lxuid[]
Definition: btrfs_drv.h:1287
#define IO_REPARSE_TAG_LX_CHR
Definition: btrfs_drv.h:122
#define IO_REPARSE_TAG_LX_BLK
Definition: btrfs_drv.h:123
struct _ccb ccb
NTSTATUS NTSTATUS void clear_rollback(LIST_ENTRY *rollback) __attribute__((nonnull(1)))
#define IO_REPARSE_TAG_LX_FIFO
Definition: btrfs_drv.h:121
NTSTATUS update_changed_extent_ref(device_extension *Vcb, chunk *c, uint64_t address, uint64_t size, uint64_t root, uint64_t objid, uint64_t offset, int32_t count, bool no_csum, bool superseded, PIRP Irp)
Definition: extent-tree.c:1951
fcb * create_fcb(device_extension *Vcb, POOL_TYPE pool_type)
Definition: create.c:91
NTSTATUS add_dir_child(fcb *fcb, uint64_t inode, bool subvol, PANSI_STRING utf8, PUNICODE_STRING name, uint8_t type, dir_child **pdc)
Definition: create.c:1871
@ PropCompression_None
Definition: btrfs_drv.h:268
file_ref * create_fileref(device_extension *Vcb)
Definition: create.c:160
static __inline void * map_user_buffer(PIRP Irp, ULONG priority)
Definition: btrfs_drv.h:977
#define __S_IFBLK
Definition: btrfs_drv.h:1756
static __inline uint64_t fcb_alloc_size(fcb *fcb)
Definition: btrfs_drv.h:1824
static __inline bool is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:1033
#define __S_IFCHR
Definition: btrfs_drv.h:1755
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
#define _Requires_exclusive_lock_held_(lock)
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
crc_func calc_crc32c
Definition: crc32c.c:23
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
UINT32 uint32_t
Definition: types.h:75
UINT64 uint64_t
Definition: types.h:77
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static string utf16_to_utf8(const wstring_view &utf16)
Definition: main.cpp:670
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define crc32(crc, buf, len)
Definition: inflate.c:1081
static const WCHAR *const ext[]
Definition: module.c:53
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1695
NTSTATUS delete_fileref(_In_ file_ref *fileref, _In_opt_ PFILE_OBJECT FileObject, _In_ bool make_orphan, _In_opt_ PIRP Irp, _In_ LIST_ENTRY *rollback)
Definition: btrfs.c:2270
void free_fileref(_Inout_ file_ref *fr)
Definition: btrfs.c:1856
void reap_fileref(device_extension *Vcb, file_ref *fr)
Definition: btrfs.c:1875
void free_fcb(_Inout_ fcb *fcb)
Definition: btrfs.c:1734
void mark_fileref_dirty(_In_ file_ref *fileref)
Definition: btrfs.c:1717
ULONG get_file_attributes(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t inode, _In_ uint8_t type, _In_ bool dotfile, _In_ bool ignore_xa, _In_opt_ PIRP Irp)
Definition: btrfs.c:2664
bool is_top_level(_In_ PIRP Irp)
Definition: btrfs.c:278
void queue_notification_fcb(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1667
NTSTATUS check_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream)
Definition: btrfs.c:5797
void send_notification_fileref(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1517
void reap_fcb(fcb *fcb)
Definition: btrfs.c:1743
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:76
#define BTRFS_SUBVOL_READONLY
Definition: btrfs.h:109
#define BTRFS_ENCODING_NONE
Definition: btrfs.h:72
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:74
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:75
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:65
#define BTRFS_ROOT_FSTREE
Definition: btrfs.h:58
#define BTRFS_ENCRYPTION_NONE
Definition: btrfs.h:70
#define TYPE_INODE_ITEM
Definition: btrfs.h:23
struct _FILE_STAT_INFORMATION FILE_STAT_INFORMATION
struct _FILE_STAT_INFORMATION * PFILE_STAT_INFORMATION
#define FileStatInformation
Definition: fileinfo.c:28
static NTSTATUS duplicate_fcb(fcb *oldfcb, fcb **pfcb)
Definition: fileinfo.c:463
static NTSTATUS fill_in_hard_link_information(FILE_LINKS_INFORMATION *fli, file_ref *fileref, PIRP Irp, LONG *length)
Definition: fileinfo.c:4535
struct _FILE_ID_INFORMATION FILE_ID_INFORMATION
struct _move_entry move_entry
static NTSTATUS set_link_information(device_extension *Vcb, PIRP Irp, PFILE_OBJECT FileObject, PFILE_OBJECT tfo, bool ex)
Definition: fileinfo.c:3406
#define FILE_RENAME_IGNORE_READONLY_ATTRIBUTE
Definition: fileinfo.c:126
static NTSTATUS fill_in_file_standard_link_information(FILE_STANDARD_LINK_INFORMATION *fsli, fcb *fcb, file_ref *fileref, LONG *length)
Definition: fileinfo.c:4520
static NTSTATUS fill_in_file_internal_information(FILE_INTERNAL_INFORMATION *fii, fcb *fcb, LONG *length)
Definition: fileinfo.c:4214
#define FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK
Definition: fileinfo.c:132
static NTSTATUS fill_in_file_name_information(FILE_NAME_INFORMATION *fni, fcb *fcb, file_ref *fileref, LONG *length)
Definition: fileinfo.c:4332
#define FILE_LINK_IGNORE_READONLY_ATTRIBUTE
Definition: fileinfo.c:140
static NTSTATUS fill_in_file_stream_information(FILE_STREAM_INFORMATION *fsi, file_ref *fileref, LONG *length)
Definition: fileinfo.c:4410
static NTSTATUS fill_in_file_basic_information(FILE_BASIC_INFORMATION *fbi, INODE_ITEM *ii, LONG *length, fcb *fcb, file_ref *fileref)
Definition: fileinfo.c:4111
struct _FILE_CASE_SENSITIVE_INFORMATION FILE_CASE_SENSITIVE_INFORMATION
struct _FILE_CASE_SENSITIVE_INFORMATION * PFILE_CASE_SENSITIVE_INFORMATION
static NTSTATUS fill_in_file_id_information(FILE_ID_INFORMATION *fii, fcb *fcb, LONG *length)
Definition: fileinfo.c:4875
struct _FILE_DISPOSITION_INFORMATION_EX * PFILE_DISPOSITION_INFORMATION_EX
static NTSTATUS fill_in_file_compression_information(FILE_COMPRESSION_INFORMATION *fci, LONG *length, fcb *fcb)
Definition: fileinfo.c:5029
#define FileStorageReserveIdInformation
Definition: fileinfo.c:32
#define FileHardLinkFullIdInformation
Definition: fileinfo.c:25
#define FileCaseSensitiveInformation
Definition: fileinfo.c:30
struct _FILE_RENAME_INFORMATION_EX FILE_RENAME_INFORMATION_EX
#define FILE_DISPOSITION_POSIX_SEMANTICS
Definition: fileinfo.c:131
#define FileIdInformation
Definition: fileinfo.c:24
static NTSTATUS fill_in_file_attribute_information(FILE_ATTRIBUTE_TAG_INFORMATION *ati, fcb *fcb, ccb *ccb, LONG *length)
Definition: fileinfo.c:4389
static NTSTATUS set_end_of_file_information(device_extension *Vcb, PIRP Irp, PFILE_OBJECT FileObject, bool advance_only, bool prealloc)
Definition: fileinfo.c:3240
static NTSTATUS rename_stream(device_extension *Vcb, file_ref *fileref, ccb *ccb, FILE_RENAME_INFORMATION_EX *fri, ULONG flags, PIRP Irp, LIST_ENTRY *rollback)
Definition: fileinfo.c:1856
static NTSTATUS rename_file_to_stream(device_extension *Vcb, file_ref *fileref, ccb *ccb, FILE_RENAME_INFORMATION_EX *fri, ULONG flags, PIRP Irp, LIST_ENTRY *rollback)
Definition: fileinfo.c:2100
#define LX_FILE_METADATA_HAS_DEVICE_ID
Definition: fileinfo.c:76
NTSTATUS stream_set_end_of_file_information(device_extension *Vcb, uint16_t end, fcb *fcb, file_ref *fileref, bool advance_only)
Definition: fileinfo.c:3170
#define LX_FILE_METADATA_HAS_UID
Definition: fileinfo.c:73
struct _FILE_ID_INFORMATION * PFILE_ID_INFORMATION
static NTSTATUS move_across_subvols(file_ref *fileref, ccb *ccb, file_ref *destdir, PANSI_STRING utf8, PUNICODE_STRING fnus, PIRP Irp, LIST_ENTRY *rollback)
Definition: fileinfo.c:950
#define FileRenameInformationEx
Definition: fileinfo.c:27
#define FileDispositionInformationEx
Definition: fileinfo.c:26
#define FILE_DISPOSITION_DELETE
Definition: fileinfo.c:130
static NTSTATUS set_case_sensitive_information(PIRP Irp)
Definition: fileinfo.c:3856
static NTSTATUS rename_stream_to_file(device_extension *Vcb, file_ref *fileref, ccb *ccb, ULONG flags, PIRP Irp, LIST_ENTRY *rollback)
Definition: fileinfo.c:1558
bool has_open_children(file_ref *fileref)
Definition: fileinfo.c:442
#define FILE_LINK_POSIX_SEMANTICS
Definition: fileinfo.c:136
static NTSTATUS fill_in_file_stat_information(FILE_STAT_INFORMATION *fsi, fcb *fcb, ccb *ccb, LONG *length)
Definition: fileinfo.c:4885
static NTSTATUS fill_in_file_ea_information(FILE_EA_INFORMATION *eai, fcb *fcb, LONG *length)
Definition: fileinfo.c:4222
void remove_fcb_from_subvol(_In_ _Requires_exclusive_lock_held_(_Curr_->Vcb->fcb_lock) fcb *fcb)
Definition: fileinfo.c:937
static NTSTATUS set_rename_information(device_extension *Vcb, PIRP Irp, PFILE_OBJECT FileObject, PFILE_OBJECT tfo, bool ex)
Definition: fileinfo.c:2527
#define FILE_RENAME_POSIX_SEMANTICS
Definition: fileinfo.c:121
struct _FILE_LINKS_FULL_ID_INFORMATION * PFILE_LINKS_FULL_ID_INFORMATION
static NTSTATUS set_valid_data_length_information(device_extension *Vcb, PIRP Irp, PFILE_OBJECT FileObject)
Definition: fileinfo.c:3760
#define LX_FILE_CASE_SENSITIVE_DIR
Definition: fileinfo.c:77
#define FILE_RENAME_REPLACE_IF_EXISTS
Definition: fileinfo.c:120
struct _FILE_LINKS_FULL_ID_INFORMATION FILE_LINKS_FULL_ID_INFORMATION
struct _FILE_LINK_ENTRY_FULL_ID_INFORMATION * PFILE_LINK_ENTRY_FULL_ID_INFORMATION
static NTSTATUS set_disposition_information(device_extension *Vcb, PIRP Irp, PFILE_OBJECT FileObject, bool ex)
Definition: fileinfo.c:357
static NTSTATUS fill_in_file_network_open_information(FILE_NETWORK_OPEN_INFORMATION *fnoi, fcb *fcb, file_ref *fileref, LONG *length)
Definition: fileinfo.c:4140
struct _FILE_STAT_LX_INFORMATION * PFILE_STAT_LX_INFORMATION
struct _FILE_DISPOSITION_INFORMATION_EX FILE_DISPOSITION_INFORMATION_EX
static NTSTATUS fill_in_file_stat_lx_information(FILE_STAT_LX_INFORMATION *fsli, fcb *fcb, ccb *ccb, LONG *length)
Definition: fileinfo.c:4944
struct _FILE_STAT_LX_INFORMATION FILE_STAT_LX_INFORMATION
#define FileLinkInformationEx
Definition: fileinfo.c:31
void add_fcb_to_subvol(_In_ _Requires_exclusive_lock_held_(_Curr_->Vcb->fcb_lock) fcb *fcb)
Definition: fileinfo.c:888
static NTSTATUS fill_in_file_standard_information(FILE_STANDARD_INFORMATION *fsi, fcb *fcb, file_ref *fileref, LONG *length)
Definition: fileinfo.c:4186
static NTSTATUS set_basic_information(device_extension *Vcb, PIRP Irp, PFILE_OBJECT FileObject)
Definition: fileinfo.c:190
static NTSTATUS create_directory_fcb(device_extension *Vcb, root *r, fcb *parfcb, fcb **pfcb)
Definition: fileinfo.c:782
NTSTATUS fileref_get_filename(file_ref *fileref, PUNICODE_STRING fn, USHORT *name_offset, ULONG *preqlen)
Definition: fileinfo.c:4245
#define FileStatLxInformation
Definition: fileinfo.c:29
struct _FILE_RENAME_INFORMATION_EX * PFILE_RENAME_INFORMATION_EX
static NTSTATUS add_children_to_move_list(device_extension *Vcb, move_entry *me, PIRP Irp)
Definition: fileinfo.c:701
void insert_dir_child_into_hash_lists(fcb *fcb, dir_child *dc)
Definition: fileinfo.c:1470
struct _FILE_LINK_INFORMATION_EX * PFILE_LINK_INFORMATION_EX
struct _FILE_LINK_ENTRY_FULL_ID_INFORMATION FILE_LINK_ENTRY_FULL_ID_INFORMATION
static NTSTATUS fill_in_hard_link_full_id_information(FILE_LINKS_FULL_ID_INFORMATION *flfii, file_ref *fileref, PIRP Irp, LONG *length)
Definition: fileinfo.c:4704
static NTSTATUS fill_in_file_position_information(FILE_POSITION_INFORMATION *fpi, PFILE_OBJECT FileObject, LONG *length)
Definition: fileinfo.c:4235
#define FILE_LINK_REPLACE_IF_EXISTS
Definition: fileinfo.c:135
static NTSTATUS query_info(device_extension *Vcb, PFILE_OBJECT FileObject, PIRP Irp)
Definition: fileinfo.c:5042
struct _FILE_LINK_INFORMATION_EX FILE_LINK_INFORMATION_EX
void remove_dir_child_from_hash_lists(fcb *fcb, dir_child *dc)
Definition: fileinfo.c:744
static NTSTATUS fill_in_file_case_sensitive_information(FILE_CASE_SENSITIVE_INFORMATION *fcsi, fcb *fcb, LONG *length)
Definition: fileinfo.c:5019
static NTSTATUS set_position_information(PFILE_OBJECT FileObject, PIRP Irp)
Definition: fileinfo.c:3394
#define LX_FILE_METADATA_HAS_GID
Definition: fileinfo.c:74
#define LX_FILE_METADATA_HAS_MODE
Definition: fileinfo.c:75
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define ExAcquireResourceSharedLite(res, wait)
Definition: env_spec_w32.h:621
#define PagedPool
Definition: env_spec_w32.h:308
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
time_t now
Definition: finger.c:65
std::wstring STRING
Definition: fontsub.cpp:33
@ FilePositionInformation
Definition: from_kernel.h:75
@ FileEndOfFileInformation
Definition: from_kernel.h:81
@ FileCompressionInformation
Definition: from_kernel.h:89
@ FileRenameInformation
Definition: from_kernel.h:71
@ FileAllInformation
Definition: from_kernel.h:79
@ FileLinkInformation
Definition: from_kernel.h:72
@ FileInternalInformation
Definition: from_kernel.h:67
@ FileAttributeTagInformation
Definition: from_kernel.h:96
@ FileNormalizedNameInformation
Definition: from_kernel.h:109
@ FileEaInformation
Definition: from_kernel.h:68
@ FileValidDataLengthInformation
Definition: from_kernel.h:100
@ FileNameInformation
Definition: from_kernel.h:70
@ FileAllocationInformation
Definition: from_kernel.h:80
@ FileNetworkOpenInformation
Definition: from_kernel.h:95
@ FileStreamInformation
Definition: from_kernel.h:83
@ FileBasicInformation
Definition: from_kernel.h:65
@ FileDispositionInformation
Definition: from_kernel.h:74
@ FileHardLinkInformation
Definition: from_kernel.h:107
struct _FILE_NETWORK_OPEN_INFORMATION FILE_NETWORK_OPEN_INFORMATION
struct _FILE_INTERNAL_INFORMATION FILE_INTERNAL_INFORMATION
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
VOID NTAPI CcSetFileSizes(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes)
Definition: fssup.c:356
Status
Definition: gdiplustypes.h:25
GLdouble s
Definition: gl.h:2039
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLsizeiptr size
Definition: glext.h:5919
const GLubyte * c
Definition: glext.h:8905
GLint namelen
Definition: glext.h:7232
GLuint index
Definition: glext.h:6031
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint in
Definition: glext.h:9616
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glext.h:7005
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLuint GLfloat * val
Definition: glext.h:7180
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
GLenum GLsizei len
Definition: glext.h:6722
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
@ FileRemoteProtocolInformation
Definition: winternl.h:501
@ FileStandardLinkInformation
Definition: winternl.h:500
struct _FILE_ATTRIBUTE_TAG_INFORMATION FILE_ATTRIBUTE_TAG_INFORMATION
NTSYSAPI ULONG WINAPI RtlLengthSecurityDescriptor(PSECURITY_DESCRIPTOR)
struct _FILE_MODE_INFORMATION FILE_MODE_INFORMATION
struct _FILE_EA_INFORMATION FILE_EA_INFORMATION
struct _FILE_STREAM_INFORMATION FILE_STREAM_INFORMATION
uint32_t entry
Definition: isohybrid.c:63
#define d
Definition: ke_i.h:81
#define c
Definition: ke_i.h:80
if(dx< 0)
Definition: linetemp.h:194
static const WCHAR dc[]
__u16 time
Definition: mkdosfs.c:8
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define FILE_STANDARD_INFORMATION
Definition: disk.h:54
#define FILE_BASIC_INFORMATION
Definition: disk.h:53
@ NormalPagePriority
Definition: imports.h:56
static const BYTE ext2[]
Definition: encode.c:2699
static const DWORD padding[]
Definition: mciwnd.c:89
static PIO_STATUS_BLOCK iosb
Definition: file.c:98
static ATOM item
Definition: dde.c:856
#define min(a, b)
Definition: monoChain.cc:55
#define _Function_class_(x)
Definition: ms_sal.h:2946
#define _In_
Definition: ms_sal.h:308
BYTE uint8_t
Definition: msvideo1.c:66
#define KernelMode
Definition: asm.h:34
#define UserMode
Definition: asm.h:35
DRIVER_DISPATCH(nfs41_FsdDispatch)
#define uint32_t
Definition: nsiface.idl:61
#define uint16_t
Definition: nsiface.idl:60
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define FILE_READ_EA
Definition: nt_native.h:638
struct _FILE_POSITION_INFORMATION FILE_POSITION_INFORMATION
struct _FILE_ALIGNMENT_INFORMATION FILE_ALIGNMENT_INFORMATION
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define FILE_APPEND_DATA
Definition: nt_native.h:634
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define DELETE
Definition: nt_native.h:57
#define FILE_ADD_SUBDIRECTORY
Definition: nt_native.h:635
NTSYSAPI VOID NTAPI RtlUpperString(PSTRING DestinationString, PSTRING SourceString)
#define FILE_ADD_FILE
Definition: nt_native.h:632
#define FILE_WRITE_EA
Definition: nt_native.h:640
#define FILE_ATTRIBUTE_SPARSE_FILE
Definition: ntifs_ex.h:380
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
NTSYSAPI NTSTATUS NTAPI RtlGetOwnerSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PSID *Owner, OUT PBOOLEAN OwnerDefaulted)
Definition: sd.c:257
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
VOID NTAPI FsRtlNotifyFilterReportChange(IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PSTRING FullTargetName, IN USHORT TargetNameOffset, IN PSTRING StreamName OPTIONAL, IN PSTRING NormalizedParentName OPTIONAL, IN ULONG FilterMatch, IN ULONG Action, IN PVOID TargetContext, IN PVOID FilterContext)
Definition: notify.c:997
VOID NTAPI FsRtlNotifyFullChangeDirectory(IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PVOID FsContext, IN PSTRING FullDirectoryName, IN BOOLEAN WatchTree, IN BOOLEAN IgnoreBuffer, IN ULONG CompletionFilter, IN PIRP NotifyIrp, IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL, IN PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL)
Definition: notify.c:1487
PGENERIC_MAPPING NTAPI IoGetFileObjectGenericMapping(VOID)
Definition: file.c:3267
#define IoCompleteRequest
Definition: irp.c:1240
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
NTSTATUS NTAPI IoCheckEaBufferValidity(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: util.c:191
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define STATUS_NONEXISTENT_EA_ENTRY
Definition: ntstatus.h:317
#define STATUS_FILE_CLOSED
Definition: ntstatus.h:532
#define STATUS_NO_EAS_ON_FILE
Definition: ntstatus.h:318
#define STATUS_USER_MAPPED_FILE
Definition: ntstatus.h:711
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define STATUS_NO_MORE_EAS
Definition: ntstatus.h:198
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI FsRtlCheckOplock(IN POPLOCK Oplock, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
Definition: oplock.c:1170
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define Vcb
Definition: cdprocs.h:1415
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
struct _FILE_ACCESS_INFORMATION FILE_ACCESS_INFORMATION
#define FileStandardInformation
Definition: propsheet.cpp:61
#define S_IXGRP
Definition: propsheet.h:49
#define S_IROTH
Definition: propsheet.h:53
#define BTRFS_INODE_COMPRESS
Definition: propsheet.h:87
#define S_ISUID
Definition: propsheet.h:65
#define S_IXOTH
Definition: propsheet.h:61
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
#define S_IRGRP
Definition: propsheet.h:41
#define S_IWOTH
Definition: propsheet.h:57
#define S_IRUSR
Definition: propsheet.h:29
#define S_ISVTX
Definition: propsheet.h:73
#define S_ISGID
Definition: propsheet.h:69
#define S_IWUSR
Definition: propsheet.h:33
#define S_IWGRP
Definition: propsheet.h:45
#define S_IXUSR
Definition: propsheet.h:37
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define IRP_MJ_SET_INFORMATION
Definition: rdpdr.c:49
#define IRP_MJ_QUERY_INFORMATION
Definition: rdpdr.c:48
static __inline uint64_t unix_time_to_win(BTRFS_TIME *t)
Definition: recv.cpp:1067
static FILE * out
Definition: regtests2xml.c:44
#define offsetof(TYPE, MEMBER)
#define exit(n)
Definition: config.h:202
#define memset(x, y, z)
Definition: compat.h:39
BOOLEAN NTAPI MmCanFileBeTruncated(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER NewFileSize)
Definition: section.c:4255
BOOLEAN NTAPI MmFlushImageSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN MMFLUSH_TYPE FlushType)
Definition: section.c:4356
#define STATUS_CANNOT_DELETE
Definition: shellext.h:71
#define BTRFS_TYPE_FILE
Definition: shellext.h:85
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
#define STATUS_SUCCESS
Definition: shellext.h:65
#define BTRFS_TYPE_SOCKET
Definition: shellext.h:90
#define BTRFS_TYPE_FIFO
Definition: shellext.h:89
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:91
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define BTRFS_TYPE_CHARDEV
Definition: shellext.h:87
#define BTRFS_TYPE_BLOCKDEV
Definition: shellext.h:88
#define TRACE(s)
Definition: solgame.cpp:4
uint64_t num_bytes
Definition: btrfs.h:371
uint64_t address
Definition: btrfs.h:368
uint64_t size
Definition: btrfs.h:369
uint64_t offset
Definition: btrfs.h:370
uint8_t data[1]
Definition: btrfs.h:364
uint64_t generation
Definition: btrfs.h:358
uint8_t type
Definition: btrfs.h:363
uint16_t encoding
Definition: btrfs.h:362
uint8_t encryption
Definition: btrfs.h:361
uint8_t compression
Definition: btrfs.h:360
uint64_t decoded_size
Definition: btrfs.h:359
base of all file and directory entries
Definition: entries.h:83
uint64_t st_rdev
Definition: btrfs.h:296
uint32_t st_mode
Definition: btrfs.h:295
uint32_t st_nlink
Definition: btrfs.h:292
uint32_t flags
Definition: btrfs.h:297
BTRFS_TIME otime
Definition: btrfs.h:304
BTRFS_TIME st_mtime
Definition: btrfs.h:303
uint64_t st_size
Definition: btrfs.h:289
uint32_t st_uid
Definition: btrfs.h:293
BTRFS_TIME st_atime
Definition: btrfs.h:301
uint64_t sequence
Definition: btrfs.h:299
BTRFS_TIME st_ctime
Definition: btrfs.h:302
uint64_t transid
Definition: btrfs.h:288
uint32_t st_gid
Definition: btrfs.h:294
uint64_t generation
Definition: btrfs.h:287
uint8_t obj_type
Definition: btrfs.h:145
uint64_t obj_id
Definition: btrfs.h:144
USHORT MaximumLength
Definition: env_spec_w32.h:377
LARGE_INTEGER FileSize
Definition: cctypes.h:16
LARGE_INTEGER ValidDataLength
Definition: cctypes.h:17
LARGE_INTEGER AllocationSize
Definition: cctypes.h:15
FILE_STANDARD_INFORMATION StandardInformation
Definition: winternl.h:797
FILE_EA_INFORMATION EaInformation
Definition: winternl.h:799
FILE_INTERNAL_INFORMATION InternalInformation
Definition: winternl.h:798
FILE_NAME_INFORMATION NameInformation
Definition: winternl.h:804
FILE_POSITION_INFORMATION PositionInformation
Definition: winternl.h:801
FILE_BASIC_INFORMATION BasicInformation
Definition: winternl.h:796
LARGE_INTEGER LastWriteTime
Definition: nt_native.h:941
LARGE_INTEGER CreationTime
Definition: nt_native.h:939
LARGE_INTEGER ChangeTime
Definition: nt_native.h:942
LARGE_INTEGER LastAccessTime
Definition: nt_native.h:940
LARGE_INTEGER CompressedFileSize
Definition: iotypes.h:5849
UCHAR Identifier[16]
Definition: btrfs_drv.h:162
FILE_ID_128 FileId
Definition: fileinfo.c:36
ULONGLONG VolumeSerialNumber
Definition: fileinfo.c:35
Definition: fileinfo.c:107
WCHAR FileName[1]
Definition: fileinfo.c:111
FILE_ID_128 ParentFileId
Definition: fileinfo.c:109
ULONG NextEntryOffset
Definition: fileinfo.c:108
ULONG FileNameLength
Definition: fileinfo.c:110
Definition: iotypes.h:5937
WCHAR FileName[1]
Definition: iotypes.h:5941
ULONG NextEntryOffset
Definition: iotypes.h:5938
ULONG FileNameLength
Definition: iotypes.h:5940
LONGLONG ParentFileId
Definition: iotypes.h:5939
LARGE_INTEGER CurrentByteOffset
Definition: nt_native.h:955
LARGE_INTEGER AllocationSize
Definition: propsheet.cpp:54
LARGE_INTEGER AllocationSize
Definition: fileinfo.c:45
LARGE_INTEGER LastAccessTime
Definition: fileinfo.c:42
ACCESS_MASK EffectiveAccess
Definition: fileinfo.c:50
LARGE_INTEGER ChangeTime
Definition: fileinfo.c:44
LARGE_INTEGER FileId
Definition: fileinfo.c:40
LARGE_INTEGER EndOfFile
Definition: fileinfo.c:46
LARGE_INTEGER LastWriteTime
Definition: fileinfo.c:43
LARGE_INTEGER CreationTime
Definition: fileinfo.c:41
LARGE_INTEGER ChangeTime
Definition: fileinfo.c:58
LARGE_INTEGER CreationTime
Definition: fileinfo.c:55
LARGE_INTEGER FileId
Definition: fileinfo.c:54
LARGE_INTEGER EndOfFile
Definition: fileinfo.c:60
LARGE_INTEGER LastWriteTime
Definition: fileinfo.c:57
LARGE_INTEGER AllocationSize
Definition: fileinfo.c:59
ACCESS_MASK EffectiveAccess
Definition: fileinfo.c:64
LARGE_INTEGER LastAccessTime
Definition: fileinfo.c:56
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
Definition: typedefs.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
USHORT MaximumLength
Definition: env_spec_w32.h:370
bool user_set_change_time
Definition: btrfs_drv.h:390
bool user_set_access_time
Definition: btrfs_drv.h:388
ACCESS_MASK access
Definition: btrfs_drv.h:382
bool user_set_write_time
Definition: btrfs_drv.h:389
bool user_set_creation_time
Definition: btrfs_drv.h:387
file_ref * fileref
Definition: btrfs_drv.h:383
ULONG ea_index
Definition: btrfs_drv.h:385
bool case_sensitive
Definition: btrfs_drv.h:386
bool ads
Definition: btrfs_drv.h:330
bool marked_as_orphan
Definition: btrfs_drv.h:309
LIST_ENTRY list_entry_all
Definition: btrfs_drv.h:337
ULONG ealen
Definition: btrfs_drv.h:303
LIST_ENTRY xattrs
Definition: btrfs_drv.h:308
LIST_ENTRY hardlinks
Definition: btrfs_drv.h:304
bool case_sensitive_set
Definition: btrfs_drv.h:311
LIST_ENTRY dir_children_index
Definition: btrfs_drv.h:314
ULONG atts
Definition: btrfs_drv.h:297
bool atts_deleted
Definition: btrfs_drv.h:322
bool sd_dirty
Definition: btrfs_drv.h:321
bool deleted
Definition: btrfs_drv.h:295
struct _file_ref * fileref
Definition: btrfs_drv.h:305
LIST_ENTRY extents
Definition: btrfs_drv.h:300
uint64_t inode
Definition: btrfs_drv.h:289
SECURITY_DESCRIPTOR * sd
Definition: btrfs_drv.h:293
bool case_sensitive
Definition: btrfs_drv.h:310
ANSI_STRING adsdata
Definition: btrfs_drv.h:334
ANSI_STRING adsxattr
Definition: btrfs_drv.h:333
INODE_ITEM inode_item
Definition: btrfs_drv.h:292
bool created
Definition: btrfs_drv.h:328
LIST_ENTRY dir_children_hash
Definition: btrfs_drv.h:315
LIST_ENTRY ** hash_ptrs_uc
Definition: btrfs_drv.h:318
uint8_t type
Definition: btrfs_drv.h:291
struct _device_extension * Vcb
Definition: btrfs_drv.h:287
LIST_ENTRY dir_children_hash_uc
Definition: btrfs_drv.h:316
struct _root * subvol
Definition: btrfs_drv.h:288
ULONG adsmaxlen
Definition: btrfs_drv.h:332
LIST_ENTRY list_entry
Definition: btrfs_drv.h:336
ANSI_STRING reparse_xattr
Definition: btrfs_drv.h:301
LIST_ENTRY ** hash_ptrs
Definition: btrfs_drv.h:317
bool xattrs_changed
Definition: btrfs_drv.h:327
uint32_t hash
Definition: btrfs_drv.h:290
bool sd_deleted
Definition: btrfs_drv.h:321
uint32_t adshash
Definition: btrfs_drv.h:331
bool reparse_xattr_changed
Definition: btrfs_drv.h:324
LONG refcount
Definition: btrfs_drv.h:285
bool extents_changed
Definition: btrfs_drv.h:323
bool atts_changed
Definition: btrfs_drv.h:322
enum prop_compression_type prop_compression
Definition: btrfs_drv.h:307
bool ea_changed
Definition: btrfs_drv.h:325
struct _fcb_nonpaged * nonpaged
Definition: btrfs_drv.h:284
ANSI_STRING ea_xattr
Definition: btrfs_drv.h:302
bool prop_compression_changed
Definition: btrfs_drv.h:326
bool inode_item_changed
Definition: btrfs_drv.h:306
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:283
bool deleted
Definition: btrfs_drv.h:347
LONG refcount
Definition: btrfs_drv.h:350
struct _file_ref * parent
Definition: btrfs_drv.h:352
fcb * fcb
Definition: btrfs_drv.h:342
dir_child * dc
Definition: btrfs_drv.h:353
bool posix_delete
Definition: btrfs_drv.h:346
uint64_t oldindex
Definition: btrfs_drv.h:344
LIST_ENTRY list_entry
Definition: btrfs_drv.h:357
LIST_ENTRY children
Definition: btrfs_drv.h:349
LONG open_count
Definition: btrfs_drv.h:351
bool delete_on_close
Definition: btrfs_drv.h:345
ANSI_STRING oldutf8
Definition: btrfs_drv.h:343
bool created
Definition: btrfs_drv.h:348
Definition: fileinfo.c:693
fcb * dummyfcb
Definition: fileinfo.c:695
LIST_ENTRY list_entry
Definition: fileinfo.c:698
file_ref * dummyfileref
Definition: fileinfo.c:696
file_ref * fileref
Definition: fileinfo.c:694
struct _move_entry * parent
Definition: fileinfo.c:697
char * name
Definition: compiler.c:66
LIST_ENTRY list_entry_hash_uc
Definition: btrfs_drv.h:264
UNICODE_STRING name
Definition: btrfs_drv.h:256
uint32_t hash
Definition: btrfs_drv.h:255
UNICODE_STRING name_uc
Definition: btrfs_drv.h:258
LIST_ENTRY list_entry_hash
Definition: btrfs_drv.h:263
ANSI_STRING utf8
Definition: btrfs_drv.h:254
struct _file_ref * fileref
Definition: btrfs_drv.h:260
uint64_t index
Definition: btrfs_drv.h:252
LIST_ENTRY list_entry_index
Definition: btrfs_drv.h:262
uint32_t hash_uc
Definition: btrfs_drv.h:257
Definition: comerr.c:44
Definition: _hash_fun.h:40
Definition: list.h:27
Definition: name.c:39
bool dirty
Definition: btrfs_drv.h:278
USHORT namelen
Definition: btrfs_drv.h:276
char data[1]
Definition: btrfs_drv.h:279
USHORT valuelen
Definition: btrfs_drv.h:277
LIST_ENTRY list_entry
Definition: btrfs_drv.h:275
VOID NTAPI SeReleaseSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Releases both the primary and client tokens of a security subject context.
Definition: subject.c:171
VOID NTAPI SeCaptureSubjectContext(_Out_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Captures the security subject context of the calling thread and calling process.
Definition: subject.c:85
#define max(a, b)
Definition: svc.c:63
int64_t LONGLONG
Definition: typedefs.h:68
#define __stdcall
Definition: typedefs.h:25
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define STATUS_DIRECTORY_NOT_EMPTY
Definition: udferr_usr.h:167
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_FILE_IS_A_DIRECTORY
Definition: udferr_usr.h:164
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_TOO_MANY_LINKS
Definition: udferr_usr.h:184
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
struct _FILE_COMPRESSION_INFORMATION FILE_COMPRESSION_INFORMATION
#define FILE_ACTION_MODIFIED_STREAM
#define FILE_NOTIFY_CHANGE_SIZE
struct _FILE_LINK_ENTRY_INFORMATION FILE_LINK_ENTRY_INFORMATION
#define IRP_MJ_QUERY_EA
#define SL_INDEX_SPECIFIED
Definition: iotypes.h:1837
#define VPB_MOUNTED
Definition: iotypes.h:1807
#define FILE_ACTION_MODIFIED
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define IRP_PAGING_IO
#define FILE_ACTION_RENAMED_OLD_NAME
#define FILE_NOTIFY_CHANGE_LAST_ACCESS
#define FILE_NOTIFY_CHANGE_ATTRIBUTES
#define FILE_ACTION_REMOVED
#define SL_RETURN_SINGLE_ENTRY
Definition: iotypes.h:1836
struct _FILE_STANDARD_LINK_INFORMATION FILE_STANDARD_LINK_INFORMATION
#define FILE_NOTIFY_CHANGE_FILE_NAME
#define IRP_MJ_SET_EA
#define FILE_NOTIFY_CHANGE_STREAM_SIZE
* PFILE_OBJECT
Definition: iotypes.h:1998
#define FILE_ACTION_RENAMED_NEW_NAME
#define FILE_NOTIFY_CHANGE_CREATION
#define FILE_NOTIFY_CHANGE_LAST_WRITE
#define FILE_NOTIFY_CHANGE_EA
#define SL_RESTART_SCAN
Definition: iotypes.h:1835
#define FILE_ACTION_ADDED
#define FILE_NOTIFY_CHANGE_DIR_NAME
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180