ReactOS  0.4.14-dev-317-g96040ec
reparse.c File Reference
#include "btrfs_drv.h"
Include dependency graph for reparse.c:

Go to the source code of this file.

Functions

NTSTATUS get_reparse_point (PDEVICE_OBJECT DeviceObject, 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, bool write, 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 (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 
NTSTATUS delete_reparse_point (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 

Variables

tFsRtlValidateReparsePointBuffer fFsRtlValidateReparsePointBuffer
 

Function Documentation

◆ delete_reparse_point()

NTSTATUS delete_reparse_point ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp 
)

Definition at line 440 of file reparse.c.

440  {
443  REPARSE_DATA_BUFFER* rdb = Irp->AssociatedIrp.SystemBuffer;
444  DWORD buflen = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
446  fcb* fcb;
447  ccb* ccb;
448  file_ref* fileref;
450 
451  TRACE("(%p, %p)\n", DeviceObject, Irp);
452 
454 
455  if (!FileObject) {
456  ERR("FileObject was NULL\n");
458  }
459 
460  fcb = FileObject->FsContext;
461 
462  if (!fcb) {
463  ERR("fcb was NULL\n");
465  }
466 
467  ccb = FileObject->FsContext2;
468 
469  if (!ccb) {
470  ERR("ccb was NULL\n");
472  }
473 
474  if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_WRITE_ATTRIBUTES)) {
475  WARN("insufficient privileges\n");
476  return STATUS_ACCESS_DENIED;
477  }
478 
479  fileref = ccb->fileref;
480 
481  if (!fileref) {
482  ERR("fileref was NULL\n");
484  }
485 
486  ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, true);
487  ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
488 
489  if (buflen < offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer)) {
490  ERR("buffer was too short\n");
492  goto end;
493  }
494 
495  if (rdb->ReparseDataLength > 0) {
496  WARN("rdb->ReparseDataLength was not zero\n");
498  goto end;
499  }
500 
501  if (fcb->ads) {
502  WARN("tried to delete reparse point on ADS\n");
504  goto end;
505  }
506 
507  if (fcb->type == BTRFS_TYPE_SYMLINK) {
509  BTRFS_TIME now;
510 
511  if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK) {
512  WARN("reparse tag was not IO_REPARSE_TAG_SYMLINK\n");
514  goto end;
515  }
516 
519 
520  fileref->fcb->type = BTRFS_TYPE_FILE;
521  fileref->fcb->inode_item.st_mode &= ~__S_IFLNK;
522  fileref->fcb->inode_item.st_mode |= __S_IFREG;
523  fileref->fcb->inode_item.generation = fileref->fcb->Vcb->superblock.generation; // so we don't confuse btrfs send on Linux
524  fileref->fcb->inode_item.transid = fileref->fcb->Vcb->superblock.generation;
525  fileref->fcb->inode_item.sequence++;
526 
528  fileref->fcb->inode_item.st_ctime = now;
529 
530  if (!ccb->user_set_write_time)
531  fileref->fcb->inode_item.st_mtime = now;
532 
533  fileref->fcb->atts &= ~FILE_ATTRIBUTE_REPARSE_POINT;
534 
535  if (fileref->dc)
536  fileref->dc->type = fileref->fcb->type;
537 
538  mark_fileref_dirty(fileref);
539 
540  fileref->fcb->inode_item_changed = true;
541  mark_fcb_dirty(fileref->fcb);
542 
543  fileref->fcb->subvol->root_item.ctransid = fcb->Vcb->superblock.generation;
544  fileref->fcb->subvol->root_item.ctime = now;
545  } else if (fcb->type == BTRFS_TYPE_FILE) {
547  BTRFS_TIME now;
548 
549  // FIXME - do we need to check that the reparse tags match?
550 
552  if (!NT_SUCCESS(Status)) {
553  ERR("truncate_file returned %08x\n", Status);
554  goto end;
555  }
556 
558  fcb->atts_changed = true;
559 
562 
563  fcb->inode_item.transid = fcb->Vcb->superblock.generation;
565 
568 
569  if (!ccb->user_set_write_time)
571 
572  fcb->inode_item_changed = true;
574 
575  fcb->subvol->root_item.ctransid = fcb->Vcb->superblock.generation;
576  fcb->subvol->root_item.ctime = now;
577  } else if (fcb->type == BTRFS_TYPE_DIRECTORY) {
579  BTRFS_TIME now;
580 
581  // FIXME - do we need to check that the reparse tags match?
582 
584  fcb->atts_changed = true;
585 
586  if (fcb->reparse_xattr.Buffer) {
589  }
590 
591  fcb->reparse_xattr_changed = true;
592 
595 
596  fcb->inode_item.transid = fcb->Vcb->superblock.generation;
598 
601 
602  if (!ccb->user_set_write_time)
604 
605  fcb->inode_item_changed = true;
607 
608  fcb->subvol->root_item.ctransid = fcb->Vcb->superblock.generation;
609  fcb->subvol->root_item.ctime = now;
610  } else {
611  ERR("unsupported file type %u\n", fcb->type);
613  goto end;
614  }
615 
617 
619 
620 end:
621  if (NT_SUCCESS(Status))
623  else
625 
626  ExReleaseResourceLite(fcb->Header.Resource);
627  ExReleaseResourceLite(&fcb->Vcb->tree_lock);
628 
629  return Status;
630 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback)
Definition: treefuncs.c:1049
void clear_rollback(LIST_ENTRY *rollback)
Definition: treefuncs.c:1028
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
bool reparse_xattr_changed
Definition: btrfs_drv.h:320
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
ANSI_STRING reparse_xattr
Definition: btrfs_drv.h:297
#define FILE_NOTIFY_CHANGE_LAST_WRITE
GLuint GLuint end
Definition: gl.h:1545
__u16 time
Definition: mkdosfs.c:366
ACCESS_MASK access
Definition: btrfs_drv.h:383
NTSTATUS truncate_file(fcb *fcb, uint64_t end, PIRP Irp, LIST_ENTRY *rollback)
Definition: write.c:3236
bool atts_changed
Definition: btrfs_drv.h:318
BTRFS_TIME st_ctime
Definition: btrfs.h:284
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
bool user_set_write_time
Definition: btrfs_drv.h:390
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
void queue_notification_fcb(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1586
void mark_fileref_dirty(_In_ file_ref *fileref)
Definition: btrfs.c:1636
uint64_t sequence
Definition: btrfs.h:281
time_t now
Definition: finger.c:65
#define FILE_ACTION_MODIFIED
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
UCHAR DataBuffer[1]
Definition: shellext.h:188
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1614
uint8_t type
Definition: btrfs_drv.h:287
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
BTRFS_TIME st_mtime
Definition: btrfs.h:285
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:279
#define TRACE(s)
Definition: solgame.cpp:4
struct _fcb fcb
Definition: btrfs_drv.h:1314
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
bool user_set_change_time
Definition: btrfs_drv.h:391
unsigned long DWORD
Definition: ntddk_ex.h:95
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1955
dir_child * dc
Definition: btrfs_drv.h:354
USHORT ReparseDataLength
Definition: shellext.h:166
fcb * fcb
Definition: btrfs_drv.h:342
Definition: typedefs.h:117
INODE_ITEM inode_item
Definition: btrfs_drv.h:288
uint64_t generation
Definition: btrfs.h:270
#define __S_IFREG
Definition: btrfs_drv.h:1734
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
ULONG atts
Definition: btrfs_drv.h:293
uint8_t type
Definition: btrfs_drv.h:249
#define FILE_NOTIFY_CHANGE_ATTRIBUTES
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
uint64_t transid
Definition: btrfs.h:271
struct _root * subvol
Definition: btrfs_drv.h:284
_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:1314
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
#define BTRFS_TYPE_FILE
Definition: shellext.h:85
bool ads
Definition: btrfs_drv.h:326
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:964
uint32_t buflen
Definition: read.c:47
#define __S_IFLNK
Definition: btrfs_drv.h:1736
struct _ccb ccb
file_ref * fileref
Definition: btrfs_drv.h:384
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
return STATUS_SUCCESS
Definition: btrfs.c:2938
bool inode_item_changed
Definition: btrfs_drv.h:302
#define IO_REPARSE_TAG_SYMLINK
Definition: iotypes.h:6884
struct _device_extension * Vcb
Definition: btrfs_drv.h:283
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:91
uint32_t st_mode
Definition: btrfs.h:278

Referenced by fsctl_request().

◆ get_reparse_point()

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

Definition at line 22 of file reparse.c.

22  {
23  USHORT subnamelen, printnamelen, i;
25  DWORD reqlen;
27  fcb* fcb = FileObject->FsContext;
28  ccb* ccb = FileObject->FsContext2;
30 
31  TRACE("(%p, %p, %p, %x, %p)\n", DeviceObject, FileObject, buffer, buflen, retlen);
32 
33  if (!ccb)
35 
36  ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, true);
37  ExAcquireResourceSharedLite(fcb->Header.Resource, true);
38 
39  if (fcb->type == BTRFS_TYPE_SYMLINK) {
40  if (ccb->lxss) {
41  reqlen = offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + sizeof(uint32_t);
42 
43  if (buflen < reqlen) {
45  goto end;
46  }
47 
49  rdb->ReparseDataLength = offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + sizeof(uint32_t);
50  rdb->Reserved = 0;
51 
52  *((uint32_t*)rdb->GenericReparseBuffer.DataBuffer) = 1;
53 
54  *retlen = reqlen;
55  } else {
56  char* data;
57 
58  if (fcb->inode_item.st_size == 0 || fcb->inode_item.st_size > 0xffff) {
60  goto end;
61  }
62 
64  if (!data) {
65  ERR("out of memory\n");
67  goto end;
68  }
69 
70  TRACE("data = %p, size = %x\n", data, fcb->inode_item.st_size);
72 
73  if (!NT_SUCCESS(Status)) {
74  ERR("read_file returned %08x\n", Status);
76  goto end;
77  }
78 
80  if (!NT_SUCCESS(Status)) {
81  ERR("utf8_to_utf16 1 returned %08x\n", Status);
83  goto end;
84  }
85 
86  subnamelen = (uint16_t)stringlen;
87  printnamelen = (uint16_t)stringlen;
88 
89  reqlen = offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + subnamelen + printnamelen;
90 
91  if (buflen >= offsetof(REPARSE_DATA_BUFFER, ReparseDataLength))
93 
95  rdb->ReparseDataLength = (USHORT)(reqlen - offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer));
96 
97  if (buflen >= offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.SubstituteNameOffset))
98  rdb->Reserved = 0;
99 
100  if (buflen < reqlen) {
101  ExFreePool(data);
103  *retlen = min(buflen, offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.SubstituteNameOffset));
104  goto end;
105  }
106 
107  rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
108  rdb->SymbolicLinkReparseBuffer.SubstituteNameLength = subnamelen;
109  rdb->SymbolicLinkReparseBuffer.PrintNameOffset = subnamelen;
110  rdb->SymbolicLinkReparseBuffer.PrintNameLength = printnamelen;
112 
113  Status = utf8_to_utf16(&rdb->SymbolicLinkReparseBuffer.PathBuffer[rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)],
115 
116  if (!NT_SUCCESS(Status)) {
117  ERR("utf8_to_utf16 2 returned %08x\n", Status);
118  ExFreePool(data);
119  goto end;
120  }
121 
122  for (i = 0; i < stringlen / sizeof(WCHAR); i++) {
123  if (rdb->SymbolicLinkReparseBuffer.PathBuffer[(rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)) + i] == '/')
124  rdb->SymbolicLinkReparseBuffer.PathBuffer[(rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)) + i] = '\\';
125  }
126 
127  RtlCopyMemory(&rdb->SymbolicLinkReparseBuffer.PathBuffer[rdb->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(WCHAR)],
128  &rdb->SymbolicLinkReparseBuffer.PathBuffer[rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)],
129  rdb->SymbolicLinkReparseBuffer.SubstituteNameLength);
130 
131  *retlen = reqlen;
132 
133  ExFreePool(data);
134  }
135 
137  } else if (fcb->atts & FILE_ATTRIBUTE_REPARSE_POINT) {
138  if (fcb->type == BTRFS_TYPE_FILE) {
139  ULONG len;
140 
141  Status = read_file(fcb, buffer, 0, buflen, &len, NULL);
142 
143  if (!NT_SUCCESS(Status)) {
144  ERR("read_file returned %08x\n", Status);
145  }
146 
147  *retlen = len;
148  } else if (fcb->type == BTRFS_TYPE_DIRECTORY) {
149  if (!fcb->reparse_xattr.Buffer || fcb->reparse_xattr.Length < sizeof(ULONG)) {
151  goto end;
152  }
153 
154  if (buflen > 0) {
155  *retlen = min(buflen, fcb->reparse_xattr.Length);
157  } else
158  *retlen = 0;
159 
161  } else
163  } else {
165  }
166 
167 end:
168  ExReleaseResourceLite(fcb->Header.Resource);
169  ExReleaseResourceLite(&fcb->Vcb->tree_lock);
170 
171  return Status;
172 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define IO_REPARSE_TAG_LXSS_SYMLINK
Definition: btrfs_drv.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONG NTSTATUS
Definition: precomp.h:26
ANSI_STRING reparse_xattr
Definition: btrfs_drv.h:297
GLuint buffer
Definition: glext.h:5915
GLuint GLuint end
Definition: gl.h:1545
NTSTATUS read_file(fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp)
Definition: read.c:2715
#define uint16_t
Definition: nsiface.idl:60
#define ALLOC_TAG
Definition: btrfs_drv.h:91
WCHAR PathBuffer[1]
Definition: shellext.h:176
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 BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
UCHAR DataBuffer[1]
Definition: shellext.h:188
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
_Reserved_ PVOID Reserved
Definition: winddi.h:3974
uint8_t type
Definition: btrfs_drv.h:287
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:279
uint64_t st_size
Definition: btrfs.h:272
#define TRACE(s)
Definition: solgame.cpp:4
if(!(yy_init))
Definition: macro.lex.yy.c:714
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
wstring utf8_to_utf16(const string_view &utf8)
Definition: main.cpp:736
unsigned long DWORD
Definition: ntddk_ex.h:95
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
USHORT ReparseDataLength
Definition: shellext.h:166
GLint const GLchar GLint stringlen
Definition: glext.h:7232
#define STATUS_NOT_A_REPARSE_POINT
Definition: ntstatus.h:739
GLenum GLsizei len
Definition: glext.h:6722
struct _REPARSE_DATA_BUFFER::@308::@310 SymbolicLinkReparseBuffer
INODE_ITEM inode_item
Definition: btrfs_drv.h:288
BYTE uint8_t
Definition: msvideo1.c:66
#define SYMLINK_FLAG_RELATIVE
Definition: shellext.h:193
Status
Definition: gdiplustypes.h:24
struct _REPARSE_DATA_BUFFER::@308::@312 GenericReparseBuffer
#define ERR(fmt,...)
Definition: debug.h:109
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
ULONG atts
Definition: btrfs_drv.h:293
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
unsigned short USHORT
Definition: pedump.c:61
#define min(a, b)
Definition: monoChain.cc:55
UINT32 uint32_t
Definition: types.h:75
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
#define BTRFS_TYPE_FILE
Definition: shellext.h:85
uint32_t buflen
Definition: read.c:47
USHORT SubstituteNameOffset
Definition: shellext.h:171
unsigned int ULONG
Definition: retypes.h:1
bool lxss
Definition: btrfs_drv.h:392
#define uint32_t
Definition: nsiface.idl:61
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define IO_REPARSE_TAG_SYMLINK
Definition: iotypes.h:6884
struct _device_extension * Vcb
Definition: btrfs_drv.h:283
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:91

