You've already forked wine-staging
mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-09-12 18:50:20 -07:00
Updated ntdll-Junction_Points patchset
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
From 87bbbc7d6c67c2ec3e13f84a7eecccb71e486ac0 Mon Sep 17 00:00:00 2001
|
||||
From 589bbdea7af00507d3dce26feec1c6db1d8e9746 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: ntdll: Add support for junction point creation.
|
||||
@@ -18,10 +18,10 @@ Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
create mode 100644 libs/port/renameat2.c
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index d1502bacf7..84307f0f54 100644
|
||||
index 0ad8417735..39a9571a95 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -2207,6 +2207,8 @@ AC_CHECK_FUNCS(\
|
||||
@@ -2206,6 +2206,8 @@ AC_CHECK_FUNCS(\
|
||||
pwrite \
|
||||
readdir \
|
||||
readlink \
|
||||
@@ -305,10 +305,10 @@ index 8e54dbb541..322dadefe3 100644
|
||||
+ test_reparse_points();
|
||||
}
|
||||
diff --git a/include/Makefile.in b/include/Makefile.in
|
||||
index 4a0f927082..519a34c856 100644
|
||||
index 979695f552..2a1382e811 100644
|
||||
--- a/include/Makefile.in
|
||||
+++ b/include/Makefile.in
|
||||
@@ -480,6 +480,7 @@ SOURCES = \
|
||||
@@ -482,6 +482,7 @@ SOURCES = \
|
||||
ntddvdeo.h \
|
||||
ntdef.h \
|
||||
ntdsapi.h \
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From 38245bc3099137dd16dc78e3f41c6d50b7f0f804 Mon Sep 17 00:00:00 2001
|
||||
From 56730d38b6326cee609916af394a37d4559d249e 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: ntdll: Add support for reading junction points.
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From 9f0a95668d86bacd6cd006e6fe6c6d463cfb5e9b Mon Sep 17 00:00:00 2001
|
||||
From 424814c370108dcad48290dc203adff96672dea9 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: ntdll: Add support for deleting junction points.
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From 52fb88dc16f22188dd2b3800fc1cd0034dbd118e Mon Sep 17 00:00:00 2001
|
||||
From 3e60e844c4ce938fb12ff09d561967a75e110f82 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: ntdll: Add a test for junction point advertisement.
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From db064094e068f3e6434f4b4302c5b2eadf8395ef Mon Sep 17 00:00:00 2001
|
||||
From f0ac5c57f3a0c2ddb542ed1cc1e78513ad4a60fe 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: kernel32,ntdll: Add support for deleting junction points with
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From aa5ad3e25315a3ca2113df9a80e178fdfef58296 Mon Sep 17 00:00:00 2001
|
||||
From 944851b4f7cda627c3c35a6735f14121b87d0148 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Thu, 16 Jan 2014 21:03:47 -0700
|
||||
Subject: kernel32: Advertise junction point support.
|
||||
@@ -9,7 +9,7 @@ Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
1 file changed, 84 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/kernel32/volume.c b/dlls/kernel32/volume.c
|
||||
index 12084369cb..76bb32b850 100644
|
||||
index 4fd913aa22..437832e5c9 100644
|
||||
--- a/dlls/kernel32/volume.c
|
||||
+++ b/dlls/kernel32/volume.c
|
||||
@@ -44,6 +44,19 @@
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From 8547ee103b062ae2c8e1a5fd058ea3e9dc8a2146 Mon Sep 17 00:00:00 2001
|
||||
From 7183c92e5f02346e8d72432a602fb7dfc3659a5b 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: ntdll: Add support for absolute symlink creation.
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From b9fa01baf73dc3975bd56b9b0ce0d26eddb45e81 Mon Sep 17 00:00:00 2001
|
||||
From d3129f74304e5fa5ba33eb51bd4ef1e9bfce1b8f 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: ntdll: Add support for reading absolute symlinks.
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From 90921ac6aba0f98fb9b33104c82d77e07cc82278 Mon Sep 17 00:00:00 2001
|
||||
From 9bc86ef7b245595248c0f5b157c9a57f4ce0c8aa 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: ntdll: Add support for deleting symlinks.
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From 4cfe8631a57057a13afa650f41576c8c3ae465d5 Mon Sep 17 00:00:00 2001
|
||||
From 0879c8d8575ba4ff1b7e9f408679c4fb92468f62 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: ntdll: Add support for relative symlink creation.
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From cdd6070ee2b8876877c66bfdaa44b4b152633b1d Mon Sep 17 00:00:00 2001
|
||||
From 7c02ce3203b8796455d12423b960b720e90a9639 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: ntdll: Add support for reading relative symlinks.
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From 05a16c210c3dabb07cc5b5514e9745f00fb364ea Mon Sep 17 00:00:00 2001
|
||||
From ac69cecc3f024819efae83723b77d9f310b43251 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: ntdll: Add support for file symlinks.
|
||||
@@ -92,7 +92,7 @@ index 5df2d8c3fa..03a07d46cd 100644
|
||||
lchown( tmpfile, st.st_uid, st.st_gid );
|
||||
/* Atomically move the directory into position */
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index c13ee84bf0..f40dc1f51b 100644
|
||||
index c13ee84bf0..5bf8ebf704 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5050,6 +5050,39 @@ static void test_reparse_points(void)
|
||||
@@ -106,7 +106,7 @@ index c13ee84bf0..f40dc1f51b 100644
|
||||
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
|
||||
+ if (handle == INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ win_skip("Failed to open symlink directory handle (0x%x).\n", GetLastError());
|
||||
+ win_skip("Failed to open symlink file handle (0x%x).\n", GetLastError());
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ dwret = NtQueryInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
|
||||
|
@@ -0,0 +1,68 @@
|
||||
From 1cb09e87cf0fd0a805849f3483d2b3b7bed5ec18 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: ntdll: Allow creation of dangling reparse points to non-existent
|
||||
paths.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/directory.c | 14 ++++++++++++++
|
||||
dlls/ntdll/file.c | 3 ++-
|
||||
include/winternl.h | 1 +
|
||||
3 files changed, 17 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
|
||||
index bbdbbe9781..cca1e3c4a8 100644
|
||||
--- a/dlls/ntdll/directory.c
|
||||
+++ b/dlls/ntdll/directory.c
|
||||
@@ -2705,6 +2705,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)
|
||||
+ {
|
||||
+ ret = ntdll_wcstoumbs( 0, name, end - name, unix_name + pos + 1,
|
||||
+ MAX_DIR_ENTRY_LEN, NULL, &used_default );
|
||||
+ if (ret > 0 && !used_default)
|
||||
+ {
|
||||
+ unix_name[pos] = '/';
|
||||
+ unix_name[pos + 1 + ret] = 0;
|
||||
+ status = STATUS_NO_SUCH_FILE;
|
||||
+ pos += strlen( unix_name + pos );
|
||||
+ name = next;
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
if (status != STATUS_SUCCESS) break;
|
||||
|
||||
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
|
||||
index 03a07d46cd..04d34dd572 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -1722,8 +1722,9 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
RtlCreateUnicodeString( &nt_dest, dest );
|
||||
nt_dest.Length = dest_len;
|
||||
}
|
||||
+
|
||||
nt_dest_allocated = TRUE;
|
||||
- status = wine_nt_to_unix_file_name( &nt_dest, &unix_dest, 0, FALSE );
|
||||
+ status = wine_nt_to_unix_file_name( &nt_dest, &unix_dest, FILE_WINE_PATH, FALSE );
|
||||
if (status != STATUS_SUCCESS && status != STATUS_NO_SUCH_FILE)
|
||||
goto cleanup;
|
||||
dest_allocated = TRUE;
|
||||
diff --git a/include/winternl.h b/include/winternl.h
|
||||
index 2b3fb947b9..7f6b2f57ba 100644
|
||||
--- a/include/winternl.h
|
||||
+++ b/include/winternl.h
|
||||
@@ -1788,6 +1788,7 @@ typedef struct _RTL_HANDLE_TABLE
|
||||
#define FILE_OVERWRITE 4
|
||||
#define FILE_OVERWRITE_IF 5
|
||||
#define FILE_MAXIMUM_DISPOSITION 5
|
||||
+#define FILE_WINE_PATH 6
|
||||
|
||||
/* Characteristics of a File System */
|
||||
#define FILE_REMOVABLE_MEDIA 0x00000001
|
||||
--
|
||||
2.17.1
|
||||
|
@@ -1,16 +1,16 @@
|
||||
From 9c0229cf831240320ef2797dbfd21493d7871088 Mon Sep 17 00:00:00 2001
|
||||
From 20171f2a705fdf94966e9661d360ac70bb92cb8e 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: ntdll: Correctly report file symbolic links as files.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/file.c | 110 +++++++++++++++++++++++++++-------------
|
||||
dlls/ntdll/file.c | 118 ++++++++++++++++++++++++++--------------
|
||||
dlls/ntdll/tests/file.c | 8 +--
|
||||
2 files changed, 79 insertions(+), 39 deletions(-)
|
||||
2 files changed, 82 insertions(+), 44 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
|
||||
index 03a07d46cd..8b78306fbf 100644
|
||||
index 04d34dd572..8336392ddb 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -124,6 +124,9 @@ mode_t FILE_umask = 0;
|
||||
@@ -23,22 +23,25 @@ index 03a07d46cd..8b78306fbf 100644
|
||||
/* fetch the attributes of a file */
|
||||
static inline ULONG get_file_attributes( const struct stat *st )
|
||||
{
|
||||
@@ -160,10 +163,14 @@ int get_file_info( const char *path, struct stat *st, ULONG *attr )
|
||||
@@ -160,10 +163,13 @@ int get_file_info( const char *path, struct stat *st, ULONG *attr )
|
||||
if (ret == -1) return ret;
|
||||
if (S_ISLNK( st->st_mode ))
|
||||
{
|
||||
- ret = stat( path, st );
|
||||
- if (ret == -1) return ret;
|
||||
- /* is a symbolic link and a directory, consider these "reparse points" */
|
||||
- if (S_ISDIR( st->st_mode )) *attr |= FILE_ATTRIBUTE_REPARSE_POINT;
|
||||
+ BOOL is_dir;
|
||||
+
|
||||
ret = stat( path, st );
|
||||
if (ret == -1) return ret;
|
||||
/* is a symbolic link and a directory, consider these "reparse points" */
|
||||
if (S_ISDIR( st->st_mode )) *attr |= FILE_ATTRIBUTE_REPARSE_POINT;
|
||||
+ if (FILE_DecodeSymlink( path, NULL, NULL, NULL, NULL, &is_dir) == STATUS_SUCCESS)
|
||||
+ /* 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)
|
||||
+ st->st_mode = (st->st_mode & ~S_IFMT) | (is_dir ? S_IFDIR : S_IFREG);
|
||||
}
|
||||
*attr |= get_file_attributes( st );
|
||||
return ret;
|
||||
@@ -1825,48 +1832,34 @@ cleanup:
|
||||
@@ -1826,48 +1832,33 @@ cleanup:
|
||||
}
|
||||
|
||||
|
||||
@@ -78,13 +81,13 @@ index 03a07d46cd..8b78306fbf 100644
|
||||
- unix_dest.MaximumLength = PATH_MAX;
|
||||
- dest_allocated = TRUE;
|
||||
- ret = readlink( unix_src.Buffer, unix_dest.Buffer, unix_dest.MaximumLength );
|
||||
- if (ret < 0)
|
||||
+ if (unix_dest_len) len = *unix_dest_len;
|
||||
+ if (!unix_dest)
|
||||
+ tmp = RtlAllocateHeap( GetProcessHeap(), 0, len );
|
||||
+ else
|
||||
+ tmp = unix_dest;
|
||||
+ ret = readlink( unix_src, tmp, len );
|
||||
if (ret < 0)
|
||||
+ if ((ret = readlink( unix_src, tmp, len )) < 0)
|
||||
{
|
||||
status = FILE_GetNtStatus();
|
||||
goto cleanup;
|
||||
@@ -102,7 +105,7 @@ index 03a07d46cd..8b78306fbf 100644
|
||||
p++;
|
||||
}
|
||||
if (*p++ != '/')
|
||||
@@ -1874,7 +1867,7 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
@@ -1875,7 +1866,7 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
status = STATUS_NOT_IMPLEMENTED;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -111,7 +114,7 @@ index 03a07d46cd..8b78306fbf 100644
|
||||
for (i = 0; i < sizeof(ULONG)*8; i++)
|
||||
{
|
||||
char c = *p++;
|
||||
@@ -1889,21 +1882,68 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
@@ -1890,21 +1881,68 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
status = STATUS_NOT_IMPLEMENTED;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -186,7 +189,7 @@ index 03a07d46cd..8b78306fbf 100644
|
||||
/* convert the relative path into an absolute path */
|
||||
if (flags == SYMLINK_FLAG_RELATIVE)
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index f40dc1f51b..f23bf8644c 100644
|
||||
index 5bf8ebf704..bacfad266e 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5069,13 +5069,13 @@ static void test_reparse_points(void)
|
@@ -0,0 +1,137 @@
|
||||
From 4f8611e2dfc7fb70e13a6f05949257e5d441328a Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Wed, 1 May 2019 19:46:03 -0600
|
||||
Subject: ntdll: Correctly report fd-based file info for symlinks.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/file.c | 64 ++++++++++++++++++++++++++++++++++-------------
|
||||
1 file changed, 46 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
|
||||
index 8336392ddb..934577bfba 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -141,18 +141,6 @@ static inline ULONG get_file_attributes( const struct stat *st )
|
||||
return attr;
|
||||
}
|
||||
|
||||
-/* get the stat info and file attributes for a file (by file descriptor) */
|
||||
-int fd_get_file_info( int fd, struct stat *st, ULONG *attr )
|
||||
-{
|
||||
- int ret;
|
||||
-
|
||||
- *attr = 0;
|
||||
- ret = fstat( fd, st );
|
||||
- if (ret == -1) return ret;
|
||||
- *attr |= get_file_attributes( st );
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
/* get the stat info and file attributes for a file (by name) */
|
||||
int get_file_info( const char *path, struct stat *st, ULONG *attr )
|
||||
{
|
||||
@@ -175,6 +163,46 @@ int get_file_info( const char *path, struct stat *st, ULONG *attr )
|
||||
return ret;
|
||||
}
|
||||
|
||||
+/* get the stat info and file attributes for a file (by file descriptor) */
|
||||
+int fd_get_file_info( HANDLE h, int fd, struct stat *st, ULONG *attr )
|
||||
+{
|
||||
+ ANSI_STRING unix_src;
|
||||
+ struct stat tmp;
|
||||
+ int ret = -1;
|
||||
+
|
||||
+ /* if this handle is to a symlink then we need to return information about the symlink */
|
||||
+ if (server_get_unix_name( h, &unix_src ) != STATUS_SUCCESS)
|
||||
+ return ret;
|
||||
+ ret = get_file_info( unix_src.Buffer, st, attr);
|
||||
+ RtlFreeAnsiString( &unix_src );
|
||||
+ if (ret == -1) return ret;
|
||||
+ /* but return the times from the file itself */
|
||||
+ ret = fstat( fd, &tmp );
|
||||
+ if (ret == -1) return ret;
|
||||
+#if defined(HAVE_STRUCT_STAT_ST_ATIM)
|
||||
+ st->st_atim = tmp.st_atim;
|
||||
+#elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC)
|
||||
+ st->st_atimespec = tmp.st_atimespec;
|
||||
+#else
|
||||
+ st->st_atime = tmp.st_atime;
|
||||
+#endif
|
||||
+#if defined(HAVE_STRUCT_STAT_ST_MTIM)
|
||||
+ st->st_mtim = tmp.st_mtim;
|
||||
+#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC)
|
||||
+ st->st_mtimespec = tmp.st_mtimespec;
|
||||
+#else
|
||||
+ st->st_mtime = tmp.st_mtime;
|
||||
+#endif
|
||||
+#if defined(HAVE_STRUCT_STAT_ST_CTIM)
|
||||
+ st->st_ctim = tmp.st_ctim;
|
||||
+#elif defined(HAVE_STRUCT_STAT_ST_CTIMESPEC)
|
||||
+ st->st_ctimespec = tmp.st_ctimespec;
|
||||
+#else
|
||||
+ st->st_ctime = tmp.st_ctime;
|
||||
+#endif
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/**************************************************************************
|
||||
* FILE_CreateFile (internal)
|
||||
* Open a file.
|
||||
@@ -2832,7 +2860,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
|
||||
switch (class)
|
||||
{
|
||||
case FileBasicInformation:
|
||||
- if (fd_get_file_info( fd, &st, &attr ) == -1)
|
||||
+ if (fd_get_file_info( hFile, fd, &st, &attr ) == -1)
|
||||
io->u.Status = FILE_GetNtStatus();
|
||||
else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
|
||||
io->u.Status = STATUS_INVALID_INFO_CLASS;
|
||||
@@ -2843,7 +2871,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
|
||||
{
|
||||
FILE_STANDARD_INFORMATION *info = ptr;
|
||||
|
||||
- if (fd_get_file_info( fd, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
|
||||
+ if (fd_get_file_info( hFile, fd, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
|
||||
else
|
||||
{
|
||||
fill_file_info( &st, attr, info, class );
|
||||
@@ -2860,7 +2888,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
|
||||
}
|
||||
break;
|
||||
case FileInternalInformation:
|
||||
- if (fd_get_file_info( fd, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
|
||||
+ if (fd_get_file_info( hFile, fd, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
|
||||
else fill_file_info( &st, attr, ptr, class );
|
||||
break;
|
||||
case FileEaInformation:
|
||||
@@ -2870,7 +2898,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
|
||||
}
|
||||
break;
|
||||
case FileEndOfFileInformation:
|
||||
- if (fd_get_file_info( fd, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
|
||||
+ if (fd_get_file_info( hFile, fd, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
|
||||
else fill_file_info( &st, attr, ptr, class );
|
||||
break;
|
||||
case FileAllInformation:
|
||||
@@ -2878,7 +2906,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
|
||||
FILE_ALL_INFORMATION *info = ptr;
|
||||
ANSI_STRING unix_name;
|
||||
|
||||
- if (fd_get_file_info( fd, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
|
||||
+ if (fd_get_file_info( hFile, fd, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
|
||||
else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
|
||||
io->u.Status = STATUS_INVALID_INFO_CLASS;
|
||||
else if (!(io->u.Status = server_get_unix_name( hFile, &unix_name )))
|
||||
@@ -2986,7 +3014,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
|
||||
}
|
||||
break;
|
||||
case FileIdInformation:
|
||||
- if (fd_get_file_info( fd, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
|
||||
+ if (fd_get_file_info( hFile, fd, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
|
||||
else
|
||||
{
|
||||
FILE_ID_INFORMATION *info = ptr;
|
||||
--
|
||||
2.17.1
|
||||
|
@@ -1,288 +0,0 @@
|
||||
From 99b54adfcc2740af27224957748f94a0e84b47c3 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Wed, 13 Mar 2019 16:02:05 -0600
|
||||
Subject: kernel32: Implement CreateSymbolicLink[A|W] with ntdll reparse
|
||||
points.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/kernel32/path.c | 124 +++++++++++++++++++++++++++++++++++--
|
||||
dlls/kernel32/tests/path.c | 94 ++++++++++++++++++++++++++++
|
||||
2 files changed, 214 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/path.c b/dlls/kernel32/path.c
|
||||
index f15b6dd68b..d96471e4c6 100644
|
||||
--- a/dlls/kernel32/path.c
|
||||
+++ b/dlls/kernel32/path.c
|
||||
@@ -34,6 +34,8 @@
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winternl.h"
|
||||
+#include "winioctl.h"
|
||||
+#include "ntifs.h"
|
||||
|
||||
#include "kernel_private.h"
|
||||
#include "wine/unicode.h"
|
||||
@@ -2087,8 +2089,106 @@ WCHAR * CDECL wine_get_dos_file_name( LPCSTR str )
|
||||
*/
|
||||
BOOLEAN WINAPI CreateSymbolicLinkW(LPCWSTR link, LPCWSTR target, DWORD flags)
|
||||
{
|
||||
- FIXME("(%s %s %d): stub\n", debugstr_w(link), debugstr_w(target), flags);
|
||||
- return TRUE;
|
||||
+ static INT struct_size = offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer[0]);
|
||||
+ static INT header_size = offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer);
|
||||
+ INT buffer_size, data_size, string_len, prefix_len;
|
||||
+ WCHAR *subst_dest, *print_dest, *string;
|
||||
+ REPARSE_DATA_BUFFER *buffer;
|
||||
+ LPWSTR target_path = NULL;
|
||||
+ BOOL is_relative, is_dir;
|
||||
+ int target_path_len = 0;
|
||||
+ UNICODE_STRING nt_name;
|
||||
+ BOOLEAN bret = FALSE;
|
||||
+ NTSTATUS status;
|
||||
+ HANDLE hlink;
|
||||
+ DWORD dwret;
|
||||
+
|
||||
+ TRACE("(%s %s %d)\n", debugstr_w(link), debugstr_w(target), flags);
|
||||
+
|
||||
+ is_relative = (RtlDetermineDosPathNameType_U( target ) == RELATIVE_PATH);
|
||||
+ is_dir = (flags & SYMBOLIC_LINK_FLAG_DIRECTORY);
|
||||
+ if (is_dir && !CreateDirectoryW( link, NULL ))
|
||||
+ return FALSE;
|
||||
+ hlink = CreateFileW( link, GENERIC_READ | GENERIC_WRITE, 0, 0,
|
||||
+ is_dir ? OPEN_EXISTING : CREATE_NEW,
|
||||
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0 );
|
||||
+ if (hlink == INVALID_HANDLE_VALUE)
|
||||
+ goto cleanup;
|
||||
+ if (is_relative)
|
||||
+ {
|
||||
+ UNICODE_STRING nt_path;
|
||||
+ int len;
|
||||
+
|
||||
+ status = RtlDosPathNameToNtPathName_U_WithStatus( link, &nt_path, NULL, NULL );
|
||||
+ if (status != STATUS_SUCCESS)
|
||||
+ {
|
||||
+ SetLastError( RtlNtStatusToDosError(status) );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ /* obtain the path of the link */
|
||||
+ for (; nt_path.Length > 0; nt_path.Length -= sizeof(WCHAR))
|
||||
+ {
|
||||
+ WCHAR c = nt_path.Buffer[nt_path.Length/sizeof(WCHAR)];
|
||||
+ if (c == '/' || c == '\\')
|
||||
+ {
|
||||
+ nt_path.Length += sizeof(WCHAR);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ /* append the target to the link path */
|
||||
+ target_path_len = nt_path.Length / sizeof(WCHAR);
|
||||
+ len = target_path_len + (strlenW( target ) + 1);
|
||||
+ target_path = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len*sizeof(WCHAR) );
|
||||
+ lstrcpynW( target_path, nt_path.Buffer, nt_path.Length );
|
||||
+ target_path[nt_path.Length/sizeof(WCHAR)] = 0;
|
||||
+ lstrcatW( target_path, target );
|
||||
+ RtlFreeUnicodeString( &nt_path );
|
||||
+ }
|
||||
+ else
|
||||
+ target_path = (LPWSTR)target;
|
||||
+ status = RtlDosPathNameToNtPathName_U_WithStatus( target_path, &nt_name, NULL, NULL );
|
||||
+ if (status != STATUS_SUCCESS)
|
||||
+ {
|
||||
+ SetLastError( RtlNtStatusToDosError(status) );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ if (is_relative && strncmpW( target_path, nt_name.Buffer, target_path_len ) != 0)
|
||||
+ {
|
||||
+ SetLastError( RtlNtStatusToDosError(status) );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ prefix_len = is_relative ? 0 : strlen("\\??\\");
|
||||
+ string = &nt_name.Buffer[target_path_len];
|
||||
+ string_len = lstrlenW( &string[prefix_len] );
|
||||
+ data_size = (prefix_len + 2 * string_len + 2) * sizeof(WCHAR);
|
||||
+ buffer_size = struct_size + data_size;
|
||||
+ buffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_size );
|
||||
+ buffer->ReparseTag = IO_REPARSE_TAG_SYMLINK;
|
||||
+ buffer->ReparseDataLength = struct_size - header_size + data_size;
|
||||
+ 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);
|
||||
+ buffer->SymbolicLinkReparseBuffer.Flags = is_relative ? SYMLINK_FLAG_RELATIVE : 0;
|
||||
+ subst_dest = &buffer->SymbolicLinkReparseBuffer.PathBuffer[0];
|
||||
+ print_dest = &buffer->SymbolicLinkReparseBuffer.PathBuffer[prefix_len + string_len + 1];
|
||||
+ lstrcpyW( subst_dest, string );
|
||||
+ lstrcpyW( print_dest, &string[prefix_len] );
|
||||
+ RtlFreeUnicodeString( &nt_name );
|
||||
+ bret = DeviceIoControl( hlink, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_size, NULL, 0,
|
||||
+ &dwret, 0 );
|
||||
+ CloseHandle( hlink );
|
||||
+ HeapFree( GetProcessHeap(), 0, buffer );
|
||||
+
|
||||
+cleanup:
|
||||
+ if (!bret)
|
||||
+ {
|
||||
+ if (is_dir)
|
||||
+ RemoveDirectoryW( link );
|
||||
+ else
|
||||
+ DeleteFileW( link );
|
||||
+ }
|
||||
+ if (is_relative) HeapFree( GetProcessHeap(), 0, target_path );
|
||||
+ return bret;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
@@ -2096,8 +2196,24 @@ BOOLEAN WINAPI CreateSymbolicLinkW(LPCWSTR link, LPCWSTR target, DWORD flags)
|
||||
*/
|
||||
BOOLEAN WINAPI CreateSymbolicLinkA(LPCSTR link, LPCSTR target, DWORD flags)
|
||||
{
|
||||
- FIXME("(%s %s %d): stub\n", debugstr_a(link), debugstr_a(target), flags);
|
||||
- return TRUE;
|
||||
+ WCHAR *targetW, *linkW;
|
||||
+ BOOL ret;
|
||||
+
|
||||
+ TRACE("(%s %s %d)\n", debugstr_a(link), debugstr_a(target), flags);
|
||||
+
|
||||
+ if (!(linkW = FILE_name_AtoW( link, TRUE )))
|
||||
+ {
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ if (!(targetW = FILE_name_AtoW( target, TRUE )))
|
||||
+ {
|
||||
+ HeapFree( GetProcessHeap(), 0, linkW );
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ ret = CreateSymbolicLinkW( linkW, targetW, flags );
|
||||
+ HeapFree( GetProcessHeap(), 0, linkW );
|
||||
+ HeapFree( GetProcessHeap(), 0, targetW );
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
diff --git a/dlls/kernel32/tests/path.c b/dlls/kernel32/tests/path.c
|
||||
index 0a03225120..076333b3b1 100644
|
||||
--- a/dlls/kernel32/tests/path.c
|
||||
+++ b/dlls/kernel32/tests/path.c
|
||||
@@ -81,6 +81,9 @@ static void (WINAPI *pReleaseActCtx)(HANDLE);
|
||||
static BOOL (WINAPI *pCheckNameLegalDOS8Dot3W)(const WCHAR *, char *, DWORD, BOOL *, BOOL *);
|
||||
static BOOL (WINAPI *pCheckNameLegalDOS8Dot3A)(const char *, char *, DWORD, BOOL *, BOOL *);
|
||||
|
||||
+/* Present in Vista+ */
|
||||
+static BOOL (WINAPI *pCreateSymbolicLinkW)(LPCWSTR, LPCWSTR, DWORD);
|
||||
+
|
||||
/* a structure to deal with wine todos somewhat cleanly */
|
||||
typedef struct {
|
||||
DWORD shortlen;
|
||||
@@ -2179,6 +2182,7 @@ static void init_pointers(void)
|
||||
MAKEFUNC(ReleaseActCtx);
|
||||
MAKEFUNC(CheckNameLegalDOS8Dot3W);
|
||||
MAKEFUNC(CheckNameLegalDOS8Dot3A);
|
||||
+ MAKEFUNC(CreateSymbolicLinkW);
|
||||
#undef MAKEFUNC
|
||||
}
|
||||
|
||||
@@ -2435,6 +2439,95 @@ static void test_SetSearchPathMode(void)
|
||||
RemoveDirectoryA( dir );
|
||||
}
|
||||
|
||||
+static void test_CreateSymbolicLink(void)
|
||||
+{
|
||||
+ static const WCHAR target_fileW[] = {'t','a','r','g','e','t','_','f','i','l','e',0};
|
||||
+ static const WCHAR target_dirW[] = {'t','a','r','g','e','t','_','d','i','r',0};
|
||||
+ static const WCHAR linkW[] = {'l','i','n','k',0};
|
||||
+ static const WCHAR fooW[] = {'f','o','o',0};
|
||||
+ static WCHAR volW[] = {'c',':','\\',0};
|
||||
+ static const WCHAR dotW[] = {'.',0};
|
||||
+ WCHAR path[MAX_PATH], old_path[MAX_PATH], tmp[MAX_PATH];
|
||||
+ DWORD dwLen, dwFlags;
|
||||
+ TOKEN_PRIVILEGES tp;
|
||||
+ HANDLE token;
|
||||
+ LUID luid;
|
||||
+ BOOL bret;
|
||||
+ HANDLE h;
|
||||
+
|
||||
+ if (!pCreateSymbolicLinkW)
|
||||
+ {
|
||||
+ win_skip( "CreateSymbolicLink isn't available\n" );
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* Create a temporary folder for the symlink tests */
|
||||
+ GetTempFileNameW( dotW, fooW, 0, path );
|
||||
+ DeleteFileW( path );
|
||||
+ if (!CreateDirectoryW( path, NULL ))
|
||||
+ {
|
||||
+ win_skip("Unable to create a temporary junction point directory.\n");
|
||||
+ return;
|
||||
+ }
|
||||
+ GetCurrentDirectoryW( sizeof(old_path)/sizeof(WCHAR), old_path );
|
||||
+ SetCurrentDirectoryW( path );
|
||||
+
|
||||
+ /* Check that the volume this folder is located on supports reparse points */
|
||||
+ GetFullPathNameW( path, sizeof(tmp)/sizeof(WCHAR), tmp, NULL );
|
||||
+ volW[0] = tmp[0];
|
||||
+ GetVolumeInformationW( volW, 0, 0, 0, &dwLen, &dwFlags, 0, 0 );
|
||||
+ if (!(dwFlags & FILE_SUPPORTS_REPARSE_POINTS))
|
||||
+ {
|
||||
+ skip("File system does not support junction points.\n");
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ /* Establish permissions for symlink creation */
|
||||
+ bret = OpenProcessToken( GetCurrentProcess(), TOKEN_ALL_ACCESS, &token );
|
||||
+ ok(bret, "OpenProcessToken failed: %u\n", GetLastError());
|
||||
+ bret = LookupPrivilegeValueA( NULL, "SeCreateSymbolicLinkPrivilege", &luid );
|
||||
+ todo_wine ok(bret || broken(!bret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE) /* winxp */,
|
||||
+ "LookupPrivilegeValue failed: %u\n", GetLastError());
|
||||
+ if (bret)
|
||||
+ {
|
||||
+ tp.PrivilegeCount = 1;
|
||||
+ tp.Privileges[0].Luid = luid;
|
||||
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
+ bret = AdjustTokenPrivileges( token, FALSE, &tp, 0, NULL, NULL );
|
||||
+ ok(bret, "AdjustTokenPrivileges failed: %u\n", GetLastError());
|
||||
+ }
|
||||
+ if ((!bret && GetLastError() != ERROR_NO_SUCH_PRIVILEGE) || GetLastError() == ERROR_NOT_ALL_ASSIGNED)
|
||||
+ {
|
||||
+ win_skip("Insufficient permissions to perform symlink tests.\n");
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ /* Create a destination folder and file for symlinks to target */
|
||||
+ bret = CreateDirectoryW( target_dirW, NULL );
|
||||
+ ok(bret, "Failed to create symlink target directory.\n");
|
||||
+ h = CreateFileW( target_fileW, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||
+ ok(h != INVALID_HANDLE_VALUE, "Failed to create symlink target file.\n");
|
||||
+ CloseHandle( h );
|
||||
+
|
||||
+ /* Create a directory symbolic link */
|
||||
+ bret = CreateSymbolicLinkW( linkW, target_dirW, SYMBOLIC_LINK_FLAG_DIRECTORY );
|
||||
+ ok(bret, "Failed to create directory symbolic link! (0x%x)\n", GetLastError());
|
||||
+ bret = RemoveDirectoryW( linkW );
|
||||
+ ok(bret, "Failed to remove directory symbolic link! (0x%x)\n", GetLastError());
|
||||
+
|
||||
+ /* Create a file symbolic link */
|
||||
+ bret = CreateSymbolicLinkW( linkW, target_fileW, 0x0 );
|
||||
+ ok(bret, "Failed to create file symbolic link! (0x%x)\n", GetLastError());
|
||||
+ bret = DeleteFileW( linkW );
|
||||
+ ok(bret, "Failed to remove file symbolic link! (0x%x)\n", GetLastError());
|
||||
+
|
||||
+cleanup:
|
||||
+ DeleteFileW( target_fileW );
|
||||
+ RemoveDirectoryW( target_dirW );
|
||||
+ SetCurrentDirectoryW( old_path );
|
||||
+ RemoveDirectoryW( path );
|
||||
+}
|
||||
+
|
||||
START_TEST(path)
|
||||
{
|
||||
CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive;
|
||||
@@ -2469,4 +2562,5 @@ START_TEST(path)
|
||||
test_GetFullPathNameW();
|
||||
test_CheckNameLegalDOS8Dot3();
|
||||
test_SetSearchPathMode();
|
||||
+ test_CreateSymbolicLink();
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From e34db8f28e43091a02cccb2eb590f9beda9da059 Mon Sep 17 00:00:00 2001
|
||||
From 417a71fe5c16121c85bf59c13f610ebcdf701508 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Sat, 30 Mar 2019 12:01:50 -0600
|
||||
Subject: kernel32: Set error code when attempting to delete file symlinks as
|
||||
@@ -27,7 +27,7 @@ index 76a9512c77..f15b6dd68b 100644
|
||||
}
|
||||
else
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index f23bf8644c..a1323ab4f6 100644
|
||||
index bacfad266e..2f5ee0618c 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5071,9 +5071,9 @@ static void test_reparse_points(void)
|
@@ -1,4 +1,4 @@
|
||||
From 245f8c8ad1d014bbf726020fd4c37c99e8bcafea Mon Sep 17 00:00:00 2001
|
||||
From 160758d1973e49d5bb9d76d203fe1d0a8f676240 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: server: Properly handle file symlink deletion.
|
||||
@@ -6,11 +6,11 @@ Subject: server: Properly handle file symlink deletion.
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/tests/file.c | 6 ++--
|
||||
server/fd.c | 64 +++++++++++++++++++++++++++++++++++++----
|
||||
2 files changed, 62 insertions(+), 8 deletions(-)
|
||||
server/fd.c | 75 ++++++++++++++++++++++++++++++++++++++---
|
||||
2 files changed, 73 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index a1323ab4f6..8ab8a5da53 100644
|
||||
index 2f5ee0618c..5f42ad5e0b 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5080,14 +5080,14 @@ static void test_reparse_points(void)
|
||||
@@ -32,10 +32,21 @@ index a1323ab4f6..8ab8a5da53 100644
|
||||
/* Create the directory symlink */
|
||||
HeapFree(GetProcessHeap(), 0, buffer);
|
||||
diff --git a/server/fd.c b/server/fd.c
|
||||
index 5d80e218b9..71347e4318 100644
|
||||
index 5d80e218b9..e74fef6a19 100644
|
||||
--- a/server/fd.c
|
||||
+++ b/server/fd.c
|
||||
@@ -1069,7 +1069,7 @@ static void inode_destroy( struct object *obj )
|
||||
@@ -105,6 +105,10 @@
|
||||
#include "winternl.h"
|
||||
#include "winioctl.h"
|
||||
|
||||
+#if !defined(O_SYMLINK) && defined(O_PATH)
|
||||
+# define O_SYMLINK (O_NOFOLLOW | O_PATH)
|
||||
+#endif
|
||||
+
|
||||
#if defined(HAVE_SYS_EPOLL_H) && defined(HAVE_EPOLL_CREATE)
|
||||
# include <sys/epoll.h>
|
||||
# define USE_EPOLL
|
||||
@@ -1069,7 +1073,7 @@ static void inode_destroy( struct object *obj )
|
||||
{
|
||||
/* make sure it is still the same file */
|
||||
struct stat st;
|
||||
@@ -44,7 +55,7 @@ index 5d80e218b9..71347e4318 100644
|
||||
{
|
||||
if (S_ISDIR(st.st_mode)) rmdir( fd->unix_name );
|
||||
else unlink( fd->unix_name );
|
||||
@@ -1747,6 +1747,53 @@ char *dup_fd_name( struct fd *root, const char *name )
|
||||
@@ -1747,6 +1751,53 @@ char *dup_fd_name( struct fd *root, const char *name )
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -98,7 +109,21 @@ index 5d80e218b9..71347e4318 100644
|
||||
/* open() wrapper that returns a struct fd with no fd user set */
|
||||
struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode, unsigned int access,
|
||||
unsigned int sharing, unsigned int options )
|
||||
@@ -1826,14 +1873,15 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
@@ -1815,6 +1866,13 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
if ((access & FILE_UNIX_WRITE_ACCESS) || (flags & O_CREAT))
|
||||
fd->unix_fd = open( name, O_RDONLY | (flags & ~(O_TRUNC | O_CREAT | O_EXCL)), *mode );
|
||||
}
|
||||
+#if defined(O_SYMLINK)
|
||||
+ /* if we tried to open a dangling symlink then try again with O_SYMLINK */
|
||||
+ else if (errno == ENOENT)
|
||||
+ {
|
||||
+ fd->unix_fd = open( name, rw_mode | O_SYMLINK | (flags & ~O_TRUNC), *mode );
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
if (fd->unix_fd == -1)
|
||||
{
|
||||
@@ -1826,14 +1884,15 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
closed_fd->unix_fd = fd->unix_fd;
|
||||
closed_fd->unlink = 0;
|
||||
closed_fd->unix_name = fd->unix_name;
|
||||
@@ -116,7 +141,7 @@ index 5d80e218b9..71347e4318 100644
|
||||
|
||||
if (!inode)
|
||||
{
|
||||
@@ -1848,13 +1896,19 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
@@ -1848,13 +1907,19 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
list_add_head( &inode->open, &fd->inode_entry );
|
||||
closed_fd = NULL;
|
||||
|
@@ -0,0 +1,93 @@
|
||||
From 5eb8e81e70075947729f70e59825d472db8faf2a Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Wed, 1 May 2019 12:06:20 -0600
|
||||
Subject: ntdll: Always report symbolic links as containing zero bytes.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/file.c | 2 ++
|
||||
dlls/ntdll/tests/file.c | 27 +++++++++++++++++++++++++--
|
||||
2 files changed, 27 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
|
||||
index 934577bfba..cf98b1cfdd 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -153,6 +153,8 @@ int get_file_info( const char *path, struct stat *st, ULONG *attr )
|
||||
{
|
||||
BOOL is_dir;
|
||||
|
||||
+ /* symbolic links always report size 0 */
|
||||
+ st->st_size = 0;
|
||||
/* 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 */
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index 5f42ad5e0b..36c021acd7 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -4897,6 +4897,7 @@ static void test_reparse_points(void)
|
||||
REPARSE_DATA_BUFFER *buffer = NULL;
|
||||
DWORD dwret, dwLen, dwFlags, err;
|
||||
INT buffer_len, string_len;
|
||||
+ WCHAR buf[] = {0,0,0,0};
|
||||
HANDLE handle, token;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
UNICODE_STRING nameW;
|
||||
@@ -5024,8 +5025,6 @@ static void test_reparse_points(void)
|
||||
"Unexpected junction point attributes (0x%x != 0x410)!\n", dwret);
|
||||
bret = RemoveDirectoryW(target_path);
|
||||
ok(bret, "Failed to delete junction point target!\n");
|
||||
- bret = CreateDirectoryW(target_path, NULL);
|
||||
- ok(bret, "Failed to create junction point target directory.\n");
|
||||
|
||||
/* Establish permissions for symlink creation */
|
||||
bret = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token);
|
||||
@@ -5050,6 +5049,13 @@ 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");
|
||||
+ handle = CreateFileW(target_path, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_NEW, 0, 0);
|
||||
+ ok(handle != INVALID_HANDLE_VALUE, "Failed to create symlink target file.\n");
|
||||
+ bret = WriteFile(handle, fooW, sizeof(fooW), NULL, NULL);
|
||||
+ ok(bret, "Failed to write data to the symlink target file.\n");
|
||||
+ ok(GetFileSize(handle, NULL) == sizeof(fooW), "target size is incorrect (%d vs %d)\n",
|
||||
+ GetFileSize(handle, NULL), sizeof(fooW));
|
||||
+ CloseHandle(handle);
|
||||
|
||||
/* Create the file symlink */
|
||||
HeapFree(GetProcessHeap(), 0, buffer);
|
||||
@@ -5067,6 +5073,19 @@ static void test_reparse_points(void)
|
||||
ok(bret, "Failed to create symlink! (0x%x)\n", GetLastError());
|
||||
CloseHandle(handle);
|
||||
|
||||
+ /* Check the size of the symlink */
|
||||
+ handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
|
||||
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
|
||||
+ ok(handle != INVALID_HANDLE_VALUE, "Failed to open symlink file.\n");
|
||||
+ ok(GetFileSize(handle, NULL) == 0, "symlink size is not zero\n");
|
||||
+ bret = ReadFile(handle, &buf, sizeof(buf), &dwLen, NULL);
|
||||
+ ok(bret, "Failed to read data from the symlink.\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);
|
||||
ok(!bret, "Succeeded in deleting file symlink as a directory!\n");
|
||||
@@ -5088,6 +5107,10 @@ static void test_reparse_points(void)
|
||||
dwret = GetFileAttributesW(reparse_path);
|
||||
ok(dwret != (DWORD)~0, "Path doesn't exist (attributes: 0x%x)!\n", dwret);
|
||||
ok(!(dwret & FILE_ATTRIBUTE_REPARSE_POINT), "File is already a reparse point! (attributes: %d)\n", dwret);
|
||||
+ bret = DeleteFileW(target_path);
|
||||
+ ok(bret, "Failed to delete symlink target!\n");
|
||||
+ bret = CreateDirectoryW(target_path, NULL);
|
||||
+ ok(bret, "Failed to create symlink target directory.\n");
|
||||
|
||||
/* Create the directory symlink */
|
||||
HeapFree(GetProcessHeap(), 0, buffer);
|
||||
--
|
||||
2.17.1
|
||||
|
@@ -0,0 +1,47 @@
|
||||
From e573ccae4f2584e7f7c040f1c1f986d1e7ebdc6e Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Wed, 1 May 2019 17:48:51 -0600
|
||||
Subject: ntdll: Find dangling symlinks quickly.
|
||||
|
||||
This is also necessary on systems (such as MacOS) that support
|
||||
case-insensitive lookups of files.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/directory.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
|
||||
index cca1e3c4a8..8f16f5e310 100644
|
||||
--- a/dlls/ntdll/directory.c
|
||||
+++ b/dlls/ntdll/directory.c
|
||||
@@ -2052,7 +2052,7 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i
|
||||
if (ret >= 0 && !used_default)
|
||||
{
|
||||
unix_name[pos + ret] = 0;
|
||||
- if (!stat( unix_name, &st ))
|
||||
+ if (!lstat( unix_name, &st ))
|
||||
{
|
||||
if (is_win_dir) *is_win_dir = is_same_file( &windir, &st );
|
||||
return STATUS_SUCCESS;
|
||||
@@ -2174,7 +2174,7 @@ not_found:
|
||||
return STATUS_OBJECT_PATH_NOT_FOUND;
|
||||
|
||||
success:
|
||||
- if (is_win_dir && !stat( unix_name, &st )) *is_win_dir = is_same_file( &windir, &st );
|
||||
+ if (is_win_dir && !lstat( unix_name, &st )) *is_win_dir = is_same_file( &windir, &st );
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -2640,7 +2640,7 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
|
||||
for (p = unix_name + pos ; *p; p++) if (*p == '\\') *p = '/';
|
||||
if (!name_len || !redirect || (!strstr( unix_name, "/windows/") && strncmp( unix_name, "windows/", 8 )))
|
||||
{
|
||||
- if (!stat( unix_name, &st ))
|
||||
+ if (!lstat( unix_name, &st ))
|
||||
{
|
||||
if (disposition == FILE_CREATE)
|
||||
return STATUS_OBJECT_NAME_COLLISION;
|
||||
--
|
||||
2.17.1
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user