ntdll-Junction_Points: Updates from Erich E. Hoover.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50770
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50804
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50878
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51059
This commit is contained in:
Zebediah Figura 2021-05-08 15:13:53 -05:00
parent 7c888e7fee
commit 8e5c8cc63b
42 changed files with 960 additions and 733 deletions

View File

@ -1,4 +1,4 @@
From 719f4d5ab7ba2b2e9f3797dfce0370fa5cba5a66 Mon Sep 17 00:00:00 2001
From a83181801d5248f7e228810bfe0a829a81be345f Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 16 Jan 2014 20:56:49 -0700
Subject: [PATCH] ntdll: Add support for junction point creation.
@ -14,10 +14,10 @@ Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
create mode 100644 include/ntifs.h
diff --git a/configure.ac b/configure.ac
index ce6bad68f68..11f57d13274 100644
index 71991bd3938..7553b22e76d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2218,6 +2218,8 @@ AC_CHECK_FUNCS(\
@@ -2219,6 +2219,8 @@ AC_CHECK_FUNCS(\
proc_pidinfo \
pwrite \
readlink \
@ -27,7 +27,7 @@ index ce6bad68f68..11f57d13274 100644
setproctitle \
setprogname \
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 498da270a34..792c07b0d8e 100644
index 2c1835e3ff0..54e06a3f126 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -38,6 +38,7 @@
@ -38,7 +38,7 @@ index 498da270a34..792c07b0d8e 100644
#ifndef IO_COMPLETION_ALL_ACCESS
#define IO_COMPLETION_ALL_ACCESS 0x001F0003
@@ -5152,6 +5153,105 @@ static void test_mailslot_name(void)
@@ -5233,6 +5234,105 @@ static void test_mailslot_name(void)
CloseHandle( device );
}
@ -144,7 +144,7 @@ index 498da270a34..792c07b0d8e 100644
START_TEST(file)
{
HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
@@ -5224,5 +5324,6 @@ START_TEST(file)
@@ -5305,5 +5405,6 @@ START_TEST(file)
test_ioctl();
test_query_ea();
test_flush_buffers_file();
@ -152,7 +152,7 @@ index 498da270a34..792c07b0d8e 100644
test_mailslot_name();
}
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index a4728003cf8..ea9c0d811f5 100644
index 700ee717294..492838d9031 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -36,6 +36,7 @@
@ -182,7 +182,7 @@ index a4728003cf8..ea9c0d811f5 100644
#ifdef linux
/* We want the real kernel dirent structure, not the libc one */
@@ -479,6 +485,32 @@ static int xattr_set( const char *path, const char *name, void *value, size_t si
@@ -477,6 +483,32 @@ static int xattr_set( const char *path, const char *name, void *value, size_t si
#endif
}
@ -215,7 +215,7 @@ index a4728003cf8..ea9c0d811f5 100644
/* get space from the current directory data buffer, allocating a new one if necessary */
static void *get_dir_data_space( struct dir_data *data, unsigned int size )
{
@@ -5806,6 +5838,116 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer,
@@ -5950,6 +5982,116 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer,
}
@ -223,7 +223,7 @@ index a4728003cf8..ea9c0d811f5 100644
+ * Retrieve the unix name corresponding to a file handle, remove that directory, and then symlink
+ * the requested directory to the location of the old directory.
+ */
+NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
+NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
+{
+ BOOL src_allocated = FALSE, dest_allocated = FALSE, tempdir_created = FALSE;
+ int dest_len = buffer->MountPointReparseBuffer.SubstituteNameLength;
@ -332,7 +332,7 @@ index a4728003cf8..ea9c0d811f5 100644
/******************************************************************************
* NtFsControlFile (NTDLL.@)
*/
@@ -5888,6 +6030,23 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
@@ -6032,6 +6174,23 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
break;
}
@ -343,7 +343,7 @@ index a4728003cf8..ea9c0d811f5 100644
+ switch(buffer->ReparseTag)
+ {
+ case IO_REPARSE_TAG_MOUNT_POINT:
+ status = FILE_CreateSymlink( handle, buffer );
+ status = create_reparse_point( handle, buffer );
+ break;
+ default:
+ FIXME("stub: FSCTL_SET_REPARSE_POINT(%x)\n", buffer->ReparseTag);
@ -357,10 +357,10 @@ index a4728003cf8..ea9c0d811f5 100644
TRACE("FSCTL_SET_SPARSE: Ignoring request\n");
io->Information = 0;
diff --git a/include/Makefile.in b/include/Makefile.in
index 6c16e01a271..bf938cae250 100644
index 9822bce6bdd..00a1be0b74e 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -533,6 +533,7 @@ SOURCES = \
@@ -538,6 +538,7 @@ SOURCES = \
ntddvdeo.h \
ntdef.h \
ntdsapi.h \
@ -417,5 +417,5 @@ index 00000000000..21d42e17325
+
+#endif /* __WINE_NTIFS_H */
--
2.20.1
2.30.2

View File

@ -1,23 +1,28 @@
From ba7660d29357412b0a12475dacd1d96da9d5679c Mon Sep 17 00:00:00 2001
From 49ed938003d970383e684d7db56bf570d0d94b2a Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 16 Jan 2014 20:57:57 -0700
Subject: [PATCH] ntdll: Add support for reading junction points.
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
---
dlls/ntdll/tests/file.c | 14 ++++-
dlls/ntdll/unix/file.c | 120 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 133 insertions(+), 1 deletion(-)
dlls/ntdll/tests/file.c | 20 ++++++-
dlls/ntdll/unix/file.c | 125 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 144 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 792c07b0d8e..88e114ab7a2 100644
index 54e06a3f126..a3f3485ce46 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -5189,9 +5189,10 @@ static void test_reparse_points(void)
@@ -5265,14 +5265,15 @@ static void test_reparse_points(void)
static const WCHAR reparseW[] = {'\\','r','e','p','a','r','s','e',0};
WCHAR path[MAX_PATH], reparse_path[MAX_PATH], target_path[MAX_PATH];
static const WCHAR targetW[] = {'\\','t','a','r','g','e','t',0};
+ INT buffer_len, string_len, path_len, total_len;
static const WCHAR fooW[] = {'f','o','o',0};
static WCHAR volW[] = {'c',':','\\',0};
static const WCHAR dotW[] = {'.',0};
REPARSE_DATA_BUFFER *buffer = NULL;
DWORD dwret, dwLen, dwFlags;
+ INT buffer_len, string_len;
UNICODE_STRING nameW;
- INT buffer_len;
HANDLE handle;
@ -25,7 +30,7 @@ index 792c07b0d8e..88e114ab7a2 100644
BOOL bret;
/* Create a temporary folder for the junction point tests */
@@ -5239,6 +5240,17 @@ static void test_reparse_points(void)
@@ -5320,6 +5321,23 @@ static void test_reparse_points(void)
buffer_len = build_reparse_buffer(nameW.Buffer, &buffer);
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError());
@ -40,14 +45,20 @@ index 792c07b0d8e..88e114ab7a2 100644
+ dest = &buffer->MountPointReparseBuffer.PathBuffer[buffer->MountPointReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)];
+ ok((memcmp(dest, nameW.Buffer, string_len) == 0), "Junction point destination does not match ('%s' != '%s')!\n",
+ wine_dbgstr_w(dest), wine_dbgstr_w(nameW.Buffer));
+ path_len = buffer->MountPointReparseBuffer.PrintNameOffset/sizeof(WCHAR);
+ path_len += buffer->MountPointReparseBuffer.PrintNameLength/sizeof(WCHAR);
+ total_len = FIELD_OFFSET(typeof(*buffer), MountPointReparseBuffer.PathBuffer[path_len+1])
+ - FIELD_OFFSET(typeof(*buffer), GenericReparseBuffer);
+ ok(buffer->ReparseDataLength == total_len, "ReparseDataLength has unexpected value (%d != %d)\n",
+ buffer->ReparseDataLength, total_len);
CloseHandle(handle);
cleanup:
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index ea9c0d811f5..6389e7c8f20 100644
index 492838d9031..5289c0eec71 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -5948,6 +5948,120 @@ cleanup:
@@ -6092,6 +6092,125 @@ cleanup:
}
@ -55,9 +66,10 @@ index ea9c0d811f5..6389e7c8f20 100644
+ * Retrieve the unix name corresponding to a file handle and use that to find the destination of the
+ * symlink corresponding to that file handle.
+ */
+NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_size)
+NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_size)
+{
+ char *unix_src, unix_dest[PATH_MAX];
+ INT prefix_len, path_len, total_len;
+ VOID *subst_name, *print_name;
+ SIZE_T nt_dest_len = PATH_MAX;
+ BOOL dest_allocated = FALSE;
@ -66,7 +78,6 @@ index ea9c0d811f5..6389e7c8f20 100644
+ DWORD max_length;
+ NTSTATUS status;
+ WCHAR *nt_dest;
+ INT prefix_len;
+ ssize_t ret;
+ char *p;
+ int i;
@ -135,12 +146,16 @@ index ea9c0d811f5..6389e7c8f20 100644
+ {
+ case IO_REPARSE_TAG_MOUNT_POINT:
+ max_length = out_size-FIELD_OFFSET(typeof(*buffer), MountPointReparseBuffer.PathBuffer[1]);
+ buffer->MountPointReparseBuffer.SubstituteNameOffset = 0;
+ path_len = 0;
+ buffer->MountPointReparseBuffer.SubstituteNameOffset = path_len;
+ buffer->MountPointReparseBuffer.SubstituteNameLength = nt_dest_len;
+ path_len += nt_dest_len + sizeof(WCHAR);
+ subst_name = &buffer->MountPointReparseBuffer.PathBuffer[buffer->MountPointReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)];
+ buffer->MountPointReparseBuffer.PrintNameOffset = nt_dest_len + sizeof(WCHAR);
+ buffer->MountPointReparseBuffer.PrintNameOffset = path_len;
+ buffer->MountPointReparseBuffer.PrintNameLength = nt_dest_len - prefix_len*sizeof(WCHAR);
+ print_name = &buffer->MountPointReparseBuffer.PathBuffer[buffer->MountPointReparseBuffer.PrintNameOffset/sizeof(WCHAR)];
+ path_len += (nt_dest_len - prefix_len*sizeof(WCHAR)) + sizeof(WCHAR);
+ total_len = FIELD_OFFSET(typeof(*buffer), MountPointReparseBuffer.PathBuffer[path_len/sizeof(WCHAR)]);
+ break;
+ default:
+ /* unrecognized (regular) files should probably be treated as symlinks */
@ -156,6 +171,7 @@ index ea9c0d811f5..6389e7c8f20 100644
+
+ memcpy( subst_name, nt_dest, nt_dest_len );
+ memcpy( print_name, &nt_dest[prefix_len], nt_dest_len - prefix_len*sizeof(WCHAR) );
+ buffer->ReparseDataLength = total_len - FIELD_OFFSET(typeof(*buffer), GenericReparseBuffer);
+ status = STATUS_SUCCESS;
+
+cleanup:
@ -168,19 +184,19 @@ index ea9c0d811f5..6389e7c8f20 100644
/******************************************************************************
* NtFsControlFile (NTDLL.@)
*/
@@ -6030,6 +6144,12 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
@@ -6174,6 +6293,12 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
break;
}
+ case FSCTL_GET_REPARSE_POINT:
+ {
+ REPARSE_DATA_BUFFER *buffer = (REPARSE_DATA_BUFFER *)out_buffer;
+ status = FILE_GetSymlink( handle, buffer, out_size );
+ status = get_reparse_point( handle, buffer, out_size );
+ break;
+ }
case FSCTL_SET_REPARSE_POINT:
{
REPARSE_DATA_BUFFER *buffer = (REPARSE_DATA_BUFFER *)in_buffer;
--
2.20.1
2.30.2

View File

@ -1,4 +1,4 @@
From 7554efacce44c930a981312bcf341b74e896fc17 Mon Sep 17 00:00:00 2001
From cc1a2a1ade9c176a7c77a5673c26cee6ab85963c Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 16 Jan 2014 21:00:21 -0700
Subject: [PATCH] ntdll: Add support for deleting junction points.
@ -11,13 +11,13 @@ Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
3 files changed, 131 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 88e114ab7a2..0dcefdef97b 100644
index a3f3485ce46..b844fe9e1d3 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -5184,12 +5184,15 @@ static void test_reparse_points(void)
static const WCHAR reparseW[] = {'\\','r','e','p','a','r','s','e',0};
@@ -5266,11 +5266,14 @@ static void test_reparse_points(void)
WCHAR path[MAX_PATH], reparse_path[MAX_PATH], target_path[MAX_PATH];
static const WCHAR targetW[] = {'\\','t','a','r','g','e','t',0};
INT buffer_len, string_len, path_len, total_len;
+ FILE_BASIC_INFORMATION old_attrib, new_attrib;
static const WCHAR fooW[] = {'f','o','o',0};
static WCHAR volW[] = {'c',':','\\',0};
@ -25,12 +25,11 @@ index 88e114ab7a2..0dcefdef97b 100644
static const WCHAR dotW[] = {'.',0};
REPARSE_DATA_BUFFER *buffer = NULL;
DWORD dwret, dwLen, dwFlags;
INT buffer_len, string_len;
+ IO_STATUS_BLOCK iosb;
UNICODE_STRING nameW;
HANDLE handle;
WCHAR *dest;
@@ -5237,6 +5240,8 @@ static void test_reparse_points(void)
@@ -5318,6 +5321,8 @@ static void test_reparse_points(void)
win_skip("Failed to open junction point directory handle (0x%x).\n", GetLastError());
goto cleanup;
}
@ -39,10 +38,10 @@ index 88e114ab7a2..0dcefdef97b 100644
buffer_len = build_reparse_buffer(nameW.Buffer, &buffer);
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError());
@@ -5251,6 +5256,22 @@ static void test_reparse_points(void)
dest = &buffer->MountPointReparseBuffer.PathBuffer[buffer->MountPointReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)];
ok((memcmp(dest, nameW.Buffer, string_len) == 0), "Junction point destination does not match ('%s' != '%s')!\n",
wine_dbgstr_w(dest), wine_dbgstr_w(nameW.Buffer));
@@ -5338,6 +5343,22 @@ static void test_reparse_points(void)
- FIELD_OFFSET(typeof(*buffer), GenericReparseBuffer);
ok(buffer->ReparseDataLength == total_len, "ReparseDataLength has unexpected value (%d != %d)\n",
buffer->ReparseDataLength, total_len);
+
+ /* Delete the junction point */
+ memset(&old_attrib, 0x00, sizeof(old_attrib));
@ -62,7 +61,7 @@ index 88e114ab7a2..0dcefdef97b 100644
CloseHandle(handle);
cleanup:
@@ -5258,7 +5279,7 @@ cleanup:
@@ -5345,7 +5366,7 @@ cleanup:
pRtlFreeUnicodeString(&nameW);
HeapFree(GetProcessHeap(), 0, buffer);
bret = RemoveDirectoryW(reparse_path);
@ -72,10 +71,10 @@ index 88e114ab7a2..0dcefdef97b 100644
ok(bret, "Failed to remove temporary target directory!\n");
RemoveDirectoryW(path);
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index 6389e7c8f20..982df84d029 100644
index 5289c0eec71..118f81db3c1 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -6062,6 +6062,87 @@ cleanup:
@@ -6211,6 +6211,87 @@ cleanup:
}
@ -83,7 +82,7 @@ index 6389e7c8f20..982df84d029 100644
+ * Retrieve the unix name corresponding to a file handle, remove that symlink, and then recreate
+ * a directory at the location of the old filename.
+ */
+NTSTATUS FILE_RemoveSymlink(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer)
+NTSTATUS remove_reparse_point(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer)
+{
+ char tmpdir[PATH_MAX], tmpfile[PATH_MAX], *d;
+ BOOL tempdir_created = FALSE;
@ -163,7 +162,7 @@ index 6389e7c8f20..982df84d029 100644
/******************************************************************************
* NtFsControlFile (NTDLL.@)
*/
@@ -6144,6 +6225,22 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
@@ -6293,6 +6374,22 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
break;
}
@ -174,7 +173,7 @@ index 6389e7c8f20..982df84d029 100644
+ switch(buffer->ReparseTag)
+ {
+ case IO_REPARSE_TAG_MOUNT_POINT:
+ status = FILE_RemoveSymlink( handle, buffer );
+ status = remove_reparse_point( handle, buffer );
+ break;
+ default:
+ FIXME("stub: FSCTL_DELETE_REPARSE_POINT(%x)\n", buffer->ReparseTag);
@ -208,5 +207,5 @@ index 21d42e17325..4539b89d583 100644
+
#endif /* __WINE_NTIFS_H */
--
2.20.1
2.30.2

View File

@ -1,4 +1,4 @@
From c0fe3802d5baca7d4048abfca0dcc261fb63ad2c Mon Sep 17 00:00:00 2001
From 2b0a539941dcd1a292cda3f506abb6359f409527 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 16 Jan 2014 21:01:25 -0700
Subject: [PATCH] ntdll: Add a test for junction point advertisement.
@ -9,10 +9,10 @@ Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
1 file changed, 5 insertions(+)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 0dcefdef97b..7ad25ffd239 100644
index b844fe9e1d3..504d67adde6 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -5246,6 +5246,11 @@ static void test_reparse_points(void)
@@ -5327,6 +5327,11 @@ static void test_reparse_points(void)
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError());
@ -25,5 +25,5 @@ index 0dcefdef97b..7ad25ffd239 100644
HeapFree(GetProcessHeap(), 0, buffer);
buffer_len = sizeof(*buffer) + MAX_PATH*sizeof(WCHAR);
--
2.20.1
2.30.2