Referenced by fsctl_request().

◆ set_reparse_point()

NTSTATUS set_reparse_point ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp 
)

Definition at line 367 of file reparse.c.

367  {
370  void* buffer = Irp->AssociatedIrp.SystemBuffer;
372  DWORD buflen = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
374  fcb* fcb;
375  ccb* ccb;
376  file_ref* fileref;
378 
379  TRACE("(%p, %p)\n", DeviceObject, Irp);
380 
382 
383  if (!FileObject) {
384  ERR("FileObject was NULL\n");
386  }
387 
388  // IFSTest insists on this, for some reason...
389  if (Irp->UserBuffer)
391 
392  fcb = FileObject->FsContext;
393  ccb = FileObject->FsContext2;
394 
395  if (!ccb) {
396  ERR("ccb was NULL\n");
398  }
399 
400  if (Irp->RequestorMode == UserMode && !(ccb->access & (FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA))) {
401  WARN("insufficient privileges\n");
402  return STATUS_ACCESS_DENIED;
403  }
404 
405  fileref = ccb->fileref;
406 
407  if (!fileref) {
408  ERR("fileref was NULL\n");
410  }
411 
412  if (fcb->ads) {
413  fileref = fileref->parent;
414  fcb = fileref->fcb;
415  }
416 
417  ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, true);
418  ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
419 
420  Status = set_reparse_point2(fcb, rdb, buflen, ccb, fileref, Irp, &rollback);
421  if (!NT_SUCCESS(Status)) {
422  ERR("set_reparse_point2 returned %08x\n", Status);
423  goto end;
424  }
425 
427 
428 end:
429  if (NT_SUCCESS(Status))
431  else
433 
434  ExReleaseResourceLite(fcb->Header.Resource);
435  ExReleaseResourceLite(&fcb->Vcb->tree_lock);
436 
437  return Status;
438 }
struct _file_ref * parent
Definition: btrfs_drv.h:353
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback)
Definition: treefuncs.c:1049
void clear_rollback(LIST_ENTRY *rollback)
Definition: treefuncs.c:1028
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
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:273
GLuint buffer
Definition: glext.h:5915
#define FILE_NOTIFY_CHANGE_LAST_WRITE
GLuint GLuint end
Definition: gl.h:1545
ACCESS_MASK access
Definition: btrfs_drv.h:383
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
void queue_notification_fcb(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1586
#define FILE_ACTION_MODIFIED
smooth NULL
Definition: ftsmooth.c:416
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
#define FILE_WRITE_DATA
Definition: nt_native.h:631
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:279
#define TRACE(s)
Definition: solgame.cpp:4
struct _fcb fcb
Definition: btrfs_drv.h:1314
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
unsigned long DWORD
Definition: ntddk_ex.h:95
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1955
fcb * fcb
Definition: btrfs_drv.h:342
Definition: typedefs.h:117
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
#define FILE_NOTIFY_CHANGE_ATTRIBUTES
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
_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:1314
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
bool ads
Definition: btrfs_drv.h:326
uint32_t buflen
Definition: read.c:47
struct _ccb ccb
file_ref * fileref
Definition: btrfs_drv.h:384
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
return STATUS_SUCCESS
Definition: btrfs.c:2938
struct _device_extension * Vcb
Definition: btrfs_drv.h:283

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 273 of file reparse.c.

273  {
275  ULONG tag;
276 
277  if (fcb->type == BTRFS_TYPE_SYMLINK) {
278  WARN("tried to set a reparse point on an existing symlink\n");
280  }
281 
282  // FIXME - fail if we already have the attribute FILE_ATTRIBUTE_REPARSE_POINT
283 
284  // FIXME - die if not file or directory
285 
286  if (buflen < sizeof(ULONG)) {
287  WARN("buffer was not long enough to hold tag\n");
289  }
290 
292  if (!NT_SUCCESS(Status)) {
293  ERR("FsRtlValidateReparsePointBuffer returned %08x\n", Status);
294  return Status;
295  }
296 
297  RtlCopyMemory(&tag, rdb, sizeof(ULONG));
298 
299  if (fcb->type == BTRFS_TYPE_FILE &&
303  } else {
305  BTRFS_TIME now;
306 
307  if (fcb->type == BTRFS_TYPE_DIRECTORY || fcb->type == BTRFS_TYPE_CHARDEV || fcb->type == BTRFS_TYPE_BLOCKDEV) { // store as xattr
309 
311  if (!buf.Buffer) {
312  ERR("out of memory\n");
314  }
315  buf.Length = buf.MaximumLength = (uint16_t)buflen;
316 
317  if (fcb->reparse_xattr.Buffer)
319 
320  fcb->reparse_xattr = buf;
321  RtlCopyMemory(buf.Buffer, rdb, buflen);
322 
323  fcb->reparse_xattr_changed = true;
324 
326  } else { // otherwise, store as file data
328  if (!NT_SUCCESS(Status)) {
329  ERR("truncate_file returned %08x\n", Status);
330  return Status;
331  }
332 
333  offset.QuadPart = 0;
334 
335  Status = write_file2(fcb->Vcb, Irp, offset, rdb, &buflen, false, true, true, false, false, rollback);
336  if (!NT_SUCCESS(Status)) {
337  ERR("write_file2 returned %08x\n", Status);
338  return Status;
339  }
340  }
341 
344 
345  fcb->inode_item.transid = fcb->Vcb->superblock.generation;
347 
348  if (!ccb || !ccb->user_set_change_time)
350 
351  if (!ccb || !ccb->user_set_write_time)
353 
355  fcb->atts_changed = true;
356 
357  fcb->subvol->root_item.ctransid = fcb->Vcb->superblock.generation;
358  fcb->subvol->root_item.ctime = now;
359 
360  fcb->inode_item_changed = true;
362  }
363 
364  return STATUS_SUCCESS;
365 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define IO_REPARSE_TAG_LXSS_SYMLINK
Definition: btrfs_drv.h:120
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define BTRFS_TYPE_BLOCKDEV
Definition: shellext.h:88
bool reparse_xattr_changed
Definition: btrfs_drv.h:320
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
static NTSTATUS set_symlink(PIRP Irp, file_ref *fileref, fcb *fcb, ccb *ccb, REPARSE_DATA_BUFFER *rdb, ULONG buflen, bool write, LIST_ENTRY *rollback)
Definition: reparse.c:174
Definition: ecma_167.h:138
ANSI_STRING reparse_xattr
Definition: btrfs_drv.h:297
tFsRtlValidateReparsePointBuffer fFsRtlValidateReparsePointBuffer
Definition: btrfs.c:101
__u16 time
Definition: mkdosfs.c:366
#define uint16_t
Definition: nsiface.idl:60
#define BTRFS_TYPE_CHARDEV
Definition: shellext.h:87
NTSTATUS truncate_file(fcb *fcb, uint64_t end, PIRP Irp, LIST_ENTRY *rollback)
Definition: write.c:3236
bool atts_changed
Definition: btrfs_drv.h:318
BTRFS_TIME st_ctime
Definition: btrfs.h:284
bool user_set_write_time
Definition: btrfs_drv.h:390
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint64_t sequence
Definition: btrfs.h:281
time_t now
Definition: finger.c:65
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1614
uint8_t type
Definition: btrfs_drv.h:287
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
BTRFS_TIME st_mtime
Definition: btrfs.h:285
#define STATUS_INVALID_BUFFER_SIZE
Definition: ntstatus.h:636
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
bool user_set_change_time
Definition: btrfs_drv.h:391
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
struct _REPARSE_DATA_BUFFER::@308::@310 SymbolicLinkReparseBuffer
INODE_ITEM inode_item
Definition: btrfs_drv.h:288
#define SYMLINK_FLAG_RELATIVE
Definition: shellext.h:193
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
ULONG atts
Definition: btrfs_drv.h:293
uint64_t transid
Definition: btrfs.h:271
struct _root * subvol
Definition: btrfs_drv.h:284
_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:1314
#define BTRFS_TYPE_FILE
Definition: shellext.h:85
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:964
uint32_t buflen
Definition: read.c:47
unsigned int ULONG
Definition: retypes.h:1
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)
Definition: write.c:4145
return STATUS_SUCCESS
Definition: btrfs.c:2938
bool inode_item_changed
Definition: btrfs_drv.h:302
#define IO_REPARSE_TAG_SYMLINK
Definition: iotypes.h:6884
struct _device_extension * Vcb
Definition: btrfs_drv.h:283
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:91
char * tag
Definition: main.c:59

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,
bool  write,
LIST_ENTRY rollback 
)
static

