ReactOS 0.4.15-dev-8102-g108db8f
reparse.c File Reference
#include "btrfs_drv.h"
Include dependency graph for reparse.c:

Go to the source code of this file.

Classes

struct  REPARSE_DATA_BUFFER_LX_SYMLINK
 

Functions

NTSTATUS get_reparse_point (PFILE_OBJECT FileObject, void *buffer, DWORD buflen, ULONG_PTR *retlen)
 
static NTSTATUS set_symlink (PIRP Irp, file_ref *fileref, fcb *fcb, ccb *ccb, REPARSE_DATA_BUFFER *rdb, ULONG buflen, LIST_ENTRY *rollback)
 
NTSTATUS set_reparse_point2 (fcb *fcb, REPARSE_DATA_BUFFER *rdb, ULONG buflen, ccb *ccb, file_ref *fileref, PIRP Irp, LIST_ENTRY *rollback)
 
NTSTATUS set_reparse_point (PIRP Irp)
 
NTSTATUS delete_reparse_point (PIRP Irp)
 

Variables

tFsRtlValidateReparsePointBuffer fFsRtlValidateReparsePointBuffer
 

Function Documentation

◆ delete_reparse_point()

NTSTATUS delete_reparse_point ( PIRP  Irp)

Definition at line 482 of file reparse.c.

