Updated ntdll-Junction_Points patchset

This commit is contained in:
Alistair Leslie-Hughes 2019-05-10 08:57:46 +10:00
parent 992845eae7
commit 082a898ad4
25 changed files with 1007 additions and 389 deletions

View File

@ -1,4 +1,4 @@
From 935694ac40ed4b264ef0ede519bd8b9b2f1f28de Mon Sep 17 00:00:00 2001
From 78f4401a1e5d50097be8dd8458273ef1d4a548a7 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Tue, 19 Aug 2014 22:10:49 -0600
Subject: [PATCH] ntdll: Implement retrieving DOS attributes in
@ -6,15 +6,15 @@ Subject: [PATCH] ntdll: Implement retrieving DOS attributes in
---
configure.ac | 12 ++++++++++++
dlls/ntdll/file.c | 22 +++++++++++++++++++++-
dlls/ntdll/file.c | 16 ++++++++++++++++
include/wine/port.h | 8 ++++++++
libs/port/Makefile.in | 4 +++-
libs/port/xattr.c | 39 +++++++++++++++++++++++++++++++++++++++
5 files changed, 83 insertions(+), 2 deletions(-)
5 files changed, 78 insertions(+), 1 deletion(-)
create mode 100644 libs/port/xattr.c
diff --git a/configure.ac b/configure.ac
index 1905733..6f0429e 100644
index 9385d20..60d43d3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -85,6 +85,7 @@ AC_ARG_WITH(udev, AS_HELP_STRING([--without-udev],[do not use udev (plug an
@ -25,7 +25,7 @@ index 1905733..6f0429e 100644
AC_ARG_WITH(xcomposite,AS_HELP_STRING([--without-xcomposite],[do not use the Xcomposite extension]),
[if test "x$withval" = "xno"; then ac_cv_header_X11_extensions_Xcomposite_h=no; fi])
AC_ARG_WITH(xcursor, AS_HELP_STRING([--without-xcursor],[do not use the Xcursor extension]),
@@ -698,6 +699,17 @@ AC_CHECK_HEADERS([libprocstat.h],,,
@@ -711,6 +712,17 @@ AC_CHECK_HEADERS([libprocstat.h],,,
#include <sys/socket.h>
#endif])
@ -44,7 +44,7 @@ index 1905733..6f0429e 100644
AC_SUBST(DLLFLAGS,"-D_REENTRANT")
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 919eaea..1ffa675 100644
index b70477e..2c99c1d 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -127,6 +127,22 @@ static const WCHAR ntfsW[] = {'N','T','F','S'};
@ -70,24 +70,6 @@ index 919eaea..1ffa675 100644
/* fetch the attributes of a file */
static inline ULONG get_file_attributes( const struct stat *st )
{
@@ -144,12 +160,16 @@ static inline ULONG get_file_attributes( const struct stat *st )
/* 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;
+ char hexattr[11];
+ int len, ret;
*attr = 0;
ret = fstat( fd, st );
if (ret == -1) return ret;
*attr |= get_file_attributes( st );
+ len = xattr_fget( fd, SAMBA_XATTR_DOS_ATTRIB, hexattr, sizeof(hexattr)-1 );
+ if (len == -1) return ret;
+ *attr |= get_file_xattr( hexattr, len );
return ret;
}
diff --git a/include/wine/port.h b/include/wine/port.h
index 19c8682..eaa23bc 100644
--- a/include/wine/port.h

View File

@ -1,7 +1,8 @@
From c65dec8465c321f09ee3bfd0317994da8cd0c0c1 Mon Sep 17 00:00:00 2001
From 347997c4118fa01fbf87cf7cadb6ba04a83a97c4 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Wed, 20 Aug 2014 00:08:52 -0600
Subject: ntdll: Implement storing DOS attributes in NtSetInformationFile.
Subject: [PATCH] ntdll: Implement storing DOS attributes in
NtSetInformationFile.
---
dlls/ntdll/file.c | 54 +++++++++++++++++++++++++++++++------------------
@ -11,11 +12,11 @@ Subject: ntdll: Implement storing DOS attributes in NtSetInformationFile.
4 files changed, 60 insertions(+), 24 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index b977e45..521ab64 100644
index 6743d37..12d47ae 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -149,6 +149,39 @@ int fd_get_file_info( int fd, struct stat *st, ULONG *attr )
return ret;
@@ -157,6 +157,39 @@ static inline ULONG get_file_attributes( const struct stat *st )
return attr;
}
+/* set the stat info and file attributes for a file (by file descriptor) */
@ -54,7 +55,7 @@ index b977e45..521ab64 100644
/* get the stat info and file attributes for a file (by name) */
int get_file_info( const char *path, struct stat *st, ULONG *attr )
{
@@ -2320,7 +2353,6 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
@@ -3097,7 +3130,6 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
case FileBasicInformation:
if (len >= sizeof(FILE_BASIC_INFORMATION))
{
@ -62,7 +63,7 @@ index b977e45..521ab64 100644
const FILE_BASIC_INFORMATION *info = ptr;
if ((io->u.Status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
@@ -2330,25 +2362,7 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
@@ -3107,25 +3139,7 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
io->u.Status = set_file_times( fd, &info->LastWriteTime, &info->LastAccessTime );
if (io->u.Status == STATUS_SUCCESS && info->FileAttributes)
@ -90,10 +91,10 @@ index b977e45..521ab64 100644
if (needs_close) close( fd );
}
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index d70ed6b..7a8e5d4 100644
index d0646aa..39f9013 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -1234,7 +1234,7 @@ static void test_file_basic_information(void)
@@ -1341,7 +1341,7 @@ static void test_file_basic_information(void)
memset(&fbi, 0, sizeof(fbi));
res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
ok ( res == STATUS_SUCCESS, "can't get attributes\n");
@ -102,7 +103,7 @@ index d70ed6b..7a8e5d4 100644
/* Then HIDDEN */
memset(&fbi, 0, sizeof(fbi));
@@ -1247,7 +1247,7 @@ static void test_file_basic_information(void)
@@ -1354,7 +1354,7 @@ static void test_file_basic_information(void)
memset(&fbi, 0, sizeof(fbi));
res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
ok ( res == STATUS_SUCCESS, "can't get attributes\n");
@ -111,7 +112,7 @@ index d70ed6b..7a8e5d4 100644
/* Check NORMAL last of all (to make sure we can clear attributes) */
memset(&fbi, 0, sizeof(fbi));
@@ -1304,7 +1304,7 @@ static void test_file_all_information(void)
@@ -1411,7 +1411,7 @@ static void test_file_all_information(void)
memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
@ -120,7 +121,7 @@ index d70ed6b..7a8e5d4 100644
/* Then HIDDEN */
memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
@@ -1317,7 +1317,7 @@ static void test_file_all_information(void)
@@ -1424,7 +1424,7 @@ static void test_file_all_information(void)
memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
ok ( res == STATUS_SUCCESS, "can't get attributes\n");
@ -130,10 +131,10 @@ index d70ed6b..7a8e5d4 100644
/* Check NORMAL last of all (to make sure we can clear attributes) */
memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
diff --git a/include/wine/port.h b/include/wine/port.h
index 7977eb9..cc572f3 100644
index de6b995..c075958 100644
--- a/include/wine/port.h
+++ b/include/wine/port.h
@@ -370,6 +370,8 @@ extern int _spawnvp(int mode, const char *cmdname, const char * const argv[]);
@@ -351,6 +351,8 @@ extern int mkstemps(char *template, int suffix_len);
#endif
extern int xattr_fget( int filedes, const char *name, void *value, size_t size );

View File

@ -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 \

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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 @@

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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);

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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;

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