You've already forked wine-staging
mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-12-15 08:03:15 -08:00
Rebase against 9250ecc5a6a64c73aada0ea751815412f7f00410.
This commit is contained in:
@@ -1,413 +0,0 @@
|
||||
From 5f3feef99f8c9740f04dbe0ee1b23ca27d60548e 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 creating reparse points.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
configure.ac | 2 +
|
||||
dlls/ntdll/Makefile.in | 2 +-
|
||||
dlls/ntdll/unix/file.c | 302 +++++++++++++++++++++++++++++++++++++++++
|
||||
include/ddk/ntifs.h | 5 +
|
||||
4 files changed, 310 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index b675da34d58..63e3bb5bdc7 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -2137,6 +2137,8 @@ AC_CHECK_FUNCS(\
|
||||
process_vm_writev \
|
||||
sched_getcpu \
|
||||
sched_yield \
|
||||
+ renameat \
|
||||
+ renameat2 \
|
||||
setproctitle \
|
||||
setprogname \
|
||||
sigprocmask \
|
||||
diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
|
||||
index 3c0dfa7a895..b9a8bcba4cf 100644
|
||||
--- a/dlls/ntdll/Makefile.in
|
||||
+++ b/dlls/ntdll/Makefile.in
|
||||
@@ -5,7 +5,7 @@ IMPORTLIB = ntdll
|
||||
IMPORTS = $(TOMCRYPT_PE_LIBS) $(MUSL_PE_LIBS)
|
||||
EXTRAINCL = $(TOMCRYPT_PE_CFLAGS)
|
||||
UNIX_CFLAGS = $(UNWIND_CFLAGS) $(HWLOC_CFLAGS)
|
||||
-UNIX_LIBS = $(IOKIT_LIBS) $(COREFOUNDATION_LIBS) $(CORESERVICES_LIBS) $(RT_LIBS) $(PTHREAD_LIBS) $(UNWIND_LIBS) $(I386_LIBS) $(PROCSTAT_LIBS) $(HWLOC_LIBS)
|
||||
+UNIX_LIBS = $(IOKIT_LIBS) $(COREFOUNDATION_LIBS) $(CORESERVICES_LIBS) $(RT_LIBS) $(PTHREAD_LIBS) $(UNWIND_LIBS) $(I386_LIBS) $(PROCSTAT_LIBS) $(HWLOC_LIBS) -lm
|
||||
|
||||
EXTRADLLFLAGS = -nodefaultlibs
|
||||
i386_EXTRADLLFLAGS = -Wl,--image-base,0x7bc00000
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index 7ab1dbb2b55..5b4fcb3711d 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -36,6 +36,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
+#include <math.h>
|
||||
+#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_MNTENT_H
|
||||
@@ -121,6 +123,7 @@
|
||||
#include "wine/list.h"
|
||||
#include "wine/debug.h"
|
||||
#include "unix_private.h"
|
||||
+#include "ddk/ntifs.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(file);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(winediag);
|
||||
@@ -132,6 +135,12 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
|
||||
#undef EXT2_IOC_GETFLAGS
|
||||
#undef EXT4_CASEFOLD_FL
|
||||
|
||||
+#ifndef RENAME_EXCHANGE
|
||||
+#define RENAME_EXCHANGE (1 << 1)
|
||||
+#endif
|
||||
+
|
||||
+#define SYM_MAX (PATH_MAX-1) /* PATH_MAX includes the NUL character */
|
||||
+
|
||||
#ifdef linux
|
||||
|
||||
/* We want the real kernel dirent structure, not the libc one */
|
||||
@@ -249,6 +258,95 @@ static const BOOL is_case_sensitive = FALSE;
|
||||
static pthread_mutex_t dir_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t mnt_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
+#ifndef HAVE_RENAMEAT2
|
||||
+int renameat2( int olddirfd, const char *oldpath, int newdirfd, const char *newpath,
|
||||
+ unsigned int flags )
|
||||
+{
|
||||
+ if (flags == 0)
|
||||
+ return renameat( olddirfd, oldpath, newdirfd, newpath );
|
||||
+#if defined(__NR_renameat2)
|
||||
+ return syscall( __NR_renameat2, olddirfd, oldpath, newdirfd, newpath, flags );
|
||||
+#elif defined(RENAME_SWAP)
|
||||
+ return renameatx_np(olddirfd, oldpath, newdirfd, newpath,
|
||||
+ (flags & RENAME_EXCHANGE ? RENAME_SWAP : 0));
|
||||
+#else
|
||||
+ errno = ENOSYS;
|
||||
+ return -1;
|
||||
+#endif
|
||||
+}
|
||||
+#endif /* HAVE_RENAMEAT2 */
|
||||
+
|
||||
+static char *itoa( int i )
|
||||
+{
|
||||
+ static char buffer[11];
|
||||
+
|
||||
+ snprintf(buffer, sizeof(buffer), "%d", i);
|
||||
+ return buffer;
|
||||
+}
|
||||
+
|
||||
+/* base64url (RFC 4648 §5) encode a binary string
|
||||
+ * 1) start with base64
|
||||
+ * 2) replace '+' by '-' and replace '/' by '_'
|
||||
+ * 3) do not add padding characters
|
||||
+ * 4) do not add line separators
|
||||
+ */
|
||||
+static UINT encode_base64url( const char *bin, unsigned int len, char *base64 )
|
||||
+{
|
||||
+ UINT n = 0, x;
|
||||
+ static const char base64enc[] =
|
||||
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||
+
|
||||
+ while (len > 0)
|
||||
+ {
|
||||
+ /* first 6 bits, all from bin[0] */
|
||||
+ base64[n++] = base64enc[(bin[0] & 0xfc) >> 2];
|
||||
+ x = (bin[0] & 3) << 4;
|
||||
+
|
||||
+ /* next 6 bits, 2 from bin[0] and 4 from bin[1] */
|
||||
+ if (len == 1)
|
||||
+ {
|
||||
+ base64[n++] = base64enc[x];
|
||||
+ break;
|
||||
+ }
|
||||
+ base64[n++] = base64enc[x | ((bin[1] & 0xf0) >> 4)];
|
||||
+ x = (bin[1] & 0x0f) << 2;
|
||||
+
|
||||
+ /* next 6 bits 4 from bin[1] and 2 from bin[2] */
|
||||
+ if (len == 2)
|
||||
+ {
|
||||
+ base64[n++] = base64enc[x];
|
||||
+ break;
|
||||
+ }
|
||||
+ base64[n++] = base64enc[x | ((bin[2] & 0xc0) >> 6)];
|
||||
+
|
||||
+ /* last 6 bits, all from bin [2] */
|
||||
+ base64[n++] = base64enc[bin[2] & 0x3f];
|
||||
+ bin += 3;
|
||||
+ len -= 3;
|
||||
+ }
|
||||
+ base64[n] = 0;
|
||||
+ return n;
|
||||
+}
|
||||
+
|
||||
+/* create a directory and all the needed parent directories */
|
||||
+static int mkdir_p( int dirfd, const char *path, mode_t mode )
|
||||
+{
|
||||
+ char path_tmp[PATH_MAX], *p;
|
||||
+
|
||||
+ strcpy( path_tmp, path );
|
||||
+ for (p = path_tmp + 1; *p; p++) {
|
||||
+ if (*p == '/') {
|
||||
+ *p = '\0';
|
||||
+ if (mkdirat( dirfd, path_tmp, mode ) != 0 && errno != EEXIST)
|
||||
+ return -1;
|
||||
+ *p = '/';
|
||||
+ }
|
||||
+ }
|
||||
+ if (mkdirat( dirfd, path_tmp, mode ) != 0 && errno != EEXIST)
|
||||
+ return -1;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/* check if a given Unicode char is OK in a DOS short name */
|
||||
static inline BOOL is_invalid_dos_char( WCHAR ch )
|
||||
{
|
||||
@@ -1653,6 +1751,28 @@ static int parse_samba_dos_attrib_data( char *data, int len )
|
||||
}
|
||||
|
||||
|
||||
+/* determine whether a reparse point is meant to be a directory or a file */
|
||||
+static int is_reparse_dir( int fd, const char *path, BOOL *is_dir )
|
||||
+{
|
||||
+ char link_path[PATH_MAX], *p;
|
||||
+ int ret;
|
||||
+
|
||||
+ if ((ret = readlinkat( fd, path, link_path, sizeof(link_path) )) < 0)
|
||||
+ return ret;
|
||||
+ /* confirm that this file is a reparse point */
|
||||
+ if (strncmp( link_path, ".REPARSE_POINT/", 15) != 0)
|
||||
+ return -1;
|
||||
+ /* skip past the reparse point indicator and the filename */
|
||||
+ p = &link_path[15];
|
||||
+ if ((p = strchr( p, '/' )) == NULL)
|
||||
+ return -1;
|
||||
+ p++;
|
||||
+ /* read the flag indicating whether this reparse point is a directory */
|
||||
+ if (is_dir) *is_dir = (*p == '.');
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
static BOOL fd_is_mount_point( int fd, const struct stat *st )
|
||||
{
|
||||
struct stat parent;
|
||||
@@ -3455,6 +3575,181 @@ done:
|
||||
}
|
||||
|
||||
|
||||
+/*
|
||||
+ * 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 create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
+{
|
||||
+ int buffer_len = buffer->ReparseDataLength+FIELD_OFFSET(typeof(*buffer), GenericReparseBuffer);
|
||||
+ char target_path[PATH_MAX], link_path[PATH_MAX], link_dir[PATH_MAX];
|
||||
+ int encoded_len = (int)ceil(buffer_len*4/3.0) + 1, chunk_len;
|
||||
+ char tmpdir[PATH_MAX], tmplink[PATH_MAX], *d;
|
||||
+ BOOL needs_close, tempdir_created = FALSE;
|
||||
+ char filename_buf[PATH_MAX], *filename;
|
||||
+ char *unix_src = NULL, *encoded = NULL;
|
||||
+ int i = 0, j = 0, depth = 0, fd;
|
||||
+ int link_dir_fd = -1;
|
||||
+ NTSTATUS status;
|
||||
+ struct stat st;
|
||||
+ BOOL is_dir;
|
||||
+
|
||||
+ if (buffer_len > 16*1024)
|
||||
+ return STATUS_IO_REPARSE_DATA_INVALID;
|
||||
+
|
||||
+ if ((status = server_get_unix_fd( handle, FILE_SPECIAL_ACCESS, &fd, &needs_close, NULL, NULL )))
|
||||
+ return status;
|
||||
+ if (fstat( fd, &st ) == -1)
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ if ((status = server_get_unix_name( handle, &unix_src )))
|
||||
+ goto cleanup;
|
||||
+ is_dir = S_ISDIR( st.st_mode );
|
||||
+ is_reparse_dir( AT_FDCWD, unix_src, &is_dir ); /* keep type (replace existing reparse point) */
|
||||
+ encoded = malloc( encoded_len );
|
||||
+ if (!encoded)
|
||||
+ {
|
||||
+ status = STATUS_NO_MEMORY;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ encoded_len = encode_base64url( (const char *)buffer, buffer_len, encoded );
|
||||
+
|
||||
+ TRACE( "Linking %s to %s\n", debugstr_a(unix_src), encoded );
|
||||
+ strcpy( filename_buf, unix_src );
|
||||
+ filename = basename( filename_buf );
|
||||
+
|
||||
+ /* Create the symlink that represents the initial data in the reparse tag:
|
||||
+ * *) Begin all reparse tags with the hidden folder .REPARSE_POINT. This serves two purposes:
|
||||
+ * 1) it makes it easy to identify reparse points
|
||||
+ * 2) if the reparse buffer exceeds what can be stored in a single symlink (4095+1 bytes)
|
||||
+ * then we need to store additional data, so link to it and store it in a hidden folder
|
||||
+ * *) Append the filename of the reparse point to the hidden folder, this ensures that if
|
||||
+ * multiple reparse points contain the same data that there is no possibility of collision
|
||||
+ * *) Append a special flag to indicate whether this is a directory (./) or file (/)
|
||||
+ * *) Append the base64-url encoded reparse point buffer
|
||||
+ * *) Append the filename of the first continuing symlink (0) in case we need it
|
||||
+ */
|
||||
+ strcpy( target_path, ".REPARSE_POINT/" );
|
||||
+ strcat( target_path, filename );
|
||||
+ strcat( target_path, "/" );
|
||||
+ if (is_dir)
|
||||
+ strcat( target_path, "." );
|
||||
+ strcat( target_path, "/" );
|
||||
+ i = 0;
|
||||
+ for (depth=0; i<encoded_len && strlen(target_path)<SYM_MAX-2; i+=chunk_len, depth++)
|
||||
+ {
|
||||
+ chunk_len = min(NAME_MAX, SYM_MAX-2-strlen(target_path));
|
||||
+ strncat( target_path, &encoded[i], chunk_len );
|
||||
+ strcat( target_path, "/" );
|
||||
+ }
|
||||
+ strcat( target_path, itoa(j) );
|
||||
+
|
||||
+ /* Produce the link in a temporary location in the same folder */
|
||||
+ strcpy( tmpdir, unix_src );
|
||||
+ d = dirname( tmpdir);
|
||||
+ if (d != tmpdir) strcpy( tmpdir, d );
|
||||
+ strcat( tmpdir, "/.winelink.XXXXXX" );
|
||||
+ if (mkdtemp( tmpdir ) == NULL)
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ tempdir_created = TRUE;
|
||||
+ strcpy( tmplink, tmpdir );
|
||||
+ strcat( tmplink, "/tmplink" );
|
||||
+ if (symlink( target_path, tmplink ))
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ /* change to the link folder so that we can build any necessary additional data */
|
||||
+ strcpy( link_dir, tmpdir );
|
||||
+ link_dir[strlen(link_dir)-16] = 0;
|
||||
+ link_dir_fd = open( link_dir, O_RDONLY|O_DIRECTORY );
|
||||
+
|
||||
+ /* If there is any further information in the reparse tag then store it in the hidden folder */
|
||||
+ while(i < encoded_len)
|
||||
+ {
|
||||
+ int fd;
|
||||
+
|
||||
+ j++;
|
||||
+ strcpy( link_path, target_path );
|
||||
+
|
||||
+ target_path[0] = 0;
|
||||
+ for (; depth>0; depth--)
|
||||
+ {
|
||||
+ strcat( target_path, "../" );
|
||||
+ }
|
||||
+ for (depth=0; i<encoded_len && strlen(target_path)<SYM_MAX-2; i+=chunk_len, depth++)
|
||||
+ {
|
||||
+ chunk_len = min(NAME_MAX, SYM_MAX-2-strlen(target_path));
|
||||
+ strncat( target_path, &encoded[i], chunk_len );
|
||||
+ strcat( target_path, "/" );
|
||||
+ }
|
||||
+ strcat( target_path, itoa(j) );
|
||||
+
|
||||
+ strcpy( link_dir, link_path );
|
||||
+ link_dir[strlen(link_dir)-1] = 0;
|
||||
+ if (mkdir_p( link_dir_fd, link_dir, 0777))
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ if (symlinkat( target_path, link_dir_fd, link_path ))
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ fd = openat( link_dir_fd, link_dir, O_RDONLY|O_DIRECTORY );
|
||||
+ close( link_dir_fd );
|
||||
+ link_dir_fd = fd;
|
||||
+ }
|
||||
+
|
||||
+ /* Atomically move the initial link into position */
|
||||
+ if (!renameat2( -1, tmplink, -1, unix_src, RENAME_EXCHANGE ))
|
||||
+ {
|
||||
+ /* success: link and folder/file have switched locations */
|
||||
+ if (S_ISDIR( st.st_mode ))
|
||||
+ rmdir( tmplink ); /* remove the folder (at link location) */
|
||||
+ else
|
||||
+ unlink( tmplink ); /* remove the file (at link location) */
|
||||
+ }
|
||||
+ else if (errno == ENOSYS)
|
||||
+ {
|
||||
+ FIXME( "Atomic exchange of directory with symbolic link unsupported on this system, "
|
||||
+ "using unsafe exchange instead.\n" );
|
||||
+ if (rmdir( unix_src ))
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ if (rename( tmplink, unix_src ))
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup; /* not moved, orignal file/folder at destination is orphaned */
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ status = STATUS_SUCCESS;
|
||||
+
|
||||
+cleanup:
|
||||
+ if (link_dir_fd != -1) close( link_dir_fd );
|
||||
+ if (tempdir_created) rmdir( tmpdir );
|
||||
+ if (needs_close) close( fd );
|
||||
+ free( unix_src );
|
||||
+ free( encoded );
|
||||
+
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/******************************************************************************
|
||||
* lookup_unix_name
|
||||
*
|
||||
@@ -6400,6 +6695,13 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
|
||||
break;
|
||||
}
|
||||
|
||||
+ case FSCTL_SET_REPARSE_POINT:
|
||||
+ {
|
||||
+ REPARSE_DATA_BUFFER *buffer = (REPARSE_DATA_BUFFER *)in_buffer;
|
||||
+ status = create_reparse_point( handle, buffer );
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
case FSCTL_SET_SPARSE:
|
||||
TRACE("FSCTL_SET_SPARSE: Ignoring request\n");
|
||||
status = STATUS_SUCCESS;
|
||||
diff --git a/include/ddk/ntifs.h b/include/ddk/ntifs.h
|
||||
index 980235abdc9..90248b4897c 100644
|
||||
--- a/include/ddk/ntifs.h
|
||||
+++ b/include/ddk/ntifs.h
|
||||
@@ -166,6 +166,11 @@ typedef struct _REPARSE_DATA_BUFFER
|
||||
WCHAR PathBuffer[1];
|
||||
} MountPointReparseBuffer;
|
||||
|
||||
+ struct {
|
||||
+ ULONG Version;
|
||||
+ UCHAR PathBuffer[1];
|
||||
+ } LinuxSymbolicLinkReparseBuffer;
|
||||
+
|
||||
struct
|
||||
{
|
||||
UCHAR DataBuffer[1];
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@@ -1,266 +0,0 @@
|
||||
From 369f4d92683910c01d82719e448d21a74b7b82d8 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 reparse points.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/unix/file.c | 221 ++++++++++++++++++++++++++++++++++++++--
|
||||
2 files changed, 231 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index 0d58abbfa84..3e160fb1e5c 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -325,6 +325,84 @@ static UINT encode_base64url( const char *bin, unsigned int len, char *base64 )
|
||||
return n;
|
||||
}
|
||||
|
||||
+static inline char decode_base64url_char( char c )
|
||||
+{
|
||||
+ if (c >= 'A' && c <= 'Z') return c - 'A';
|
||||
+ if (c >= 'a' && c <= 'z') return c - 'a' + 26;
|
||||
+ if (c >= '0' && c <= '9') return c - '0' + 52;
|
||||
+ if (c == '-') return 62;
|
||||
+ if (c == '_') return 63;
|
||||
+ return 64;
|
||||
+}
|
||||
+
|
||||
+/* decode a base64url (RFC 4648 §5) binary string
|
||||
+ * 1) start with base64
|
||||
+ * 2) replace '+' by '-' and replace '/' by '_'
|
||||
+ * 3) do not add padding characters
|
||||
+ * 4) do not add line separators
|
||||
+ */
|
||||
+static unsigned int decode_base64url( const char *base64, unsigned int len, char *buf )
|
||||
+{
|
||||
+ unsigned int i = 0;
|
||||
+ char c0, c1, c2, c3;
|
||||
+ const char *p = base64;
|
||||
+
|
||||
+ while (len > 4)
|
||||
+ {
|
||||
+ if ((c0 = decode_base64url_char( p[0] )) > 63) return 0;
|
||||
+ if ((c1 = decode_base64url_char( p[1] )) > 63) return 0;
|
||||
+ if ((c2 = decode_base64url_char( p[2] )) > 63) return 0;
|
||||
+ if ((c3 = decode_base64url_char( p[3] )) > 63) return 0;
|
||||
+
|
||||
+ if (buf)
|
||||
+ {
|
||||
+ buf[i + 0] = (c0 << 2) | (c1 >> 4);
|
||||
+ buf[i + 1] = (c1 << 4) | (c2 >> 2);
|
||||
+ buf[i + 2] = (c2 << 6) | c3;
|
||||
+ }
|
||||
+ len -= 4;
|
||||
+ i += 3;
|
||||
+ p += 4;
|
||||
+ }
|
||||
+ if (len == 2)
|
||||
+ {
|
||||
+ if ((c0 = decode_base64url_char( p[0] )) > 63) return 0;
|
||||
+ if ((c1 = decode_base64url_char( p[1] )) > 63) return 0;
|
||||
+
|
||||
+ if (buf) buf[i] = (c0 << 2) | (c1 >> 4);
|
||||
+ i++;
|
||||
+ }
|
||||
+ else if (len == 3)
|
||||
+ {
|
||||
+ if ((c0 = decode_base64url_char( p[0] )) > 63) return 0;
|
||||
+ if ((c1 = decode_base64url_char( p[1] )) > 63) return 0;
|
||||
+ if ((c2 = decode_base64url_char( p[2] )) > 63) return 0;
|
||||
+
|
||||
+ if (buf)
|
||||
+ {
|
||||
+ buf[i + 0] = (c0 << 2) | (c1 >> 4);
|
||||
+ buf[i + 1] = (c1 << 4) | (c2 >> 2);
|
||||
+ }
|
||||
+ i += 2;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if ((c0 = decode_base64url_char( p[0] )) > 63) return 0;
|
||||
+ if ((c1 = decode_base64url_char( p[1] )) > 63) return 0;
|
||||
+ if ((c2 = decode_base64url_char( p[2] )) > 63) return 0;
|
||||
+ if ((c3 = decode_base64url_char( p[3] )) > 63) return 0;
|
||||
+
|
||||
+ if (buf)
|
||||
+ {
|
||||
+ buf[i + 0] = (c0 << 2) | (c1 >> 4);
|
||||
+ buf[i + 1] = (c1 << 4) | (c2 >> 2);
|
||||
+ buf[i + 2] = (c2 << 6) | c3;
|
||||
+ }
|
||||
+ i += 3;
|
||||
+ }
|
||||
+ return i;
|
||||
+}
|
||||
+
|
||||
/* create a directory and all the needed parent directories */
|
||||
static int mkdir_p( int dirfd, const char *path, mode_t mode )
|
||||
{
|
||||
@@ -3715,6 +3793,132 @@ cleanup:
|
||||
}
|
||||
|
||||
|
||||
+/*
|
||||
+ * 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 get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG *size)
|
||||
+{
|
||||
+ char link_dir[PATH_MAX], link_path[PATH_MAX], *d;
|
||||
+ int link_path_len, buffer_len, encoded_len;
|
||||
+ REPARSE_DATA_BUFFER header;
|
||||
+ ULONG out_size = *size;
|
||||
+ char *unix_name = NULL;
|
||||
+ char *encoded = NULL;
|
||||
+ int link_dir_fd = -1;
|
||||
+ NTSTATUS status;
|
||||
+ ssize_t ret;
|
||||
+ int depth;
|
||||
+ char *p;
|
||||
+
|
||||
+ if ((status = server_get_unix_name( handle, &unix_name )))
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ ret = readlink( unix_name, link_path, sizeof(link_path) );
|
||||
+ if (ret < 0)
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ link_path_len = ret;
|
||||
+ link_path[link_path_len] = 0;
|
||||
+ if (strncmp( link_path, ".REPARSE_POINT/", 15 ) != 0)
|
||||
+ {
|
||||
+ status = STATUS_NOT_IMPLEMENTED;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ encoded_len = link_path_len;
|
||||
+ encoded = malloc( encoded_len );
|
||||
+ if (!encoded)
|
||||
+ {
|
||||
+ status = STATUS_NO_MEMORY;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ /* Copy the encoded data from the inital symlink */
|
||||
+ encoded[0] = 0;
|
||||
+ p = &link_path[15];
|
||||
+ if ((p = strchr( p, '/' )) == NULL)
|
||||
+ {
|
||||
+ status = STATUS_IO_REPARSE_DATA_INVALID;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ p++;
|
||||
+ if (*(p++) == '.')
|
||||
+ p++;
|
||||
+ for (depth=0; p < link_path + link_path_len; p += NAME_MAX+1, depth++)
|
||||
+ strncat( encoded, p, NAME_MAX );
|
||||
+ encoded[strlen(encoded)-1] = 0; /* chunk id */
|
||||
+ encoded[strlen(encoded)-1] = 0; /* final slash */
|
||||
+
|
||||
+ /* get the length of the full buffer so that we know when to stop collecting data */
|
||||
+ decode_base64url( encoded, sizeof(header), (char*)&header );
|
||||
+ buffer_len = header.ReparseDataLength+FIELD_OFFSET(typeof(header), GenericReparseBuffer);
|
||||
+ *size = buffer_len;
|
||||
+
|
||||
+ if (buffer_len > out_size)
|
||||
+ {
|
||||
+ status = STATUS_BUFFER_TOO_SMALL;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ encoded_len = (int)ceil(buffer_len*4/3.0);
|
||||
+ encoded = realloc( encoded, encoded_len + 3 ); /* 3 chars = slash, chunk ID, NUL character */
|
||||
+ if (!encoded)
|
||||
+ {
|
||||
+ status = STATUS_NO_MEMORY;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ /* change to the link folder so that we can build any necessary additional data */
|
||||
+ strcpy( link_dir, unix_name );
|
||||
+ d = dirname( link_dir);
|
||||
+ if (d != link_dir) strcpy( link_dir, d );
|
||||
+ link_dir_fd = open( link_dir, O_RDONLY|O_DIRECTORY );
|
||||
+
|
||||
+ /* Copy the encoded data from the follow on symlinks */
|
||||
+ while(strlen(encoded) < encoded_len)
|
||||
+ {
|
||||
+ int fd;
|
||||
+
|
||||
+ strcpy( link_dir, link_path );
|
||||
+ ret = readlinkat( link_dir_fd, link_dir, link_path, sizeof(link_path) );
|
||||
+ if (ret < 0)
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ link_path_len = ret;
|
||||
+ link_path[link_path_len] = 0; /* readlink does not NUL terminate */
|
||||
+
|
||||
+ p = &link_path[3*depth];
|
||||
+ for (depth=0; p < link_path + link_path_len; p += NAME_MAX+1, depth++)
|
||||
+ strncat( encoded, p, NAME_MAX );
|
||||
+ encoded[strlen(encoded)-1] = 0; /* chunk id */
|
||||
+ encoded[strlen(encoded)-1] = 0; /* final slash */
|
||||
+
|
||||
+ link_dir[strlen(link_dir)-1] = 0;
|
||||
+ fd = openat( link_dir_fd, link_dir, O_RDONLY|O_DIRECTORY );
|
||||
+ close( link_dir_fd );
|
||||
+ link_dir_fd = fd;
|
||||
+ }
|
||||
+
|
||||
+ /* Decode the reparse buffer from the base64-encoded symlink data */
|
||||
+ *size = decode_base64url( encoded, strlen(encoded), (char*)buffer );
|
||||
+ status = STATUS_SUCCESS;
|
||||
+ if (buffer_len != *size)
|
||||
+ {
|
||||
+ status = STATUS_IO_REPARSE_DATA_INVALID;
|
||||
+ ERR("Size mismatch decoding reparse point buffer (%d != %d)\n", *size, buffer_len);
|
||||
+ }
|
||||
+
|
||||
+cleanup:
|
||||
+ if (link_dir_fd != -1) close( link_dir_fd );
|
||||
+ free( unix_name );
|
||||
+ free( encoded );
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/******************************************************************************
|
||||
* lookup_unix_name
|
||||
*
|
||||
@@ -6525,15 +6729,6 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
|
||||
break;
|
||||
}
|
||||
|
||||
- case FSCTL_GET_REPARSE_POINT:
|
||||
- if (out_buffer && out_size)
|
||||
- {
|
||||
- FIXME("FSCTL_GET_REPARSE_POINT semi-stub\n");
|
||||
- status = STATUS_NOT_A_REPARSE_POINT;
|
||||
- }
|
||||
- else status = STATUS_INVALID_USER_BUFFER;
|
||||
- break;
|
||||
-
|
||||
case FSCTL_GET_OBJECT_ID:
|
||||
{
|
||||
FILE_OBJECTID_BUFFER *info = out_buffer;
|
||||
@@ -6555,6 +6750,14 @@ 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;
|
||||
+ ULONG size = out_size;
|
||||
+ status = get_reparse_point( handle, buffer, &size );
|
||||
+ io->Information = size;
|
||||
+ break;
|
||||
+ }
|
||||
case FSCTL_SET_REPARSE_POINT:
|
||||
{
|
||||
REPARSE_DATA_BUFFER *buffer = (REPARSE_DATA_BUFFER *)in_buffer;
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
From 3c25b2e7839c1493f97d144f137822cbf9a498a3 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 reparse points.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/unix/file.c | 99 +++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 121 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index 92ce83b685e..ba77aab61b7 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -3812,6 +3812,99 @@ cleanup:
|
||||
}
|
||||
|
||||
|
||||
+/*
|
||||
+ * 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 remove_reparse_point(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer)
|
||||
+{
|
||||
+ char tmpdir[PATH_MAX], tmplink[PATH_MAX], *d;
|
||||
+ BOOL tempdir_created = FALSE;
|
||||
+ int dest_fd, needs_close;
|
||||
+ BOOL is_dir = TRUE;
|
||||
+ NTSTATUS status;
|
||||
+ char *unix_name;
|
||||
+ struct stat st;
|
||||
+
|
||||
+ if ((status = server_get_unix_fd( handle, FILE_SPECIAL_ACCESS, &dest_fd, &needs_close, NULL, NULL )))
|
||||
+ return status;
|
||||
+
|
||||
+ if ((status = server_get_unix_name( handle, &unix_name )))
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ TRACE( "Deleting symlink %s\n", unix_name );
|
||||
+
|
||||
+ /* Produce the file/directory in a temporary location in the same folder */
|
||||
+ if (fstat( dest_fd, &st ) == -1)
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ is_dir = S_ISDIR(st.st_mode);
|
||||
+ strcpy( tmpdir, unix_name );
|
||||
+ d = dirname( tmpdir);
|
||||
+ if (d != tmpdir) strcpy( tmpdir, d );
|
||||
+ strcat( tmpdir, "/.winelink.XXXXXX" );
|
||||
+ if (mkdtemp( tmpdir ) == NULL)
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ tempdir_created = TRUE;
|
||||
+ strcpy( tmplink, tmpdir );
|
||||
+ strcat( tmplink, "/tmplink" );
|
||||
+ if (is_dir && mkdir( tmplink, st.st_mode ))
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ else if (!is_dir)
|
||||
+ {
|
||||
+ int fd = open( tmplink, O_CREAT|O_WRONLY|O_TRUNC, st.st_mode );
|
||||
+ if (fd < 0)
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ close( fd );
|
||||
+ }
|
||||
+ /* attemp to retain the ownership (if possible) */
|
||||
+ lchown( tmplink, st.st_uid, st.st_gid );
|
||||
+ /* Atomically move the directory into position */
|
||||
+ if (!renameat2( -1, tmplink, -1, unix_name, RENAME_EXCHANGE ))
|
||||
+ {
|
||||
+ /* success: link and folder/file have switched locations */
|
||||
+ unlink( tmplink ); /* remove the file (at link location) */
|
||||
+ }
|
||||
+ else if (errno == ENOSYS)
|
||||
+ {
|
||||
+ FIXME( "Atomic exchange of directory with symbolic link unsupported on this system, "
|
||||
+ "using unsafe exchange instead.\n" );
|
||||
+ if (unlink( unix_name ))
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ if (rename( tmplink, unix_name ))
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup; /* not moved, orignal file/folder at destination is orphaned */
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ status = STATUS_SUCCESS;
|
||||
+
|
||||
+cleanup:
|
||||
+ if (tempdir_created) rmdir( tmpdir );
|
||||
+ if (needs_close) close( dest_fd );
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/******************************************************************************
|
||||
* lookup_unix_name
|
||||
*
|
||||
@@ -6571,6 +6664,12 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
|
||||
break;
|
||||
}
|
||||
|
||||
+ case FSCTL_DELETE_REPARSE_POINT:
|
||||
+ {
|
||||
+ REPARSE_GUID_DATA_BUFFER *buffer = (REPARSE_GUID_DATA_BUFFER *)in_buffer;
|
||||
+ status = remove_reparse_point( handle, buffer );
|
||||
+ break;
|
||||
+ }
|
||||
case FSCTL_GET_REPARSE_POINT:
|
||||
{
|
||||
REPARSE_DATA_BUFFER *buffer = (REPARSE_DATA_BUFFER *)out_buffer;
|
||||
--
|
||||
2.37.2
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
From 246a50e7cf09bd1d77d327e170c2d7432e0d5f5e Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Ferrillo <lorenzofersteam@live.it>
|
||||
Date: Mon, 6 May 2024 23:46:44 +0200
|
||||
Subject: [PATCH] Return correct status value if handle is not a reparse point
|
||||
|
||||
---
|
||||
dlls/ntdll/unix/file.c | 19 ++++++++++++++-----
|
||||
1 file changed, 14 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index 2bfb9b7d051..93732543ae4 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -3944,9 +3944,11 @@ NTSTATUS get_reparse_point_unix(const char *unix_name, REPARSE_DATA_BUFFER *buff
|
||||
char *p;
|
||||
|
||||
ret = readlink( unix_name, link_path, sizeof(link_path) );
|
||||
+
|
||||
if (ret < 0)
|
||||
{
|
||||
- status = errno_to_status( errno );
|
||||
+ if (errno == EINVAL) status = STATUS_NOT_A_REPARSE_POINT;
|
||||
+ else status = errno_to_status( errno );
|
||||
goto cleanup;
|
||||
}
|
||||
link_path_len = ret;
|
||||
@@ -7303,10 +7305,17 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
|
||||
}
|
||||
case FSCTL_GET_REPARSE_POINT:
|
||||
{
|
||||
- REPARSE_DATA_BUFFER *buffer = (REPARSE_DATA_BUFFER *)out_buffer;
|
||||
- ULONG size = out_size;
|
||||
- status = get_reparse_point( handle, buffer, &size );
|
||||
- io->Information = size;
|
||||
+ io->Information = 0;
|
||||
+ if (out_buffer){
|
||||
+ REPARSE_DATA_BUFFER *buffer = (REPARSE_DATA_BUFFER *)out_buffer;
|
||||
+ ULONG size = out_size;
|
||||
+ status = get_reparse_point( handle, buffer, &size );
|
||||
+ if (status == STATUS_SUCCESS)
|
||||
+ io->Information = size;
|
||||
+ }
|
||||
+ else {
|
||||
+ status = STATUS_INVALID_USER_BUFFER;
|
||||
+ }
|
||||
break;
|
||||
}
|
||||
case FSCTL_SET_REPARSE_POINT:
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
From efd73d7778d8c083337bda1ad162618841c368e0 Mon Sep 17 00:00:00 2001
|
||||
From 6bef707eb81bcdaf7a4f159f07852cbf092a3a2a Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Tue, 30 Nov 2021 16:32:34 +0300
|
||||
Subject: [PATCH] ntdll: Implement opening files through nt device paths.
|
||||
|
||||
---
|
||||
dlls/ntdll/tests/file.c | 25 +++++++-
|
||||
dlls/ntdll/unix/file.c | 135 +++++++++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 157 insertions(+), 3 deletions(-)
|
||||
dlls/ntdll/unix/file.c | 133 +++++++++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 154 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index 25381caf313..7f048572e03 100644
|
||||
index 7016ca166f9..362c9fcc640 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -139,18 +139,22 @@ static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
|
||||
@@ -63,10 +63,10 @@ index 25381caf313..7f048572e03 100644
|
||||
|
||||
static void open_file_test(void)
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index 542a314ea81..68587cbef11 100644
|
||||
index a6873bb2f79..91afff6e49c 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -4593,7 +4593,7 @@ static NTSTATUS nt_to_unix_file_name_no_root( FILE_OBJECT *fileobj, char **unix_
|
||||
@@ -3721,7 +3721,7 @@ static NTSTATUS nt_to_unix_file_name_no_root( OBJECT_ATTRIBUTES *attr, UNICODE_S
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
@@ -75,16 +75,18 @@ index 542a314ea81..68587cbef11 100644
|
||||
*
|
||||
* Convert a file name from NT namespace to Unix namespace.
|
||||
*
|
||||
@@ -4601,7 +4601,7 @@ static NTSTATUS nt_to_unix_file_name_no_root( FILE_OBJECT *fileobj, char **unix_
|
||||
@@ -3729,8 +3729,8 @@ static NTSTATUS nt_to_unix_file_name_no_root( OBJECT_ATTRIBUTES *attr, UNICODE_S
|
||||
* element doesn't have to exist; in that case STATUS_NO_SUCH_FILE is
|
||||
* returned, but the unix name is still filled in properly.
|
||||
*/
|
||||
-static NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name_ret, UINT disposition )
|
||||
+NTSTATUS nt_to_unix_file_name_internal( const OBJECT_ATTRIBUTES *attr, char **name_ret, UINT disposition )
|
||||
-static NTSTATUS nt_to_unix_file_name( OBJECT_ATTRIBUTES *attr, UNICODE_STRING *nt_name,
|
||||
- char **name_ret, UINT disposition )
|
||||
+NTSTATUS nt_to_unix_file_name_internal( OBJECT_ATTRIBUTES *attr, UNICODE_STRING *nt_name,
|
||||
+ char **name_ret, UINT disposition )
|
||||
{
|
||||
HANDLE rootdir = attr->RootDirectory;
|
||||
enum server_fd_type type;
|
||||
@@ -4680,6 +4680,137 @@ reparse:
|
||||
int root_fd, needs_close;
|
||||
@@ -3781,6 +3781,133 @@ static NTSTATUS nt_to_unix_file_name( OBJECT_ATTRIBUTES *attr, UNICODE_STRING *n
|
||||
}
|
||||
|
||||
|
||||
@@ -162,18 +164,18 @@ index 542a314ea81..68587cbef11 100644
|
||||
+ * element doesn't have to exist; in that case STATUS_NO_SUCH_FILE is
|
||||
+ * returned, but the unix name is still filled in properly.
|
||||
+ */
|
||||
+NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name_ret, UINT disposition )
|
||||
+NTSTATUS nt_to_unix_file_name( OBJECT_ATTRIBUTES *attr, UNICODE_STRING *nt_name,
|
||||
+ char **name_ret, UINT disposition )
|
||||
+{
|
||||
+ static const WCHAR systemrootW[] = {'\\','S','y','s','t','e','m','R','o','o','t','\\',0};
|
||||
+ static const WCHAR dosprefixW[] = {'\\','?','?','\\'};
|
||||
+ static const WCHAR deviceW[] = {'\\','D','e','v','i','c','e','\\',0};
|
||||
+ WCHAR *name, *ptr, *prefix, buffer[3] = {'c',':',0};
|
||||
+ UNICODE_STRING dospathW, *nameW;
|
||||
+ OBJECT_ATTRIBUTES attr_copy;
|
||||
+ UNICODE_STRING *nameW;
|
||||
+ size_t offset, name_len;
|
||||
+ NTSTATUS status;
|
||||
+
|
||||
+ if (attr->RootDirectory) return nt_to_unix_file_name_internal( attr, name_ret, disposition );
|
||||
+ if (attr->RootDirectory) return nt_to_unix_file_name_internal( attr, nt_name, name_ret, disposition );
|
||||
+
|
||||
+ nameW = attr->ObjectName;
|
||||
+
|
||||
@@ -192,7 +194,7 @@ index 542a314ea81..68587cbef11 100644
|
||||
+ prefix = user_shared_data->NtSystemRoot;
|
||||
+ }
|
||||
+ else
|
||||
+ return nt_to_unix_file_name_internal( attr, name_ret, disposition );
|
||||
+ return nt_to_unix_file_name_internal( attr, nt_name, name_ret, disposition );
|
||||
+
|
||||
+ name_len = sizeof(dosprefixW) + wcslen(prefix) * sizeof(WCHAR)
|
||||
+ + sizeof(WCHAR) /* '\\' */ + nameW->Length - offset * sizeof(WCHAR) + sizeof(WCHAR);
|
||||
@@ -208,14 +210,10 @@ index 542a314ea81..68587cbef11 100644
|
||||
+ memcpy( ptr, nameW->Buffer + offset, nameW->Length - offset * sizeof(WCHAR) );
|
||||
+ ptr[ nameW->Length / sizeof(WCHAR) - offset ] = 0;
|
||||
+
|
||||
+ dospathW.Buffer = name;
|
||||
+ dospathW.Length = wcslen( name ) * sizeof(WCHAR);
|
||||
+ attr_copy = *attr;
|
||||
+ attr_copy.ObjectName = &dospathW;
|
||||
+ status = nt_to_unix_file_name_internal( &attr_copy, name_ret, disposition );
|
||||
+
|
||||
+ free( name );
|
||||
+ return status;
|
||||
+ nt_name->Buffer = name;
|
||||
+ nt_name->Length = wcslen( name ) * sizeof(WCHAR);
|
||||
+ attr->ObjectName = nt_name;
|
||||
+ return nt_to_unix_file_name_internal( attr, nt_name, name_ret, disposition );
|
||||
+}
|
||||
+
|
||||
+
|
||||
@@ -223,5 +221,5 @@ index 542a314ea81..68587cbef11 100644
|
||||
* collapse_path
|
||||
*
|
||||
--
|
||||
2.47.2
|
||||
2.51.0
|
||||
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
Fixes: [37487] Resolve \\SystemRoot\\ prefix when opening files
|
||||
Fixes: Implement opening files through nt device paths
|
||||
Depends: ntdll-Junction_Points
|
||||
Disabled: True
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
From f8970096657145099840f30a355661e5cfe74b72 Mon Sep 17 00:00:00 2001
|
||||
From 30cc9b257b136f32e1d04fe77411dcb9e4a818ef Mon Sep 17 00:00:00 2001
|
||||
From: Ally Sommers <dropbear.sh@gmail.com>
|
||||
Date: Thu, 30 Jan 2025 23:48:43 +0100
|
||||
Subject: [PATCH] server: Allow for deletion of socket files.
|
||||
@@ -10,10 +10,10 @@ is analogous to unbinding.
|
||||
1 file changed, 27 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/server/fd.c b/server/fd.c
|
||||
index dde92beb664..b937e1238b2 100644
|
||||
index 4db5209ee4c..e4b1f03882a 100644
|
||||
--- a/server/fd.c
|
||||
+++ b/server/fd.c
|
||||
@@ -2072,6 +2072,19 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam
|
||||
@@ -1983,6 +1983,19 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam
|
||||
fd->unix_fd = open( name, O_RDONLY | (flags & ~(O_TRUNC | O_CREAT | O_EXCL)), *mode );
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ index dde92beb664..b937e1238b2 100644
|
||||
if (fd->unix_fd == -1)
|
||||
{
|
||||
/* check for trailing slash on file path */
|
||||
@@ -2083,13 +2096,24 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam
|
||||
@@ -1994,13 +2007,24 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,12 +55,12 @@ index dde92beb664..b937e1238b2 100644
|
||||
*mode = st.st_mode;
|
||||
|
||||
- /* only bother with an inode for normal files and directories */
|
||||
- if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))
|
||||
- if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
|
||||
+ /* only bother with an inode for normal files, directories, and socket files */
|
||||
+ if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode) || S_ISSOCK(st.st_mode))
|
||||
+ if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISSOCK(st.st_mode))
|
||||
{
|
||||
unsigned int err;
|
||||
struct inode *inode = get_inode( st.st_dev, st.st_ino, fd->unix_fd );
|
||||
--
|
||||
2.47.2
|
||||
2.51.0
|
||||
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
Fixes: [52568] ws_ws2: Support for AF_UNIX sockets.
|
||||
Depends: ntdll-Junction_Points
|
||||
Disabled: True
|
||||
|
||||
Reference in New Issue
Block a user