View File

@ -1,4 +1,4 @@
From 55571cb23f81d2d5836c69793d5621f09f535009 Mon Sep 17 00:00:00 2001
From d5a062699b1a599fc87ba757e65b3aeb2ead9834 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 16 Jan 2014 21:02:11 -0700
Subject: [PATCH] server: Add support for deleting junction points with
@ -11,19 +11,19 @@ Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
2 files changed, 60 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 7ad25ffd239..5a2ac2114b0 100644
index 504d67adde6..2ddabc865bf 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -5190,7 +5190,7 @@ static void test_reparse_points(void)
@@ -5272,7 +5272,7 @@ static void test_reparse_points(void)
REPARSE_GUID_DATA_BUFFER guid_buffer;
static const WCHAR dotW[] = {'.',0};
REPARSE_DATA_BUFFER *buffer = NULL;
- DWORD dwret, dwLen, dwFlags;
+ DWORD dwret, dwLen, dwFlags, err;
INT buffer_len, string_len;
IO_STATUS_BLOCK iosb;
UNICODE_STRING nameW;
@@ -5279,6 +5279,38 @@ static void test_reparse_points(void)
HANDLE handle;
@@ -5366,6 +5366,38 @@ static void test_reparse_points(void)
"Junction point folder's access time does not match.\n");
CloseHandle(handle);
@ -63,7 +63,7 @@ index 7ad25ffd239..5a2ac2114b0 100644
/* Cleanup */
pRtlFreeUnicodeString(&nameW);
diff --git a/server/fd.c b/server/fd.c
index 65a6f876e5c..4f43f41fb31 100644
index 481e9a88f0f..2605adf96ff 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -169,7 +169,8 @@ struct closed_fd
@ -187,7 +187,7 @@ index 65a6f876e5c..4f43f41fb31 100644
/* check directory options */
if ((options & FILE_DIRECTORY_FILE) && !S_ISDIR(st.st_mode))
{
@@ -2611,10 +2629,10 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da
@@ -2605,10 +2623,10 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da
free( fd->nt_name );
fd->nt_name = dup_nt_name( root, nt_name, &fd->nt_namelen );
@ -201,5 +201,5 @@ index 65a6f876e5c..4f43f41fb31 100644
return;
--
2.20.1
2.30.2

View File

@ -1,4 +1,4 @@
From 2086a18555c0c4111c48676af90c642828ce87f5 Mon Sep 17 00:00:00 2001
From 58c9e69484d7c8da358e61de61827ec1d8399bbd Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
Date: Sat, 12 Dec 2020 17:28:31 -0700
Subject: [PATCH] kernel32: Advertise junction point support.
@ -9,7 +9,7 @@ Subject: [PATCH] kernel32: Advertise junction point support.
2 files changed, 86 insertions(+), 3 deletions(-)
diff --git a/dlls/mountmgr.sys/device.c b/dlls/mountmgr.sys/device.c
index dd2c7d70759..171dc6ea592 100644
index 04e8fe3c0f5..c8e7d6bf088 100644
--- a/dlls/mountmgr.sys/device.c
+++ b/dlls/mountmgr.sys/device.c
@@ -31,6 +31,21 @@
@ -34,7 +34,7 @@ index dd2c7d70759..171dc6ea592 100644
#define NONAMELESSUNION
@@ -1828,6 +1843,68 @@ static NTSTATUS query_property( struct disk_device *device, IRP *irp )
@@ -1902,6 +1917,68 @@ static NTSTATUS query_property( struct disk_device *device, IRP *irp )
return status;
}
@ -103,7 +103,7 @@ index dd2c7d70759..171dc6ea592 100644
static NTSTATUS WINAPI harddisk_query_volume( DEVICE_OBJECT *device, IRP *irp )
{
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
@@ -1916,7 +1993,8 @@ static NTSTATUS WINAPI harddisk_query_volume( DEVICE_OBJECT *device, IRP *irp )
@@ -1990,7 +2067,8 @@ static NTSTATUS WINAPI harddisk_query_volume( DEVICE_OBJECT *device, IRP *irp )
memcpy(info->FileSystemName, fat32W, info->FileSystemNameLength);
break;
default:
@ -114,10 +114,10 @@ index dd2c7d70759..171dc6ea592 100644
info->FileSystemNameLength = min( sizeof(ntfsW), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) );
memcpy(info->FileSystemName, ntfsW, info->FileSystemNameLength);
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 5a2ac2114b0..5882793c883 100644
index 2ddabc865bf..699d5e67d88 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -5181,8 +5181,8 @@ static INT build_reparse_buffer(const WCHAR *filename, REPARSE_DATA_BUFFER **pbu
@@ -5262,8 +5262,8 @@ static INT build_reparse_buffer(const WCHAR *filename, REPARSE_DATA_BUFFER **pbu
static void test_reparse_points(void)
{
@ -125,9 +125,9 @@ index 5a2ac2114b0..5882793c883 100644
static const WCHAR reparseW[] = {'\\','r','e','p','a','r','s','e',0};
- WCHAR path[MAX_PATH], reparse_path[MAX_PATH], target_path[MAX_PATH];
static const WCHAR targetW[] = {'\\','t','a','r','g','e','t',0};
INT buffer_len, string_len, path_len, total_len;
FILE_BASIC_INFORMATION old_attrib, new_attrib;
static const WCHAR fooW[] = {'f','o','o',0};
@@ -5211,7 +5211,12 @@ static void test_reparse_points(void)
@@ -5292,7 +5292,12 @@ static void test_reparse_points(void)
pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
volW[0] = nameW.Buffer[4];
pRtlFreeUnicodeString( &nameW );
@ -142,5 +142,5 @@ index 5a2ac2114b0..5882793c883 100644
{
skip("File system does not support reparse points.\n");
--
2.20.1
2.30.2

View File

@ -1,4 +1,4 @@
From 7fd3c661bce1c490fe9e2ad04b524777e897b896 Mon Sep 17 00:00:00 2001
From fb7afe57f143a7777f54c1e936d60af5ace51865 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 16 Jan 2014 21:06:24 -0700
Subject: [PATCH] ntdll: Add support for absolute symlink creation.
@ -6,15 +6,15 @@ Subject: [PATCH] ntdll: Add support for absolute symlink creation.
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
---
dlls/ntdll/tests/file.c | 117 ++++++++++++++++++++++++++++++++++------
dlls/ntdll/unix/file.c | 37 +++++++++++--
dlls/ntdll/unix/file.c | 49 ++++++++++++-----
include/ntifs.h | 10 ++++
3 files changed, 145 insertions(+), 19 deletions(-)
3 files changed, 146 insertions(+), 30 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 5882793c883..53a24574eec 100644
index 699d5e67d88..e0fa36ea64f 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -5153,26 +5153,50 @@ static void test_mailslot_name(void)
@@ -5234,26 +5234,50 @@ static void test_mailslot_name(void)
CloseHandle( device );
}
@ -73,10 +73,10 @@ index 5882793c883..53a24574eec 100644
lstrcpyW(subst_dest, filename);
lstrcpyW(print_dest, &filename[prefix_len]);
*pbuffer = buffer;
@@ -5192,10 +5216,12 @@ static void test_reparse_points(void)
@@ -5273,10 +5297,12 @@ static void test_reparse_points(void)
static const WCHAR dotW[] = {'.',0};
REPARSE_DATA_BUFFER *buffer = NULL;
DWORD dwret, dwLen, dwFlags, err;
INT buffer_len, string_len;
+ HANDLE handle, token;
IO_STATUS_BLOCK iosb;
UNICODE_STRING nameW;
@ -87,7 +87,7 @@ index 5882793c883..53a24574eec 100644
BOOL bret;
/* Create a temporary folder for the junction point tests */
@@ -5247,7 +5273,7 @@ static void test_reparse_points(void)
@@ -5328,7 +5354,7 @@ static void test_reparse_points(void)
}
dwret = NtQueryInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
ok(dwret == STATUS_SUCCESS, "Failed to get junction point folder's attributes (0x%x).\n", dwret);
@ -96,7 +96,7 @@ index 5882793c883..53a24574eec 100644
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError());
@@ -5288,7 +5314,7 @@ static void test_reparse_points(void)
@@ -5375,7 +5401,7 @@ static void test_reparse_points(void)
HeapFree(GetProcessHeap(), 0, buffer);
handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
@ -105,7 +105,7 @@ index 5882793c883..53a24574eec 100644
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError());
CloseHandle(handle);
@@ -5303,7 +5329,7 @@ static void test_reparse_points(void)
@@ -5390,7 +5416,7 @@ static void test_reparse_points(void)
ok(bret, "Failed to create junction point target directory.\n");
handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
@ -114,7 +114,7 @@ index 5882793c883..53a24574eec 100644
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError());
CloseHandle(handle);
@@ -5316,14 +5342,73 @@ static void test_reparse_points(void)
@@ -5403,14 +5429,73 @@ static void test_reparse_points(void)
ok(dwret != (DWORD)~0, "Junction point doesn't exist (attributes: 0x%x)!\n", dwret);
ok(dwret & FILE_ATTRIBUTE_REPARSE_POINT, "File is not a junction point! (attributes: 0x%x)\n", dwret);
@ -193,11 +193,11 @@ index 5882793c883..53a24574eec 100644
}
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index 773223acd7c..9e4d00deb0e 100644
index 118f81db3c1..da5136db68c 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -5845,18 +5845,34 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer,
NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
@@ -5989,18 +5989,35 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer,
NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
{
BOOL src_allocated = FALSE, dest_allocated = FALSE, tempdir_created = FALSE;
- int dest_len = buffer->MountPointReparseBuffer.SubstituteNameLength;
@ -228,13 +228,14 @@ index 773223acd7c..9e4d00deb0e 100644
+ dest = &buffer->SymbolicLinkReparseBuffer.PathBuffer[offset];
+ break;
+ default:
+ FIXME("stub: FSCTL_SET_REPARSE_POINT(%x)\n", buffer->ReparseTag);
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
if ((status = server_get_unix_fd( handle, FILE_SPECIAL_ACCESS, &dest_fd, &needs_close, NULL, NULL )))
return status;
@@ -5891,6 +5907,20 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
@@ -6035,6 +6052,20 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
strcat( magic_dest, "." );
strcat( magic_dest, "/" );
}
@ -255,14 +256,25 @@ index 773223acd7c..9e4d00deb0e 100644
strcat( magic_dest, unix_dest );
/* Produce the link in a temporary location in the same folder */
@@ -6254,6 +6284,7 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
switch(buffer->ReparseTag)
{
case IO_REPARSE_TAG_MOUNT_POINT:
+ case IO_REPARSE_TAG_SYMLINK:
status = FILE_CreateSymlink( handle, buffer );
break;
default:
@@ -6399,17 +6430,7 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
case FSCTL_SET_REPARSE_POINT:
{
REPARSE_DATA_BUFFER *buffer = (REPARSE_DATA_BUFFER *)in_buffer;
-
- switch(buffer->ReparseTag)
- {
- case IO_REPARSE_TAG_MOUNT_POINT:
- status = create_reparse_point( handle, buffer );
- break;
- default:
- FIXME("stub: FSCTL_SET_REPARSE_POINT(%x)\n", buffer->ReparseTag);
- status = STATUS_NOT_IMPLEMENTED;
- break;
- }
+ status = create_reparse_point( handle, buffer );
break;
}
diff --git a/include/ntifs.h b/include/ntifs.h
index 4539b89d583..ab3273d3f81 100644
--- a/include/ntifs.h
@ -297,5 +309,5 @@ index 4539b89d583..ab3273d3f81 100644
typedef struct _REPARSE_GUID_DATA_BUFFER {
DWORD ReparseTag;
--
2.20.1
2.30.2

View File

@ -1,19 +1,19 @@
From 59ba8b3a0f29945da7e1f082b197ce398bf442f2 Mon Sep 17 00:00:00 2001
From 5859da2b48592d1a13f471a6932a2529aa1e0395 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Wed, 13 Mar 2019 12:55:20 -0600
Subject: [PATCH] ntdll: Add support for reading absolute symlinks.
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
---
dlls/ntdll/tests/file.c | 13 ++++++++++++-
dlls/ntdll/unix/file.c | 22 ++++++++++++++++++++++
2 files changed, 34 insertions(+), 1 deletion(-)
dlls/ntdll/tests/file.c | 19 ++++++++++++++++++-
dlls/ntdll/unix/file.c | 26 ++++++++++++++++++++++++++
2 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 53a24574eec..9a6f72cb783 100644
index e0fa36ea64f..cfc0d176b53 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -5393,7 +5393,6 @@ static void test_reparse_points(void)
@@ -5480,7 +5480,6 @@ static void test_reparse_points(void)
ok(dwret == STATUS_SUCCESS, "Failed to get symlink folder's attributes (0x%x).\n", dwret);
buffer_len = build_reparse_buffer(nameW.Buffer, IO_REPARSE_TAG_SYMLINK, &buffer);
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
@ -21,7 +21,7 @@ index 53a24574eec..9a6f72cb783 100644
ok(bret, "Failed to create symlink! (0x%x)\n", GetLastError());
/* Check the file attributes of the symlink */
@@ -5401,6 +5400,18 @@ static void test_reparse_points(void)
@@ -5488,6 +5487,24 @@ static void test_reparse_points(void)
ok(dwret != (DWORD)~0, "Symlink doesn't exist (attributes: 0x%x)!\n", dwret);
ok(dwret & FILE_ATTRIBUTE_REPARSE_POINT, "File is not a symlink! (attributes: %d)\n", dwret);
@ -35,24 +35,30 @@ index 53a24574eec..9a6f72cb783 100644
+ ok(bret, "Failed to read symlink!\n");
+ ok((memcmp(dest, nameW.Buffer, string_len) == 0), "Symlink destination does not match ('%s' != '%s')!\n",
+ wine_dbgstr_w(dest), wine_dbgstr_w(nameW.Buffer));
+ path_len = buffer->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR);
+ path_len += buffer->SymbolicLinkReparseBuffer.PrintNameLength/sizeof(WCHAR);
+ total_len = FIELD_OFFSET(typeof(*buffer), MountPointReparseBuffer.PathBuffer[path_len+1])
+ - FIELD_OFFSET(typeof(*buffer), GenericReparseBuffer);
+ ok(buffer->ReparseDataLength == total_len, "ReparseDataLength has unexpected value (%d != %d)\n",
+ buffer->ReparseDataLength, total_len);
+ CloseHandle(handle);
+
cleanup:
/* Cleanup */
pRtlFreeUnicodeString(&nameW);
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index 11a7269c09e..19a2d0ae471 100644
index da5136db68c..668f4fe2c80 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -5988,6 +5988,7 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
@@ -6138,6 +6138,7 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out
int unix_dest_len;
DWORD max_length;
NTSTATUS status;
+ ULONG flags = 0;
WCHAR *nt_dest;
INT prefix_len;
ssize_t ret;
@@ -6032,6 +6033,17 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
char *p;
@@ -6181,6 +6182,17 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out
}
buffer->ReparseTag |= (val << i);
}
@ -70,23 +76,27 @@ index 11a7269c09e..19a2d0ae471 100644
unix_dest_len -= (p - unix_dest);
memmove(unix_dest, p, unix_dest_len);
unix_dest[unix_dest_len] = 0;
@@ -6065,6 +6077,16 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
buffer->MountPointReparseBuffer.PrintNameLength = nt_dest_len - prefix_len*sizeof(WCHAR);
print_name = &buffer->MountPointReparseBuffer.PathBuffer[buffer->MountPointReparseBuffer.PrintNameOffset/sizeof(WCHAR)];
@@ -6218,6 +6230,20 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out
path_len += (nt_dest_len - prefix_len*sizeof(WCHAR)) + sizeof(WCHAR);
total_len = FIELD_OFFSET(typeof(*buffer), MountPointReparseBuffer.PathBuffer[path_len/sizeof(WCHAR)]);
break;
+ case IO_REPARSE_TAG_SYMLINK:
+ max_length = out_size-FIELD_OFFSET(typeof(*buffer), SymbolicLinkReparseBuffer.PathBuffer[1]);
+ buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
+ path_len = 0;
+ buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = path_len;
+ buffer->SymbolicLinkReparseBuffer.SubstituteNameLength = nt_dest_len;
+ path_len += nt_dest_len + sizeof(WCHAR);
+ subst_name = &buffer->SymbolicLinkReparseBuffer.PathBuffer[buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)];
+ buffer->SymbolicLinkReparseBuffer.PrintNameOffset = nt_dest_len + sizeof(WCHAR);
+ buffer->SymbolicLinkReparseBuffer.PrintNameOffset = path_len;
+ buffer->SymbolicLinkReparseBuffer.PrintNameLength = nt_dest_len - prefix_len*sizeof(WCHAR);
+ print_name = &buffer->SymbolicLinkReparseBuffer.PathBuffer[buffer->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR)];
+ path_len += (nt_dest_len - prefix_len*sizeof(WCHAR)) + sizeof(WCHAR);
+ total_len = FIELD_OFFSET(typeof(*buffer), MountPointReparseBuffer.PathBuffer[path_len/sizeof(WCHAR)]);
+ buffer->SymbolicLinkReparseBuffer.Flags = flags;
+ break;
default:
/* unrecognized (regular) files should probably be treated as symlinks */
WARN("unrecognized symbolic link\n");
--
2.20.1
2.30.2