Definition at line 174 of file reparse.c.

174  {
176  ULONG minlen;
177  ULONG tlength;
178  UNICODE_STRING subname;
181  BTRFS_TIME now;
182  USHORT i;
183 
184  if (write) {
185  minlen = offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + sizeof(WCHAR);
186  if (buflen < minlen) {
187  WARN("buffer was less than minimum length (%u < %u)\n", buflen, minlen);
189  }
190 
191  if (rdb->SymbolicLinkReparseBuffer.SubstituteNameLength < sizeof(WCHAR)) {
192  WARN("rdb->SymbolicLinkReparseBuffer.SubstituteNameLength was too short\n");
194  }
195 
196  subname.Buffer = &rdb->SymbolicLinkReparseBuffer.PathBuffer[rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)];
197  subname.MaximumLength = subname.Length = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength;
198 
199  TRACE("substitute name = %.*S\n", subname.Length / sizeof(WCHAR), subname.Buffer);
200  }
201 
204  fcb->inode_item.generation = fcb->Vcb->superblock.generation; // so we don't confuse btrfs send on Linux
205 
206  if (fileref && fileref->dc)
207  fileref->dc->type = fcb->type;
208 
209  if (write) {
211  if (!NT_SUCCESS(Status)) {
212  ERR("truncate_file returned %08x\n", Status);
213  return Status;
214  }
215 
216  Status = utf16_to_utf8(NULL, 0, (PULONG)&target.Length, subname.Buffer, subname.Length);
217  if (!NT_SUCCESS(Status)) {
218  ERR("utf16_to_utf8 1 failed with error %08x\n", Status);
219  return Status;
220  }
221 
222  target.MaximumLength = target.Length;
223  target.Buffer = ExAllocatePoolWithTag(PagedPool, target.MaximumLength, ALLOC_TAG);
224  if (!target.Buffer) {
225  ERR("out of memory\n");
227  }
228 
229  Status = utf16_to_utf8(target.Buffer, target.Length, (PULONG)&target.Length, subname.Buffer, subname.Length);
230  if (!NT_SUCCESS(Status)) {
231  ERR("utf16_to_utf8 2 failed with error %08x\n", Status);
232  ExFreePool(target.Buffer);
233  return Status;
234  }
235 
236  for (i = 0; i < target.MaximumLength; i++) {
237  if (target.Buffer[i] == '\\')
238  target.Buffer[i] = '/';
239  }
240 
241  offset.QuadPart = 0;
242  tlength = target.Length;
243  Status = write_file2(fcb->Vcb, Irp, offset, target.Buffer, &tlength, false, true,
244  true, false, false, rollback);
245  ExFreePool(target.Buffer);
246  } else
248 
251 
252  fcb->inode_item.transid = fcb->Vcb->superblock.generation;
254 
255  if (!ccb || !ccb->user_set_change_time)
257 
258  if (!ccb || !ccb->user_set_write_time)
260 
261  fcb->subvol->root_item.ctransid = fcb->Vcb->superblock.generation;
262  fcb->subvol->root_item.ctime = now;
263 
264  fcb->inode_item_changed = true;
266 
267  if (fileref)
268  mark_fileref_dirty(fileref);
269 
270  return Status;
271 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
USHORT MaximumLength
Definition: env_spec_w32.h:370
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
__u16 time
Definition: mkdosfs.c:366
NTSTATUS truncate_file(fcb *fcb, uint64_t end, PIRP Irp, LIST_ENTRY *rollback)
Definition: write.c:3236
BTRFS_TIME st_ctime
Definition: btrfs.h:284
bool user_set_write_time
Definition: btrfs_drv.h:390
#define ALLOC_TAG
Definition: btrfs_drv.h:91
#define write
Definition: acwin.h:97
WCHAR PathBuffer[1]
Definition: shellext.h:176
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
void mark_fileref_dirty(_In_ file_ref *fileref)
Definition: btrfs.c:1636
uint64_t sequence
Definition: btrfs.h:281
time_t now
Definition: finger.c:65
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1614
static string utf16_to_utf8(const wstring_view &utf16)
Definition: main.cpp:672
uint8_t type
Definition: btrfs_drv.h:287
BTRFS_TIME st_mtime
Definition: btrfs.h:285
#define TRACE(s)
Definition: solgame.cpp:4
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
bool user_set_change_time
Definition: btrfs_drv.h:391
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
dir_child * dc
Definition: btrfs_drv.h:354
struct _REPARSE_DATA_BUFFER::@308::@310 SymbolicLinkReparseBuffer
INODE_ITEM inode_item
Definition: btrfs_drv.h:288
uint64_t generation
Definition: btrfs.h:270
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
unsigned short USHORT
Definition: pedump.c:61
uint8_t type
Definition: btrfs_drv.h:249
uint64_t transid
Definition: btrfs.h:271
unsigned int * PULONG
Definition: retypes.h:1
struct _root * subvol
Definition: btrfs_drv.h:284
_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:1314
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:964
uint32_t buflen
Definition: read.c:47
unsigned int ULONG
Definition: retypes.h:1
GLenum target
Definition: glext.h:7315
#define __S_IFLNK
Definition: btrfs_drv.h:1736
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)
Definition: write.c:4145
return STATUS_SUCCESS
Definition: btrfs.c:2938
bool inode_item_changed
Definition: btrfs_drv.h:302
struct _device_extension * Vcb
Definition: btrfs_drv.h:283
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:91
uint32_t st_mode
Definition: btrfs.h:278

Referenced by set_reparse_point2().

Variable Documentation

◆ fFsRtlValidateReparsePointBuffer

tFsRtlValidateReparsePointBuffer fFsRtlValidateReparsePointBuffer

Definition at line 101 of file btrfs.c.

Referenced by _Function_class_(), and set_reparse_point2().