482 {
485 REPARSE_DATA_BUFFER* rdb = Irp->AssociatedIrp.SystemBuffer;
486 DWORD buflen = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
488 fcb* fcb;
489 ccb* ccb;
490 file_ref* fileref;
492
493 TRACE("(%p)\n", Irp);
494
496
497 if (!FileObject) {
498 ERR("FileObject was NULL\n");
500 }
501
502 fcb = FileObject->FsContext;
503
504 if (!fcb) {
505 ERR("fcb was NULL\n");
507 }
508
509 ccb = FileObject->FsContext2;
510
511 if (!ccb) {
512 ERR("ccb was NULL\n");
514 }
515
516 if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_WRITE_ATTRIBUTES)) {
517 WARN("insufficient privileges\n");
519 }
520
521 fileref = ccb->fileref;
522
523 if (!fileref) {
524 ERR("fileref was NULL\n");
526 }
527
528 ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, true);
530
531 if (buflen < offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer)) {
532 ERR("buffer was too short\n");
534 goto end;
535 }
536
537 if (rdb->ReparseDataLength > 0) {
538 WARN("rdb->ReparseDataLength was not zero\n");
540 goto end;
541 }
542
543 if (fcb->ads) {
544 WARN("tried to delete reparse point on ADS\n");
546 goto end;
547 }
548
549 if (fcb->type == BTRFS_TYPE_SYMLINK) {
552
554 WARN("reparse tag was not IO_REPARSE_TAG_SYMLINK\n");
556 goto end;
557 }
558
561
562 fileref->fcb->type = BTRFS_TYPE_FILE;
563 fileref->fcb->inode_item.st_mode &= ~__S_IFLNK;
564 fileref->fcb->inode_item.st_mode |= __S_IFREG;
565 fileref->fcb->inode_item.generation = fileref->fcb->Vcb->superblock.generation; // so we don't confuse btrfs send on Linux
566 fileref->fcb->inode_item.transid = fileref->fcb->Vcb->superblock.generation;
567 fileref->fcb->inode_item.sequence++;
568
570 fileref->fcb->inode_item.st_ctime = now;
571
573 fileref->fcb->inode_item.st_mtime = now;
574
575 fileref->fcb->atts &= ~FILE_ATTRIBUTE_REPARSE_POINT;
576
577 if (fileref->dc)
578 fileref->dc->type = fileref->fcb->type;
579
580 mark_fileref_dirty(fileref);
581
582 fileref->fcb->inode_item_changed = true;
583 mark_fcb_dirty(fileref->fcb);
584
585 fileref->fcb->subvol->root_item.ctransid = fcb->Vcb->superblock.generation;
586 fileref->fcb->subvol->root_item.ctime = now;
587 } else if (fcb->type == BTRFS_TYPE_FILE) {
590
591 // FIXME - do we need to check that the reparse tags match?
592
594 if (!NT_SUCCESS(Status)) {
595 ERR("truncate_file returned %08lx\n", Status);
596 goto end;
597 }
598
599 fcb->atts &= ~FILE_ATTRIBUTE_REPARSE_POINT;
600 fcb->atts_changed = true;
601
604
605 fcb->inode_item.transid = fcb->Vcb->superblock.generation;
607
610
613
614 fcb->inode_item_changed = true;
616
617 fcb->subvol->root_item.ctransid = fcb->Vcb->superblock.generation;
618 fcb->subvol->root_item.ctime = now;
619 } else if (fcb->type == BTRFS_TYPE_DIRECTORY) {
622
623 // FIXME - do we need to check that the reparse tags match?
624
625 fcb->atts &= ~FILE_ATTRIBUTE_REPARSE_POINT;
626 fcb->atts_changed = true;
627
628 if (fcb->reparse_xattr.Buffer) {
631 }
632
634
637
638 fcb->inode_item.transid = fcb->Vcb->superblock.generation;
640
643
646
647 fcb->inode_item_changed = true;
649
650 fcb->subvol->root_item.ctransid = fcb->Vcb->superblock.generation;
651 fcb->subvol->root_item.ctime = now;
652 } else {
653 ERR("unsupported file type %u\n", fcb->type);
655 goto end;
656 }
657
659
661
662end:
663 if (NT_SUCCESS(Status))
665 else
667
669 ExReleaseResourceLite(&fcb->Vcb->tree_lock);
670
671 return Status;
672}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
LONG NTSTATUS
Definition: precomp.h:26
#define WARN(fmt,...)
Definition: debug.h:115
#define ERR(fmt,...)
Definition: debug.h:113
_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 __S_IFREG
Definition: btrfs_drv.h:1757
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:989
struct _fcb fcb
Definition: btrfs_drv.h:1364
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback) __attribute__((nonnull(1
NTSTATUS NTSTATUS NTSTATUS truncate_file(fcb *fcb, uint64_t end, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
struct _ccb ccb
NTSTATUS NTSTATUS void clear_rollback(LIST_ENTRY *rollback) __attribute__((nonnull(1)))
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1695
void mark_fileref_dirty(_In_ file_ref *fileref)
Definition: btrfs.c:1717
void queue_notification_fcb(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1667
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
#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 InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define ExAcquireResourceSharedLite(res, wait)
Definition: env_spec_w32.h:621
unsigned long DWORD
Definition: ntddk_ex.h:95
time_t now
Definition: finger.c:65
Status
Definition: gdiplustypes.h:25
GLuint GLuint end
Definition: gl.h:1545
__u16 time
Definition: mkdosfs.c:8
#define UserMode
Definition: asm.h:35
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
#define offsetof(TYPE, MEMBER)
#define BTRFS_TYPE_FILE
Definition: shellext.h:85
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
#define STATUS_SUCCESS
Definition: shellext.h:65
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:91
#define TRACE(s)
Definition: solgame.cpp:4
uint32_t st_mode
Definition: btrfs.h:295
BTRFS_TIME st_mtime
Definition: btrfs.h:303
uint64_t sequence
Definition: btrfs.h:299
BTRFS_TIME st_ctime
Definition: btrfs.h:302
uint64_t transid
Definition: btrfs.h:288
uint64_t generation
Definition: btrfs.h:287
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
union _IO_STACK_LOCATION::@1567 Parameters
struct _IO_STACK_LOCATION::@1567::@1568 DeviceIoControl
Definition: typedefs.h:120
USHORT ReparseDataLength
Definition: shellext.h:166
UCHAR DataBuffer[1]
Definition: shellext.h:188
bool user_set_change_time
Definition: btrfs_drv.h:390
ACCESS_MASK access
Definition: btrfs_drv.h:382
bool user_set_write_time
Definition: btrfs_drv.h:389
file_ref * fileref
Definition: btrfs_drv.h:383
bool ads
Definition: btrfs_drv.h:330
ULONG atts
Definition: btrfs_drv.h:297
INODE_ITEM inode_item
Definition: btrfs_drv.h:292
uint8_t type
Definition: btrfs_drv.h:291
struct _device_extension * Vcb
Definition: btrfs_drv.h:287
struct _root * subvol
Definition: btrfs_drv.h:288
ANSI_STRING reparse_xattr
Definition: btrfs_drv.h:301
bool reparse_xattr_changed
Definition: btrfs_drv.h:324
bool atts_changed
Definition: btrfs_drv.h:322
bool inode_item_changed
Definition: btrfs_drv.h:306
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:283
fcb * fcb
Definition: btrfs_drv.h:342
dir_child * dc
Definition: btrfs_drv.h:353
uint8_t type
Definition: btrfs_drv.h:253
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
#define FILE_ACTION_MODIFIED
#define FILE_NOTIFY_CHANGE_ATTRIBUTES
* PFILE_OBJECT
Definition: iotypes.h:1998
#define IO_REPARSE_TAG_SYMLINK
Definition: iotypes.h:7240
#define FILE_NOTIFY_CHANGE_LAST_WRITE

Referenced by fsctl_request().

◆ get_reparse_point()

NTSTATUS get_reparse_point ( PFILE_OBJECT  FileObject,
void buffer,
DWORD  buflen,
ULONG_PTR retlen 
)

Definition at line 27 of file reparse.c.

27 {
28 USHORT subnamelen, printnamelen, i;
30 DWORD reqlen;
32 fcb* fcb = FileObject->FsContext;
33 ccb* ccb = FileObject->FsContext2;
35
36 TRACE("(%p, %p, %lx, %p)\n", FileObject, buffer, buflen, retlen);
37
38 if (!ccb)
40
41 ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, true);
42 ExAcquireResourceSharedLite(fcb->Header.Resource, true);
43
44 if (fcb->type == BTRFS_TYPE_SYMLINK) {
45 if (ccb->lxss) {
46 reqlen = offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + sizeof(uint32_t);
47
48 if (buflen < reqlen) {
50 goto end;
51 }
52
54 rdb->ReparseDataLength = offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + sizeof(uint32_t);
55 rdb->Reserved = 0;
56
57 *((uint32_t*)rdb->GenericReparseBuffer.DataBuffer) = 1;
58
59 *retlen = reqlen;
60 } else {
61 char* data;
62
63 if (fcb->inode_item.st_size == 0 || fcb->inode_item.st_size > 0xffff) {
65 goto end;
66 }
67
69 if (!data) {
70 ERR("out of memory\n");
72 goto end;
73 }
74
75 TRACE("data = %p, size = %I64x\n", data, fcb->inode_item.st_size);
77
78 if (!NT_SUCCESS(Status)) {
79 ERR("read_file returned %08lx\n", Status);
81 goto end;
82 }
83
85 if (!NT_SUCCESS(Status)) {
86 ERR("utf8_to_utf16 1 returned %08lx\n", Status);
88 goto end;
89 }
90
91 subnamelen = (uint16_t)stringlen;
92 printnamelen = (uint16_t)stringlen;
93
94 reqlen = offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + subnamelen + printnamelen;
95
96 if (buflen >= offsetof(REPARSE_DATA_BUFFER, ReparseDataLength))
98
100 rdb->ReparseDataLength = (USHORT)(reqlen - offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer));
101
102 if (buflen >= offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.SubstituteNameOffset))
103 rdb->Reserved = 0;
104
105 if (buflen < reqlen) {
108 *retlen = min(buflen, offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.SubstituteNameOffset));
109 goto end;
110 }
111
112 rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
113 rdb->SymbolicLinkReparseBuffer.SubstituteNameLength = subnamelen;
114 rdb->SymbolicLinkReparseBuffer.PrintNameOffset = subnamelen;
115 rdb->SymbolicLinkReparseBuffer.PrintNameLength = printnamelen;
117
118 Status = utf8_to_utf16(&rdb->SymbolicLinkReparseBuffer.PathBuffer[rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)],
120
121 if (!NT_SUCCESS(Status)) {
122 ERR("utf8_to_utf16 2 returned %08lx\n", Status);
124 goto end;
125 }
126
127 for (i = 0; i < stringlen / sizeof(WCHAR); i++) {
128 if (rdb->SymbolicLinkReparseBuffer.PathBuffer[(rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)) + i] == '/')
129 rdb->SymbolicLinkReparseBuffer.PathBuffer[(rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)) + i] = '\\';
130 }
131
132 RtlCopyMemory(&rdb->SymbolicLinkReparseBuffer.PathBuffer[rdb->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(WCHAR)],
133 &rdb->SymbolicLinkReparseBuffer.PathBuffer[rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)],
134 rdb->SymbolicLinkReparseBuffer.SubstituteNameLength);
135
136 *retlen = reqlen;
137
139 }
140
142 } else if (fcb->atts & FILE_ATTRIBUTE_REPARSE_POINT) {
143 if (fcb->type == BTRFS_TYPE_FILE) {
144 ULONG len;
145
146 Status = read_file(fcb, buffer, 0, buflen, &len, NULL);
147
148 if (!NT_SUCCESS(Status)) {
149 ERR("read_file returned %08lx\n", Status);
150 }
151
152 *retlen = len;
153 } else if (fcb->type == BTRFS_TYPE_DIRECTORY) {
154 if (!fcb->reparse_xattr.Buffer || fcb->reparse_xattr.Length < sizeof(ULONG)) {
156 goto end;
157 }
158
159 if (buflen > 0) {
160 *retlen = min(buflen, fcb->reparse_xattr.Length);
162 } else
163 *retlen = 0;
164
166 } else
168 } else {
170 }
171
172end:
174 ExReleaseResourceLite(&fcb->Vcb->tree_lock);
175
176 return Status;
177}
NTSTATUS read_file(fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp) __attribute__((nonnull(1
#define ALLOC_TAG
Definition: btrfs_drv.h:87
#define IO_REPARSE_TAG_LX_SYMLINK
Definition: btrfs_drv.h:118
UINT32 uint32_t
Definition: types.h:75
wstring utf8_to_utf16(const string_view &utf8)
Definition: main.cpp:734
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PagedPool
Definition: env_spec_w32.h:308
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint const GLchar GLint stringlen
Definition: glext.h:7232
GLuint buffer
Definition: glext.h:5915
GLenum GLsizei len
Definition: glext.h:6722
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
if(dx< 0)
Definition: linetemp.h:194
#define min(a, b)
Definition: monoChain.cc:55
BYTE uint8_t
Definition: msvideo1.c:66
#define uint32_t
Definition: nsiface.idl:61
#define uint16_t
Definition: nsiface.idl:60
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
#define STATUS_NOT_A_REPARSE_POINT
Definition: ntstatus.h:753
unsigned short USHORT
Definition: pedump.c:61
#define SYMLINK_FLAG_RELATIVE
Definition: shellext.h:193
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
uint64_t st_size
Definition: btrfs.h:289
WCHAR PathBuffer[1]
Definition: shellext.h:176
struct _REPARSE_DATA_BUFFER::@320::@324 GenericReparseBuffer
USHORT SubstituteNameOffset
Definition: shellext.h:171
struct _REPARSE_DATA_BUFFER::@320::@322 SymbolicLinkReparseBuffer
bool lxss
Definition: btrfs_drv.h:391
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Reserved_ PVOID Reserved
Definition: winddi.h:3974
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by fsctl_request().

◆ set_reparse_point()

NTSTATUS set_reparse_point ( PIRP  Irp)

Definition at line 409 of file reparse.c.

409 {
412 void* buffer = Irp->AssociatedIrp.SystemBuffer;
414 DWORD buflen = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
416 fcb* fcb;
417 ccb* ccb;
418 file_ref* fileref;
420
421 TRACE("(%p)\n", Irp);
422
424
425 if (!FileObject) {
426 ERR("FileObject was NULL\n");
428 }
429
430 // IFSTest insists on this, for some reason...
431 if (Irp->UserBuffer)
433
434 fcb = FileObject->FsContext;
435 ccb = FileObject->FsContext2;
436
437 if (!ccb) {
438 ERR("ccb was NULL\n");
440 }
441
442 if (Irp->RequestorMode == UserMode && !(ccb->access & (FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA))) {
443 WARN("insufficient privileges\n");
445 }
446
447 fileref = ccb->fileref;
448
449 if (!fileref) {
450 ERR("fileref was NULL\n");
452 }
453
454 if (fcb->ads) {
455 fileref = fileref->parent;
456 fcb = fileref->fcb;
457 }
458
459 ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, true);
461
462 Status = set_reparse_point2(fcb, rdb, buflen, ccb, fileref, Irp, &rollback);
463 if (!NT_SUCCESS(Status)) {
464 ERR("set_reparse_point2 returned %08lx\n", Status);
465 goto end;
466 }
467
469
470end:
471 if (NT_SUCCESS(Status))
473 else
475
477 ExReleaseResourceLite(&fcb->Vcb->tree_lock);
478
479 return Status;
480}
#define FILE_WRITE_DATA
Definition: nt_native.h:631
NTSTATUS set_reparse_point2(fcb *fcb, REPARSE_DATA_BUFFER *rdb, ULONG buflen, ccb *ccb, file_ref *fileref, PIRP Irp, LIST_ENTRY *rollback)
Definition: reparse.c:307
struct _file_ref * parent
Definition: btrfs_drv.h:352

Referenced by fsctl_request().

◆ set_reparse_point2()

NTSTATUS set_reparse_point2 ( fcb fcb,
REPARSE_DATA_BUFFER rdb,
ULONG  buflen,
ccb ccb,
file_ref fileref,
PIRP  Irp,
LIST_ENTRY rollback 
)

Definition at line 307 of file reparse.c.

307 {
309 ULONG tag;
310
311 if (fcb->type == BTRFS_TYPE_SYMLINK) {
312 WARN("tried to set a reparse point on an existing symlink\n");
314 }
315
316 // FIXME - fail if we already have the attribute FILE_ATTRIBUTE_REPARSE_POINT
317
318 // FIXME - die if not file or directory
319
321 TRACE("directory not empty\n");
323 }
324
325 if (buflen < sizeof(ULONG)) {
326 WARN("buffer was not long enough to hold tag\n");
328 }
329
331 if (!NT_SUCCESS(Status)) {
332 ERR("FsRtlValidateReparsePointBuffer returned %08lx\n", Status);
333 return Status;
334 }
335
336 tag = *(ULONG*)rdb;
337
340
341 if (fcb->type == BTRFS_TYPE_FILE &&
343 Status = set_symlink(Irp, fileref, fcb, ccb, rdb, buflen, rollback);
345 } else {
348
349 if (fcb->type == BTRFS_TYPE_DIRECTORY || fcb->type == BTRFS_TYPE_CHARDEV || fcb->type == BTRFS_TYPE_BLOCKDEV) { // store as xattr
351
352 buf.Buffer = ExAllocatePoolWithTag(PagedPool, buflen, ALLOC_TAG);
353 if (!buf.Buffer) {
354 ERR("out of memory\n");
356 }
357 buf.Length = buf.MaximumLength = (uint16_t)buflen;
358
361
363 RtlCopyMemory(buf.Buffer, rdb, buflen);
364
366
368 } else { // otherwise, store as file data
370 if (!NT_SUCCESS(Status)) {
371 ERR("truncate_file returned %08lx\n", Status);
372 return Status;
373 }
374
375 offset.QuadPart = 0;
376
377 Status = write_file2(fcb->Vcb, Irp, offset, rdb, &buflen, false, true, true, false, false, rollback);
378 if (!NT_SUCCESS(Status)) {
379 ERR("write_file2 returned %08lx\n", Status);
380 return Status;
381 }
382 }
383
386
387 fcb->inode_item.transid = fcb->Vcb->superblock.generation;
389
390 if (!ccb || !ccb->user_set_change_time)
392
393 if (!ccb || !ccb->user_set_write_time)
395
397 fcb->atts_changed = true;
398
399 fcb->subvol->root_item.ctransid = fcb->Vcb->superblock.generation;
400 fcb->subvol->root_item.ctime = now;
401
402 fcb->inode_item_changed = true;
404 }
405
406 return STATUS_SUCCESS;
407}
NTSTATUS NTSTATUS write_file2(device_extension *Vcb, PIRP Irp, LARGE_INTEGER offset, void *buf, ULONG *length, bool paging_io, bool no_cache, bool wait, bool deferred_write, bool write_irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLintptr offset
Definition: glext.h:5920
#define STATUS_INVALID_BUFFER_SIZE
Definition: ntstatus.h:650
static NTSTATUS set_symlink(PIRP Irp, file_ref *fileref, fcb *fcb, ccb *ccb, REPARSE_DATA_BUFFER *rdb, ULONG buflen, LIST_ENTRY *rollback)
Definition: reparse.c:179
tFsRtlValidateReparsePointBuffer fFsRtlValidateReparsePointBuffer
Definition: btrfs.c:98
#define BTRFS_TYPE_CHARDEV
Definition: shellext.h:87
#define BTRFS_TYPE_BLOCKDEV
Definition: shellext.h:88
Definition: ecma_167.h:138
#define STATUS_DIRECTORY_NOT_EMPTY
Definition: udferr_usr.h:167
#define STATUS_NOT_A_DIRECTORY
Definition: udferr_usr.h:169
#define IO_REPARSE_TAG_MOUNT_POINT
Definition: iotypes.h:7231

Referenced by file_create(), and set_reparse_point().

◆ set_symlink()

static NTSTATUS set_symlink ( PIRP  Irp,
file_ref fileref,
fcb fcb,
ccb ccb,
REPARSE_DATA_BUFFER rdb,
ULONG  buflen,
LIST_ENTRY rollback 
)
static

Definition at line 179 of file reparse.c.

179 {
181 ULONG tlength;
183 bool target_alloc = false;
186
188 UNICODE_STRING subname;
189 ULONG minlen, len;
190
191 minlen = offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + sizeof(WCHAR);
192 if (buflen < minlen) {
193 WARN("buffer was less than minimum length (%lu < %lu)\n", buflen, minlen);
195 }
196
197 if (rdb->SymbolicLinkReparseBuffer.SubstituteNameLength < sizeof(WCHAR)) {
198 WARN("rdb->SymbolicLinkReparseBuffer.SubstituteNameLength was too short\n");
200 }
201
202 subname.Buffer = &rdb->SymbolicLinkReparseBuffer.PathBuffer[rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)];
203 subname.MaximumLength = subname.Length = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength;
204
205 TRACE("substitute name = %.*S\n", (int)(subname.Length / sizeof(WCHAR)), subname.Buffer);
206
207 Status = utf16_to_utf8(NULL, 0, &len, subname.Buffer, subname.Length);
208 if (!NT_SUCCESS(Status)) {
209 ERR("utf16_to_utf8 1 failed with error %08lx\n", Status);
210 return Status;
211 }
212
213 target.MaximumLength = target.Length = (USHORT)len;
214 target.Buffer = ExAllocatePoolWithTag(PagedPool, target.MaximumLength, ALLOC_TAG);
215 if (!target.Buffer) {
216 ERR("out of memory\n");
218 }
219
220 target_alloc = true;
221
222 Status = utf16_to_utf8(target.Buffer, target.Length, &len, subname.Buffer, subname.Length);
223 if (!NT_SUCCESS(Status)) {
224 ERR("utf16_to_utf8 2 failed with error %08lx\n", Status);
225 ExFreePool(target.Buffer);
226 return Status;
227 }
228
229 for (USHORT i = 0; i < target.Length; i++) {
230 if (target.Buffer[i] == '\\')
231 target.Buffer[i] = '/';
232 }
233 } else if (rdb->ReparseTag == IO_REPARSE_TAG_LX_SYMLINK) {
235
236 if (buflen < offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + rdb->ReparseDataLength) {
237 WARN("buffer was less than expected length (%lu < %lu)\n", buflen,
238 (unsigned long)(offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + rdb->ReparseDataLength));
240 }
241
243
245 WARN("buffer was less than minimum length (%u < %lu)\n", rdb->ReparseDataLength,
246 (unsigned long)(offsetof(REPARSE_DATA_BUFFER_LX_SYMLINK, name)));
248 }
249
250 target.Buffer = buf->name;
252 } else {
253 ERR("unexpected reparse tag %08lx\n", rdb->ReparseTag);
255 }
256
258 fcb->inode_item.st_mode &= ~__S_IFMT;
260 fcb->inode_item.generation = fcb->Vcb->superblock.generation; // so we don't confuse btrfs send on Linux
261
262 if (fileref && fileref->dc)
263 fileref->dc->type = fcb->type;
264
266 if (!NT_SUCCESS(Status)) {
267 ERR("truncate_file returned %08lx\n", Status);
268
269 if (target_alloc)
270 ExFreePool(target.Buffer);
271
272 return Status;
273 }
274
275 offset.QuadPart = 0;
276 tlength = target.Length;
277 Status = write_file2(fcb->Vcb, Irp, offset, target.Buffer, &tlength, false, true,
278 true, false, false, rollback);
279
280 if (target_alloc)
281 ExFreePool(target.Buffer);
282
285
286 fcb->inode_item.transid = fcb->Vcb->superblock.generation;
288
289 if (!ccb || !ccb->user_set_change_time)
291
292 if (!ccb || !ccb->user_set_write_time)
294
295 fcb->subvol->root_item.ctransid = fcb->Vcb->superblock.generation;
296 fcb->subvol->root_item.ctime = now;
297
298 fcb->inode_item_changed = true;
300
301 if (fileref)
302 mark_fileref_dirty(fileref);
303
304 return Status;
305}
#define __S_IFLNK
Definition: btrfs_drv.h:1759
static string utf16_to_utf8(const wstring_view &utf16)
Definition: main.cpp:670
GLenum target
Definition: glext.h:7315
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
USHORT MaximumLength
Definition: env_spec_w32.h:370
char * name
Definition: compiler.c:66
Definition: name.c:39

Referenced by set_reparse_point2().

Variable Documentation

◆ fFsRtlValidateReparsePointBuffer

tFsRtlValidateReparsePointBuffer fFsRtlValidateReparsePointBuffer
extern

Definition at line 98 of file btrfs.c.

Referenced by _Function_class_(), and set_reparse_point2().