View File

@ -1,4 +1,4 @@
From a563404dcdc796241cb83da788c5ac62dfe1fc17 Mon Sep 17 00:00:00 2001
From 1cd53753c747d30cb1acee7f93264747a58c338b Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Wed, 13 Mar 2019 13:02:22 -0600
Subject: [PATCH] ntdll: Add support for deleting symlinks.
@ -10,13 +10,13 @@ Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
2 files changed, 17 insertions(+)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 9a6f72cb783..dd21083ebbb 100644
index cfc0d176b53..1fe5fea47d5 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -5410,6 +5410,22 @@ static void test_reparse_points(void)
ok(bret, "Failed to read symlink!\n");
ok((memcmp(dest, nameW.Buffer, string_len) == 0), "Symlink destination does not match ('%s' != '%s')!\n",
wine_dbgstr_w(dest), wine_dbgstr_w(nameW.Buffer));
@@ -5503,6 +5503,22 @@ static void test_reparse_points(void)
- FIELD_OFFSET(typeof(*buffer), GenericReparseBuffer);
ok(buffer->ReparseDataLength == total_len, "ReparseDataLength has unexpected value (%d != %d)\n",
buffer->ReparseDataLength, total_len);
+
+ /* Delete the symlink */
+ memset(&old_attrib, 0x00, sizeof(old_attrib));
@ -37,17 +37,17 @@ index 9a6f72cb783..dd21083ebbb 100644
cleanup:
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index 19a2d0ae471..4e16db830d2 100644
index 668f4fe2c80..bddf55faad8 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -6280,6 +6280,7 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
@@ -6438,6 +6438,7 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
switch(buffer->ReparseTag)
{
case IO_REPARSE_TAG_MOUNT_POINT:
+ case IO_REPARSE_TAG_SYMLINK:
status = FILE_RemoveSymlink( handle, buffer );
status = remove_reparse_point( handle, buffer );
break;
default:
--
2.20.1
2.30.2

View File

@ -1,4 +1,4 @@
From b5698ce1750769a0b57372be14bf4efb5f1c872c Mon Sep 17 00:00:00 2001
From a56456fcccb14d889925b8f82c2f4c8506143b0a Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 11 Apr 2019 12:16:49 -0600
Subject: [PATCH] ntdll: Add support for relative symlink creation.
@ -11,10 +11,10 @@ Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
3 files changed, 111 insertions(+), 13 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index dd21083ebbb..8ed749cfe33 100644
index 1fe5fea47d5..367eef539ce 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -5153,7 +5153,8 @@ static void test_mailslot_name(void)
@@ -5234,7 +5234,8 @@ static void test_mailslot_name(void)
CloseHandle( device );
}
@ -24,7 +24,7 @@ index dd21083ebbb..8ed749cfe33 100644
{
static INT header_size = offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer);
INT buffer_size, struct_size, data_size, string_len, prefix_len;
@@ -5171,7 +5172,7 @@ static INT build_reparse_buffer(const WCHAR *filename, ULONG tag, REPARSE_DATA_B
@@ -5252,7 +5253,7 @@ static INT build_reparse_buffer(const WCHAR *filename, ULONG tag, REPARSE_DATA_B
default:
return 0;
}
@ -33,7 +33,7 @@ index dd21083ebbb..8ed749cfe33 100644
string_len = lstrlenW(&filename[prefix_len]);
data_size = (prefix_len + 2 * string_len + 2) * sizeof(WCHAR);
buffer_size = struct_size + data_size;
@@ -5191,6 +5192,7 @@ static INT build_reparse_buffer(const WCHAR *filename, ULONG tag, REPARSE_DATA_B
@@ -5272,6 +5273,7 @@ static INT build_reparse_buffer(const WCHAR *filename, ULONG tag, REPARSE_DATA_B
buffer->SymbolicLinkReparseBuffer.SubstituteNameLength = (prefix_len + string_len) * sizeof(WCHAR);
buffer->SymbolicLinkReparseBuffer.PrintNameOffset = (prefix_len + string_len + 1) * sizeof(WCHAR);
buffer->SymbolicLinkReparseBuffer.PrintNameLength = string_len * sizeof(WCHAR);
@ -41,7 +41,7 @@ index dd21083ebbb..8ed749cfe33 100644
subst_dest = &buffer->SymbolicLinkReparseBuffer.PathBuffer[0];
print_dest = &buffer->SymbolicLinkReparseBuffer.PathBuffer[prefix_len + string_len + 1];
break;
@@ -5273,7 +5275,7 @@ static void test_reparse_points(void)
@@ -5354,7 +5356,7 @@ static void test_reparse_points(void)
}
dwret = NtQueryInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
ok(dwret == STATUS_SUCCESS, "Failed to get junction point folder's attributes (0x%x).\n", dwret);
@ -50,7 +50,7 @@ index dd21083ebbb..8ed749cfe33 100644
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError());
@@ -5314,7 +5316,7 @@ static void test_reparse_points(void)
@@ -5401,7 +5403,7 @@ static void test_reparse_points(void)
HeapFree(GetProcessHeap(), 0, buffer);
handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
@ -59,7 +59,7 @@ index dd21083ebbb..8ed749cfe33 100644
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError());
CloseHandle(handle);
@@ -5329,7 +5331,7 @@ static void test_reparse_points(void)
@@ -5416,7 +5418,7 @@ static void test_reparse_points(void)
ok(bret, "Failed to create junction point target directory.\n");
handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
@ -68,7 +68,7 @@ index dd21083ebbb..8ed749cfe33 100644
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError());
CloseHandle(handle);
@@ -5391,7 +5393,7 @@ static void test_reparse_points(void)
@@ -5478,7 +5480,7 @@ static void test_reparse_points(void)
}
dwret = NtQueryInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
ok(dwret == STATUS_SUCCESS, "Failed to get symlink folder's attributes (0x%x).\n", dwret);
@ -77,7 +77,7 @@ index dd21083ebbb..8ed749cfe33 100644
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
ok(bret, "Failed to create symlink! (0x%x)\n", GetLastError());
@@ -5428,6 +5430,22 @@ static void test_reparse_points(void)
@@ -5521,6 +5523,22 @@ static void test_reparse_points(void)
"Symlink folder's access time does not match.\n");
CloseHandle(handle);
@ -92,7 +92,7 @@ index dd21083ebbb..8ed749cfe33 100644
+ }
+ dwret = NtQueryInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
+ ok(dwret == STATUS_SUCCESS, "Failed to get symlink folder's attributes (0x%x).\n", dwret);
+ buffer_len = build_reparse_buffer(targetW, IO_REPARSE_TAG_SYMLINK, SYMLINK_FLAG_RELATIVE, &buffer);
+ buffer_len = build_reparse_buffer(&targetW[1], IO_REPARSE_TAG_SYMLINK, SYMLINK_FLAG_RELATIVE, &buffer);
+ bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
+ CloseHandle(handle);
+ ok(bret, "Failed to create symlink! (0x%x)\n", GetLastError());
@ -101,12 +101,12 @@ index dd21083ebbb..8ed749cfe33 100644
/* Cleanup */
pRtlFreeUnicodeString(&nameW);
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index 4e16db830d2..45aab990fb5 100644
index bddf55faad8..d907d455fc9 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -5844,17 +5844,20 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer,
@@ -5988,17 +5988,20 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer,
*/
NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
{
- BOOL src_allocated = FALSE, dest_allocated = FALSE, tempdir_created = FALSE;
+ BOOL src_allocated = FALSE, path_allocated = FALSE, dest_allocated = FALSE;
@ -127,7 +127,7 @@ index 4e16db830d2..45aab990fb5 100644
int i;
switch(buffer->ReparseTag)
@@ -5863,11 +5866,13 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
@@ -6007,11 +6010,13 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
dest_len = buffer->MountPointReparseBuffer.SubstituteNameLength;
offset = buffer->MountPointReparseBuffer.SubstituteNameOffset;
dest = &buffer->MountPointReparseBuffer.PathBuffer[offset];
@ -140,8 +140,8 @@ index 4e16db830d2..45aab990fb5 100644
+ flags = buffer->SymbolicLinkReparseBuffer.Flags;
break;
default:
return STATUS_NOT_IMPLEMENTED;
@@ -5879,8 +5884,66 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
FIXME("stub: FSCTL_SET_REPARSE_POINT(%x)\n", buffer->ReparseTag);
@@ -6024,8 +6029,66 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
if ((status = server_get_unix_name( handle, &unix_src )))
goto cleanup;
src_allocated = TRUE;
@ -210,7 +210,7 @@ index 4e16db830d2..45aab990fb5 100644
for (;;)
{
unix_dest = malloc( unix_dest_len );
@@ -5896,11 +5959,24 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
@@ -6041,11 +6104,24 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
if (status != STATUS_SUCCESS && status != STATUS_NO_SUCH_FILE)
goto cleanup;
dest_allocated = TRUE;
@ -237,7 +237,7 @@ index 4e16db830d2..45aab990fb5 100644
for (i = 0; i < sizeof(ULONG)*8; i++)
{
if ((buffer->ReparseTag >> i) & 1)
@@ -5917,7 +5993,7 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
@@ -6066,7 +6142,7 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
strcat( magic_dest, "." );
strcat( magic_dest, "/" );
}
@ -246,7 +246,7 @@ index 4e16db830d2..45aab990fb5 100644
/* Produce the link in a temporary location in the same folder */
strcpy( tmpdir, unix_src );
@@ -5967,7 +6043,9 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
@@ -6116,7 +6192,9 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
cleanup:
if (tempdir_created) rmdir( tmpdir );
@ -268,5 +268,5 @@ index ab3273d3f81..0d02225bc4f 100644
+
#endif /* __WINE_NTIFS_H */
--
2.20.1
2.30.2

View File

@ -1,4 +1,4 @@
From 26b27a370a0fac1344dc6f480648d6698a10876e Mon Sep 17 00:00:00 2001
From de6ef008eced847e63429f1a09fe1e7573110093 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 11 Apr 2019 12:31:16 -0600
Subject: [PATCH] ntdll: Add support for reading relative symlinks.
@ -10,12 +10,12 @@ Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
2 files changed, 47 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 8ed749cfe33..bdc1a151b45 100644
index 367eef539ce..46aadeb7e7d 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -5443,9 +5443,22 @@ static void test_reparse_points(void)
@@ -5536,9 +5536,22 @@ static void test_reparse_points(void)
ok(dwret == STATUS_SUCCESS, "Failed to get symlink folder's attributes (0x%x).\n", dwret);
buffer_len = build_reparse_buffer(targetW, IO_REPARSE_TAG_SYMLINK, SYMLINK_FLAG_RELATIVE, &buffer);
buffer_len = build_reparse_buffer(&targetW[1], IO_REPARSE_TAG_SYMLINK, SYMLINK_FLAG_RELATIVE, &buffer);
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
- CloseHandle(handle);
ok(bret, "Failed to create symlink! (0x%x)\n", GetLastError());
@ -27,21 +27,21 @@ index 8ed749cfe33..bdc1a151b45 100644
+ bret = DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, (LPVOID)buffer, buffer_len, &dwret, 0);
+ ok(bret, "Failed to read relative symlink!\n");
+ string_len = buffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
+ ok(string_len != lstrlenW(targetW), "Symlink destination length does not match ('%d' != '%d')!\n",
+ string_len, lstrlenW(targetW));
+ ok(string_len != lstrlenW(&targetW[1]), "Symlink destination length does not match ('%d' != '%d')!\n",
+ string_len, lstrlenW(&targetW[1]));
+ dest = &buffer->SymbolicLinkReparseBuffer.PathBuffer[buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)];
+ ok((memcmp(dest, targetW, string_len) == 0), "Symlink destination does not match ('%s' != '%s')!\n",
+ wine_dbgstr_w(dest), wine_dbgstr_w(targetW));
+ ok((memcmp(dest, &targetW[1], string_len) == 0), "Symlink destination does not match ('%s' != '%s')!\n",
+ wine_dbgstr_w(dest), wine_dbgstr_w(&targetW[1]));
+ CloseHandle(handle);
+
cleanup:
/* Cleanup */
pRtlFreeUnicodeString(&nameW);
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index 45aab990fb5..522cc38f2fc 100644
index d907d455fc9..3a25b803d6f 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -6089,6 +6089,11 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
@@ -6238,6 +6238,11 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out
/* Decode the reparse tag from the symlink */
p = unix_dest;
@ -53,7 +53,7 @@ index 45aab990fb5..522cc38f2fc 100644
if (*p++ != '/')
{
status = STATUS_NOT_IMPLEMENTED;
@@ -6126,24 +6131,47 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
@@ -6275,24 +6280,47 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out
memmove(unix_dest, p, unix_dest_len);
unix_dest[unix_dest_len] = 0;
@ -107,5 +107,5 @@ index 45aab990fb5..522cc38f2fc 100644
{
case IO_REPARSE_TAG_MOUNT_POINT:
--
2.20.1
2.30.2

View File

@ -1,4 +1,4 @@
From 4a1aecb1e9b29fbe0f8d2f4e7d7410af0bbc060e Mon Sep 17 00:00:00 2001
From 9129b44e1ef8458064d773a5605d1ff182d67c54 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 11 Apr 2019 17:57:53 -0600
Subject: [PATCH] ntdll: Add support for file symlinks.
@ -10,10 +10,10 @@ Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
2 files changed, 49 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index bdc1a151b45..8938c5bf50c 100644
index 46aadeb7e7d..e5cfbb68793 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -5376,6 +5376,35 @@ static void test_reparse_points(void)
@@ -5463,6 +5463,35 @@ static void test_reparse_points(void)
/* Delete the junction point directory and create a blank slate for symlink tests */
bret = RemoveDirectoryW(reparse_path);
ok(bret, "Failed to delete junction point!\n");
@ -50,10 +50,10 @@ index bdc1a151b45..8938c5bf50c 100644
ok(bret, "Failed to create junction point directory.\n");
dwret = GetFileAttributesW(reparse_path);
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index 0d064d98743..9b8458b413c 100644
index 3a25b803d6f..ead0c48d62e 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -5854,6 +5854,7 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
@@ -5998,6 +5998,7 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
int relative_offset = 0;
UNICODE_STRING nt_dest;
int dest_len, offset;
@ -61,7 +61,7 @@ index 0d064d98743..9b8458b413c 100644
NTSTATUS status;
struct stat st;
WCHAR *dest;
@@ -5986,7 +5987,6 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
@@ -6131,7 +6132,6 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
/* Encode the type (file or directory) if NT symlink */
if (buffer->ReparseTag == IO_REPARSE_TAG_SYMLINK)
{
@ -69,7 +69,7 @@ index 0d064d98743..9b8458b413c 100644
if (fstat( dest_fd, &st ) == -1)
{
status = errno_to_status( errno );
@@ -6020,8 +6020,11 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
@@ -6165,8 +6165,11 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
/* Atomically move the link into position */
if (!renameat2( -1, tmplink, -1, unix_src, RENAME_EXCHANGE ))
{
@ -83,7 +83,7 @@ index 0d064d98743..9b8458b413c 100644
}
else if (errno == ENOSYS)
{
@@ -6229,6 +6232,7 @@ NTSTATUS FILE_RemoveSymlink(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer)
@@ -6383,6 +6386,7 @@ NTSTATUS remove_reparse_point(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer)
char tmpdir[PATH_MAX], tmpfile[PATH_MAX], *d;
BOOL tempdir_created = FALSE;
int dest_fd, needs_close;
@ -91,7 +91,7 @@ index 0d064d98743..9b8458b413c 100644
NTSTATUS status;
char *unix_name;
struct stat st;
@@ -6241,12 +6245,13 @@ NTSTATUS FILE_RemoveSymlink(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer)
@@ -6395,12 +6399,13 @@ NTSTATUS remove_reparse_point(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer)
TRACE( "Deleting symlink %s\n", unix_name );
@ -106,7 +106,7 @@ index 0d064d98743..9b8458b413c 100644
strcpy( tmpdir, unix_name );
d = dirname( tmpdir);
if (d != tmpdir) strcpy( tmpdir, d );
@@ -6259,11 +6264,21 @@ NTSTATUS FILE_RemoveSymlink(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer)
@@ -6413,11 +6418,21 @@ NTSTATUS remove_reparse_point(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer)
tempdir_created = TRUE;
strcpy( tmpfile, tmpdir );
strcat( tmpfile, "/tmpfile" );
@ -130,5 +130,5 @@ index 0d064d98743..9b8458b413c 100644
lchown( tmpfile, st.st_uid, st.st_gid );
/* Atomically move the directory into position */
--
2.20.1
2.30.2

View File

@ -1,4 +1,4 @@
From ba365806d06a93493f1f91d6ca8ab3676a513136 Mon Sep 17 00:00:00 2001
From 5c409a2387a0df100f0fe163d48ab86b66fefa20 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Tue, 30 Apr 2019 16:24:54 -0600
Subject: [PATCH] ntdll: Allow creation of dangling reparse points to
@ -6,15 +6,15 @@ Subject: [PATCH] ntdll: Allow creation of dangling reparse points to
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
---
dlls/ntdll/unix/file.c | 18 ++++++++++++++++--
dlls/ntdll/unix/file.c | 19 +++++++++++++++++--
include/winternl.h | 1 +
2 files changed, 17 insertions(+), 2 deletions(-)
2 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index 0655371dc66..a9fcf6cc444 100644
index ead0c48d62e..be57865f6b3 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -3378,7 +3378,8 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
@@ -3388,7 +3388,8 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
/* if this is the last element, not finding it is not necessarily fatal */
if (!name_len)
{
@ -24,11 +24,12 @@ index 0655371dc66..a9fcf6cc444 100644
{
status = STATUS_OBJECT_NAME_NOT_FOUND;
if (disposition != FILE_OPEN && disposition != FILE_OVERWRITE)
@@ -3398,6 +3399,19 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
@@ -3408,6 +3409,20 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
status = STATUS_OBJECT_NAME_COLLISION;
}
}
+ else if (disposition == FILE_WINE_PATH && status == STATUS_OBJECT_PATH_NOT_FOUND)
+ else if (disposition == FILE_WINE_PATH && (status == STATUS_OBJECT_PATH_NOT_FOUND
+ || status == STATUS_OBJECT_NAME_NOT_FOUND))
+ {
+ ret = ntdll_wcstoumbs( name, end - name, unix_name + pos + 1, MAX_DIR_ENTRY_LEN + 1, TRUE );
+ if (ret > 0 && ret <= MAX_DIR_ENTRY_LEN)
@ -44,7 +45,7 @@ index 0655371dc66..a9fcf6cc444 100644
if (status != STATUS_SUCCESS) break;
@@ -5953,7 +5967,7 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
@@ -6098,7 +6113,7 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
status = STATUS_NO_MEMORY;
goto cleanup;
}
@ -54,10 +55,10 @@ index 0655371dc66..a9fcf6cc444 100644
free( unix_dest );
}
diff --git a/include/winternl.h b/include/winternl.h
index d35d509eb41..561a83bd648 100644
index 8bfc7de67d0..2daee57e50f 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -2513,6 +2513,7 @@ typedef struct _RTL_ATOM_TABLE
@@ -2678,6 +2678,7 @@ typedef struct _RTL_ATOM_TABLE
#define FILE_OVERWRITE 4
#define FILE_OVERWRITE_IF 5
#define FILE_MAXIMUM_DISPOSITION 5
@ -66,5 +67,5 @@ index d35d509eb41..561a83bd648 100644
/* Characteristics of a File System */
#define FILE_REMOVABLE_MEDIA 0x00000001
--
2.20.1
2.30.2

View File

@ -1,28 +1,28 @@
From 30353100c8647bd85bdf53fe95ccc039ca3ee867 Mon Sep 17 00:00:00 2001
From 99f1cef882a3f8098c76cf0918b99882533d1bbd Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Sat, 30 Mar 2019 12:00:51 -0600
Subject: [PATCH] ntdll: Correctly report file symbolic links as files.
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
---
dlls/ntdll/unix/file.c | 115 +++++++++++++++++++++++++++--------------
1 file changed, 77 insertions(+), 38 deletions(-)
dlls/ntdll/unix/file.c | 116 +++++++++++++++++++++++++++--------------
1 file changed, 78 insertions(+), 38 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index a9fcf6cc444..5d41919267e 100644
index be57865f6b3..94be474a0ff 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -1612,6 +1612,9 @@ static inline int get_file_xattr( char *hexattr, int attrlen )
@@ -1606,6 +1606,9 @@ static inline int get_file_xattr( char *hexattr, int attrlen )
return 0;
}
+NTSTATUS FILE_DecodeSymlink(const char *unix_src, char *unix_dest, int *unix_dest_len,
+ DWORD *tag, ULONG *flags, BOOL *is_dir);
+NTSTATUS get_symlink_properties(const char *unix_src, char *unix_dest, int *unix_dest_len,
+ DWORD *tag, ULONG *flags, BOOL *is_dir);
+
/* fetch the attributes of a file */
static inline ULONG get_file_attributes( const struct stat *st )
{
@@ -1696,10 +1699,15 @@ static int get_file_info( const char *path, struct stat *st, ULONG *attr )
@@ -1690,10 +1693,15 @@ static int get_file_info( const char *path, struct stat *st, ULONG *attr )
if (ret == -1) return ret;
if (S_ISLNK( st->st_mode ))
{
@ -37,12 +37,12 @@ index a9fcf6cc444..5d41919267e 100644
+ /* symbolic links (either junction points or NT symlinks) are "reparse points" */
+ *attr |= FILE_ATTRIBUTE_REPARSE_POINT;
+ /* whether a reparse point is a file or a directory is stored inside the link target */
+ if (FILE_DecodeSymlink( path, NULL, NULL, NULL, NULL, &is_dir ) == STATUS_SUCCESS)
+ if (get_symlink_properties( path, NULL, NULL, NULL, NULL, &is_dir ) == STATUS_SUCCESS)
+ st->st_mode = (st->st_mode & ~S_IFMT) | (is_dir ? S_IFDIR : S_IFREG);
}
else if (S_ISDIR( st->st_mode ) && (parent_path = malloc( strlen(path) + 4 )))
{
@@ -6070,46 +6078,35 @@ cleanup:
@@ -6219,46 +6227,35 @@ cleanup:
}
@ -50,11 +50,12 @@ index a9fcf6cc444..5d41919267e 100644
- * Retrieve the unix name corresponding to a file handle and use that to find the destination of the
- * symlink corresponding to that file handle.
- */
-NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_size)
+NTSTATUS FILE_DecodeSymlink(const char *unix_src, char *unix_dest, int *unix_dest_len,
+ DWORD *tag, ULONG *flags, BOOL *is_dir)
-NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_size)
+NTSTATUS get_symlink_properties(const char *unix_src, char *unix_dest, int *unix_dest_len,
+ DWORD *tag, ULONG *flags, BOOL *is_dir)
{
- char *unix_src, unix_dest[PATH_MAX];
- INT prefix_len, path_len, total_len;
- VOID *subst_name, *print_name;
- SIZE_T nt_dest_len = PATH_MAX;
- BOOL dest_allocated = FALSE;
@ -66,7 +67,6 @@ index a9fcf6cc444..5d41919267e 100644
NTSTATUS status;
- ULONG flags = 0;
- WCHAR *nt_dest;
- INT prefix_len;
+ BOOL dir_flag;
+ char *p, *tmp;
ssize_t ret;
@ -105,7 +105,7 @@ index a9fcf6cc444..5d41919267e 100644
p++;
}
if (*p++ != '/')
@@ -6117,7 +6114,7 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
@@ -6266,7 +6263,7 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out
status = STATUS_NOT_IMPLEMENTED;
goto cleanup;
}
@ -114,7 +114,7 @@ index a9fcf6cc444..5d41919267e 100644
for (i = 0; i < sizeof(ULONG)*8; i++)
{
char c = *p++;
@@ -6132,22 +6129,64 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
@@ -6281,22 +6278,65 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out
status = STATUS_NOT_IMPLEMENTED;
goto cleanup;
}
@ -160,8 +160,9 @@ index a9fcf6cc444..5d41919267e 100644
+ * Retrieve the unix name corresponding to a file handle and use that to find the destination of the
+ * symlink corresponding to that file handle.
+ */
+NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_size)
+NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_size)
+{
+ INT prefix_len, path_len, total_len;
+ char *unix_src, unix_dest[PATH_MAX];
+ VOID *subst_name, *print_name;
+ SIZE_T nt_dest_len = PATH_MAX;
@ -172,7 +173,6 @@ index a9fcf6cc444..5d41919267e 100644
+ NTSTATUS status;
+ ULONG flags = 0;
+ WCHAR *nt_dest;
+ INT prefix_len;
+
+ if ((status = server_get_unix_fd( handle, FILE_ANY_ACCESS, &dest_fd, &needs_close, NULL, NULL )))
+ return status;
@ -180,11 +180,12 @@ index a9fcf6cc444..5d41919267e 100644
+ if ((status = server_get_unix_name( handle, &unix_src )))
+ goto cleanup;
+
+ if ((status = FILE_DecodeSymlink( unix_src, unix_dest, &unix_dest_len, &buffer->ReparseTag, &flags, NULL )))
+ if ((status = get_symlink_properties( unix_src, unix_dest, &unix_dest_len, &buffer->ReparseTag,
+ &flags, NULL )))
+ goto cleanup;
/* convert the relative path into an absolute path */
if (flags == SYMLINK_FLAG_RELATIVE)
--
2.20.1
2.30.2

View File

@ -1,4 +1,4 @@
From 17a86aec0579d7632eaa718800d51cdda191a4b4 Mon Sep 17 00:00:00 2001
From 29337136ad7b6bdacd2910622ef3685ebacfe8fa Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
Date: Sun, 22 Nov 2020 22:35:50 -0700
Subject: [PATCH] kernelbase: Convert FILE_FLAG_OPEN_REPARSE_POINT for passing
@ -9,10 +9,10 @@ Subject: [PATCH] kernelbase: Convert FILE_FLAG_OPEN_REPARSE_POINT for passing
1 file changed, 2 insertions(+)
diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c
index abfdade04ed..ad3c002d8c6 100644
index e0a75c2ad08..7eabf5aa211 100644
--- a/dlls/kernelbase/file.c
+++ b/dlls/kernelbase/file.c
@@ -723,6 +723,8 @@ static UINT get_nt_file_options( DWORD attributes )
@@ -725,6 +725,8 @@ static UINT get_nt_file_options( DWORD attributes )
options |= FILE_RANDOM_ACCESS;
if (attributes & FILE_FLAG_WRITE_THROUGH)
options |= FILE_WRITE_THROUGH;
@ -22,5 +22,5 @@ index abfdade04ed..ad3c002d8c6 100644
}
--
2.20.1
2.30.2

View File

@ -1,18 +1,26 @@
From 663544d9d76dcd9d9338528a41a4e58343a8fc75 Mon Sep 17 00:00:00 2001
From 05c1471fc29add8269c805692def9107de436bfa Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
Date: Sat, 12 Dec 2020 16:54:28 -0700
Subject: [PATCH] server: Implement FILE_OPEN_REPARSE_POINT option.
---
dlls/ntdll/tests/file.c | 8 ++++----
server/fd.c | 18 +++++++++++++++++-
2 files changed, 21 insertions(+), 5 deletions(-)
dlls/ntdll/tests/file.c | 27 +++++++++++++++++++++++----
server/fd.c | 39 ++++++++++++++++++++++++++++++++-------
2 files changed, 55 insertions(+), 11 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 8938c5bf50c..59f10ea8cce 100644
index e5cfbb68793..f3eecbbc708 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -5299,7 +5299,7 @@ static void test_reparse_points(void)
@@ -5299,6 +5299,7 @@ static void test_reparse_points(void)
static const WCHAR dotW[] = {'.',0};
REPARSE_DATA_BUFFER *buffer = NULL;
DWORD dwret, dwLen, dwFlags, err;
+ WCHAR buf[] = {0,0,0,0};
HANDLE handle, token;
IO_STATUS_BLOCK iosb;
UNICODE_STRING nameW;
@@ -5386,7 +5387,7 @@ static void test_reparse_points(void)
memset(&old_attrib, 0x00, sizeof(old_attrib));
old_attrib.LastAccessTime.QuadPart = 0x200deadcafebeef;
dwret = NtSetInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
@ -21,7 +29,7 @@ index 8938c5bf50c..59f10ea8cce 100644
memset(&guid_buffer, 0x00, sizeof(guid_buffer));
guid_buffer.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
bret = DeviceIoControl(handle, FSCTL_DELETE_REPARSE_POINT, (LPVOID)&guid_buffer,
@@ -5308,7 +5308,7 @@ static void test_reparse_points(void)
@@ -5395,7 +5396,7 @@ static void test_reparse_points(void)
memset(&new_attrib, 0x00, sizeof(new_attrib));
dwret = NtQueryInformationFile(handle, &iosb, &new_attrib, sizeof(new_attrib), FileBasicInformation);
ok(dwret == STATUS_SUCCESS, "Failed to get junction point folder's attributes (0x%x).\n", dwret);
@ -30,7 +38,32 @@ index 8938c5bf50c..59f10ea8cce 100644
"Junction point folder's access time does not match.\n");
CloseHandle(handle);
@@ -5446,7 +5446,7 @@ static void test_reparse_points(void)
@@ -5476,6 +5477,24 @@ static void test_reparse_points(void)
ok(bret, "Failed to create symlink! (0x%x)\n", GetLastError());
CloseHandle(handle);
+ /* Check the size/data of the symlink target when opened with FILE_FLAG_OPEN_REPARSE_POINT */
+ handle = CreateFileW(target_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
+ if (handle == INVALID_HANDLE_VALUE)
+ {
+ win_skip("Failed to open symlink file handle (0x%x).\n", GetLastError());
+ goto cleanup;
+ }
+ ok(GetFileSize(handle, NULL) == sizeof(fooW), "symlink target size does not match (%d != %d)\n",
+ GetFileSize(handle, NULL), sizeof(fooW));
+ bret = ReadFile(handle, &buf, sizeof(buf), &dwLen, NULL);
+ ok(bret, "Failed to read data from the symlink target.\n");
+ ok(dwLen == sizeof(fooW), "Length of symlink target data does not match (%d != %d).\n",
+ dwLen, sizeof(fooW));
+ ok(!memcmp(fooW, &buf, sizeof(fooW)), "Symlink target data does not match (%s != %s).\n",
+ wine_dbgstr_wn(buf, dwLen), wine_dbgstr_w(fooW));
+ CloseHandle(handle);
+
/* Check deleting a file symlink as if it were a directory */
bret = RemoveDirectoryW(reparse_path);
todo_wine ok(!bret, "Succeeded in deleting file symlink as a directory!\n");
@@ -5539,7 +5558,7 @@ static void test_reparse_points(void)
memset(&old_attrib, 0x00, sizeof(old_attrib));
old_attrib.LastAccessTime.QuadPart = 0x200deadcafebeef;
dwret = NtSetInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
@ -39,7 +72,7 @@ index 8938c5bf50c..59f10ea8cce 100644
memset(&guid_buffer, 0x00, sizeof(guid_buffer));
guid_buffer.ReparseTag = IO_REPARSE_TAG_SYMLINK;
bret = DeviceIoControl(handle, FSCTL_DELETE_REPARSE_POINT, (LPVOID)&guid_buffer,
@@ -5455,7 +5455,7 @@ static void test_reparse_points(void)
@@ -5548,7 +5567,7 @@ static void test_reparse_points(void)
memset(&new_attrib, 0x00, sizeof(new_attrib));
dwret = NtQueryInformationFile(handle, &iosb, &new_attrib, sizeof(new_attrib), FileBasicInformation);
ok(dwret == STATUS_SUCCESS, "Failed to get symlink folder's attributes (0x%x).\n", dwret);
@ -49,7 +82,7 @@ index 8938c5bf50c..59f10ea8cce 100644
CloseHandle(handle);
diff --git a/server/fd.c b/server/fd.c
index 4f43f41fb31..a01d4c9c0f7 100644
index 2605adf96ff..4fe7e6de53f 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -107,6 +107,10 @@
@ -63,19 +96,54 @@ index 4f43f41fb31..a01d4c9c0f7 100644
#if defined(HAVE_SYS_EPOLL_H) && defined(HAVE_EPOLL_CREATE)
# include <sys/epoll.h>
# define USE_EPOLL
@@ -1958,6 +1962,11 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam
@@ -1898,6 +1902,14 @@ void get_nt_name( struct fd *fd, struct unicode_str *name )
name->len = fd->nt_namelen;
}
+int check_symlink( char *name )
+{
+ struct stat st;
+
+ lstat( name, &st );
+ return S_ISLNK( st.st_mode );
+}
+
/* open() wrapper that returns a struct fd with no fd user set */
struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_name,
int flags, mode_t *mode, unsigned int access,
@@ -1958,6 +1970,18 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam
}
else rw_mode = O_RDONLY;
+ fd->unix_name = NULL;
+ if ((path = dup_fd_name( root, name )))
+ {
+ int is_symlink = check_symlink( path );
+#if defined(O_SYMLINK)
+ if ((options & FILE_OPEN_REPARSE_POINT) && !(flags & O_CREAT))
+ flags |= O_SYMLINK;
+ if (is_symlink && (options & FILE_OPEN_REPARSE_POINT) && !(flags & O_CREAT))
+ flags |= O_SYMLINK;
+#endif
+ fd->unlink_name = path;
+ fd->unix_name = realpath( path, NULL );
+ }
+
if ((fd->unix_fd = open( name, rw_mode | (flags & ~O_TRUNC), *mode )) == -1)
{
/* if we tried to open a directory for write access, retry read-only */
@@ -2431,6 +2440,7 @@ static struct fd *get_handle_fd_obj( struct process *process, obj_handle_t handl
@@ -1975,12 +1999,6 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam
}
fd->nt_name = dup_nt_name( root, nt_name, &fd->nt_namelen );
- fd->unix_name = NULL;
- if ((path = dup_fd_name( root, name )))
- {
- fd->unlink_name = path;
- fd->unix_name = realpath( path, NULL );
- }
closed_fd->unix_fd = fd->unix_fd;
closed_fd->unlink = 0;
@@ -2425,6 +2443,7 @@ static struct fd *get_handle_fd_obj( struct process *process, obj_handle_t handl
static int is_dir_empty( int fd )
{
@ -83,7 +151,7 @@ index 4f43f41fb31..a01d4c9c0f7 100644
DIR *dir;
int empty;
struct dirent *de;
@@ -2438,8 +2448,13 @@ static int is_dir_empty( int fd )
@@ -2432,8 +2451,13 @@ static int is_dir_empty( int fd )
if ((fd = dup( fd )) == -1)
return -1;
@ -98,7 +166,7 @@ index 4f43f41fb31..a01d4c9c0f7 100644
close( fd );
return -1;
}
@@ -2451,6 +2466,7 @@ static int is_dir_empty( int fd )
@@ -2445,6 +2469,7 @@ static int is_dir_empty( int fd )
empty = 0;
}
closedir( dir );
@ -107,5 +175,5 @@ index 4f43f41fb31..a01d4c9c0f7 100644
}
--
2.20.1
2.30.2

View File

@ -1,4 +1,4 @@
From 9303f780842e09a09c2e7d0a763cdd93f4289b8a Mon Sep 17 00:00:00 2001
From 2b954893dcd3d0088f214c6a12846a3cf1149e24 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
Date: Sun, 22 Nov 2020 22:37:33 -0700
Subject: [PATCH] ntdll: Allow set_file_times_precise to work on reparse
@ -11,10 +11,10 @@ Subject: [PATCH] ntdll: Allow set_file_times_precise to work on reparse
3 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/configure.ac b/configure.ac
index 11f57d13274..eea5847c51f 100644
index 7553b22e76d..7ed08b6336d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2226,7 +2226,8 @@ AC_CHECK_FUNCS(\
@@ -2227,7 +2227,8 @@ AC_CHECK_FUNCS(\
sigprocmask \
symlink \
tcdrain \
@ -25,10 +25,10 @@ index 11f57d13274..eea5847c51f 100644
CFLAGS="$ac_save_CFLAGS"
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 59f10ea8cce..8938c5bf50c 100644
index f3eecbbc708..17ed907d628 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -5299,7 +5299,7 @@ static void test_reparse_points(void)
@@ -5387,7 +5387,7 @@ static void test_reparse_points(void)
memset(&old_attrib, 0x00, sizeof(old_attrib));
old_attrib.LastAccessTime.QuadPart = 0x200deadcafebeef;
dwret = NtSetInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
@ -37,7 +37,7 @@ index 59f10ea8cce..8938c5bf50c 100644
memset(&guid_buffer, 0x00, sizeof(guid_buffer));
guid_buffer.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
bret = DeviceIoControl(handle, FSCTL_DELETE_REPARSE_POINT, (LPVOID)&guid_buffer,
@@ -5308,7 +5308,7 @@ static void test_reparse_points(void)
@@ -5396,7 +5396,7 @@ static void test_reparse_points(void)
memset(&new_attrib, 0x00, sizeof(new_attrib));
dwret = NtQueryInformationFile(handle, &iosb, &new_attrib, sizeof(new_attrib), FileBasicInformation);
ok(dwret == STATUS_SUCCESS, "Failed to get junction point folder's attributes (0x%x).\n", dwret);
@ -46,7 +46,7 @@ index 59f10ea8cce..8938c5bf50c 100644
"Junction point folder's access time does not match.\n");
CloseHandle(handle);
@@ -5446,7 +5446,7 @@ static void test_reparse_points(void)
@@ -5558,7 +5558,7 @@ static void test_reparse_points(void)
memset(&old_attrib, 0x00, sizeof(old_attrib));
old_attrib.LastAccessTime.QuadPart = 0x200deadcafebeef;
dwret = NtSetInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
@ -55,7 +55,7 @@ index 59f10ea8cce..8938c5bf50c 100644
memset(&guid_buffer, 0x00, sizeof(guid_buffer));
guid_buffer.ReparseTag = IO_REPARSE_TAG_SYMLINK;
bret = DeviceIoControl(handle, FSCTL_DELETE_REPARSE_POINT, (LPVOID)&guid_buffer,
@@ -5455,7 +5455,7 @@ static void test_reparse_points(void)
@@ -5567,7 +5567,7 @@ static void test_reparse_points(void)
memset(&new_attrib, 0x00, sizeof(new_attrib));
dwret = NtQueryInformationFile(handle, &iosb, &new_attrib, sizeof(new_attrib), FileBasicInformation);
ok(dwret == STATUS_SUCCESS, "Failed to get symlink folder's attributes (0x%x).\n", dwret);
@ -65,10 +65,10 @@ index 59f10ea8cce..8938c5bf50c 100644
CloseHandle(handle);
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index 5d41919267e..4fb5afc2755 100644
index 94be474a0ff..319f42e9e0c 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -1737,6 +1737,14 @@ static int get_file_info( const char *path, struct stat *st, ULONG *attr )
@@ -1731,6 +1731,14 @@ static int get_file_info( const char *path, struct stat *st, ULONG *attr )
}
@ -83,7 +83,7 @@ index 5d41919267e..4fb5afc2755 100644
#if defined(__ANDROID__) && !defined(HAVE_FUTIMENS)
static int futimens( int fd, const struct timespec spec[2] )
{
@@ -1752,7 +1760,7 @@ static int futimens( int fd, const struct timespec spec[2] )
@@ -1746,7 +1754,7 @@ static int futimens( int fd, const struct timespec spec[2] )
static BOOL set_file_times_precise( int fd, const LARGE_INTEGER *mtime,
const LARGE_INTEGER *atime, NTSTATUS *status )
{
@ -92,26 +92,26 @@ index 5d41919267e..4fb5afc2755 100644
struct timespec tv[2];
tv[0].tv_sec = tv[1].tv_sec = 0;
@@ -1768,10 +1776,16 @@ static BOOL set_file_times_precise( int fd, const LARGE_INTEGER *mtime,
@@ -1762,10 +1770,16 @@ static BOOL set_file_times_precise( int fd, const LARGE_INTEGER *mtime,
tv[1].tv_nsec = (mtime->QuadPart % 10000000) * 100;
}
#ifdef __APPLE__
- if (!&futimens) return FALSE;
+ if (!&utimensat || !&futimens) return FALSE;
+#endif
#endif
- if (futimens( fd, tv ) == -1) *status = errno_to_status( errno );
- else *status = STATUS_SUCCESS;
+#if defined(HAVE_UTIMENSAT)
+ /* futimens does not work on O_PATH|O_NOFOLLOW (O_SYMLINK) file descriptors, so if fd is for a
+ * symlink then use utimensat with an empty path (.) and do not follow the link. */
+ if (utimensat(fd, ".", tv, AT_SYMLINK_NOFOLLOW) == 0) *status = STATUS_SUCCESS;
+ else
#endif
- if (futimens( fd, tv ) == -1) *status = errno_to_status( errno );
- else *status = STATUS_SUCCESS;
+#endif
+ if (futimens(fd, tv) == 0) *status = STATUS_SUCCESS;
+ else *status = errno_to_status( errno );
return TRUE;
#else
return FALSE;
--
2.20.1
2.30.2

View File

@ -1,4 +1,4 @@
From b17dd0d9dbfe6aff1654c1b8fe49019d5f97d139 Mon Sep 17 00:00:00 2001
From 4ee6ccb3ca1639d81bd9e8ce572131905e6a8df1 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Sat, 30 Mar 2019 13:41:07 -0600
Subject: [PATCH] server: Properly handle file symlink deletion.
@ -10,10 +10,10 @@ Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
2 files changed, 62 insertions(+), 8 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 8938c5bf50c..c5c186748b6 100644
index 17ed907d628..a4648dd65e0 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -5391,18 +5391,18 @@ static void test_reparse_points(void)
@@ -5497,18 +5497,18 @@ static void test_reparse_points(void)
/* Check deleting a file symlink as if it were a directory */
bret = RemoveDirectoryW(reparse_path);
@ -39,11 +39,11 @@ index 8938c5bf50c..c5c186748b6 100644
/* Create a blank slate for directory symlink tests */
bret = CreateDirectoryW(reparse_path, NULL);
diff --git a/server/fd.c b/server/fd.c
index a01d4c9c0f7..c4de093b40b 100644
index 4fe7e6de53f..fcffe4a4afd 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1902,6 +1902,55 @@ void get_nt_name( struct fd *fd, struct unicode_str *name )
name->len = fd->nt_namelen;
@@ -1910,6 +1910,55 @@ int check_symlink( char *name )
return S_ISLNK( st.st_mode );
}
+static void decode_symlink(char *name, int *is_dir)
@ -98,7 +98,7 @@ index a01d4c9c0f7..c4de093b40b 100644
/* open() wrapper that returns a struct fd with no fd user set */
struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_name,
int flags, mode_t *mode, unsigned int access,
@@ -2003,6 +2052,7 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam
@@ -2012,6 +2061,7 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam
{
unsigned int err;
struct inode *inode = get_inode( st.st_dev, st.st_ino, fd->unix_fd );
@ -106,7 +106,7 @@ index a01d4c9c0f7..c4de093b40b 100644
if (!inode)
{
@@ -2017,16 +2067,20 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam
@@ -2026,16 +2076,20 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam
list_add_head( &inode->open, &fd->inode_entry );
closed_fd = NULL;
@ -130,5 +130,5 @@ index a01d4c9c0f7..c4de093b40b 100644
set_error( STATUS_FILE_IS_A_DIRECTORY );
goto error;
--
2.20.1
2.30.2

View File

@ -1,4 +1,4 @@
From 879b893a5429ba4aa0ced3fdefd284dcca0b0a7d Mon Sep 17 00:00:00 2001
From 4f38f2552b1d31e427ea0c45f2146485a4ade4ee Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
Date: Sat, 12 Dec 2020 17:40:27 -0700
Subject: [PATCH] server: Properly handle deleting dangling symlinks.
@ -8,18 +8,18 @@ Subject: [PATCH] server: Properly handle deleting dangling symlinks.
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/server/fd.c b/server/fd.c
index c4de093b40b..da5bee3e5ec 100644
index fcffe4a4afd..4ef3c673268 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2038,6 +2038,7 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam
{
@@ -2029,6 +2029,7 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam
#endif
fd->unlink_name = path;
fd->unix_name = realpath( path, NULL );
+ if (!fd->unix_name) fd->unix_name = dup_fd_name( root, name ); /* dangling symlink */
}
closed_fd->unix_fd = fd->unix_fd;
@@ -2548,7 +2549,7 @@ static void set_fd_disposition( struct fd *fd, int unlink )
if ((fd->unix_fd = open( name, rw_mode | (flags & ~O_TRUNC), *mode )) == -1)
@@ -2551,7 +2552,7 @@ static void set_fd_disposition( struct fd *fd, int unlink )
file_set_error();
return;
}
@ -29,5 +29,5 @@ index c4de093b40b..da5bee3e5ec 100644
if (!(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
{
--
2.20.1
2.30.2

View File

@ -1,4 +1,4 @@
From b5c33b762b57ac73bc374e8aea6199730524ea59 Mon Sep 17 00:00:00 2001
From 948fd2c1ec52cb7921d23b3fbaaf355075928611 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
Date: Sat, 12 Dec 2020 17:35:21 -0700
Subject: [PATCH] kernelbase: Use FILE_OPEN_REPARSE_POINT in
@ -9,10 +9,10 @@ Subject: [PATCH] kernelbase: Use FILE_OPEN_REPARSE_POINT in
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c
index ad3c002d8c6..375c00c7367 100644
index 7eabf5aa211..80497c1ac97 100644
--- a/dlls/kernelbase/file.c
+++ b/dlls/kernelbase/file.c
@@ -3482,7 +3482,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH RemoveDirectoryW( LPCWSTR path )
@@ -3484,7 +3484,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH RemoveDirectoryW( LPCWSTR path )
InitializeObjectAttributes( &attr, &nt_name, OBJ_CASE_INSENSITIVE, 0, NULL );
status = NtOpenFile( &handle, DELETE | SYNCHRONIZE, &attr, &io,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
@ -22,5 +22,5 @@ index ad3c002d8c6..375c00c7367 100644
if (!status)
--
2.20.1
2.30.2

Some files were not shown because too many files have changed in this diff Show More