From c8c2492b130f102effa9e5e9b42b89cb511f3b3e Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Fri, 31 Oct 2025 15:17:38 +1100 Subject: [PATCH] Rebase against cd858d59d6532a0cf624ff1dabc57a370deb43bf. --- ...-support-for-creating-reparse-points.patch | 8 +- ...ort-for-creating-Unix-Linux-symlinks.patch | 22 +- ...2-tests-Add-test-for-AF_UNIX-sockets.patch | 330 ------------------ staging/upstream-commit | 2 +- 4 files changed, 16 insertions(+), 346 deletions(-) delete mode 100644 patches/ws2_32-af_unix/0006-ws2_32-tests-Add-test-for-AF_UNIX-sockets.patch diff --git a/patches/ntdll-Junction_Points/0001-ntdll-Add-support-for-creating-reparse-points.patch b/patches/ntdll-Junction_Points/0001-ntdll-Add-support-for-creating-reparse-points.patch index 833d8257..ee903956 100644 --- a/patches/ntdll-Junction_Points/0001-ntdll-Add-support-for-creating-reparse-points.patch +++ b/patches/ntdll-Junction_Points/0001-ntdll-Add-support-for-creating-reparse-points.patch @@ -1,4 +1,4 @@ -From f0d41c59ac06aabfba83d598fb017c7f0a918a99 Mon Sep 17 00:00:00 2001 +From 5f3feef99f8c9740f04dbe0ee1b23ca27d60548e Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Thu, 16 Jan 2014 20:56:49 -0700 Subject: [PATCH] ntdll: Add support for creating reparse points. @@ -12,11 +12,11 @@ Signed-off-by: Erich E. Hoover 4 files changed, 310 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac -index 242eb15ec19..ccd5095f3ba 100644 +index b675da34d58..63e3bb5bdc7 100644 --- a/configure.ac +++ b/configure.ac -@@ -2132,6 +2132,8 @@ AC_CHECK_FUNCS(\ - prctl \ +@@ -2137,6 +2137,8 @@ AC_CHECK_FUNCS(\ + process_vm_writev \ sched_getcpu \ sched_yield \ + renameat \ diff --git a/patches/ntdll-Junction_Points/0024-ntdll-Add-support-for-creating-Unix-Linux-symlinks.patch b/patches/ntdll-Junction_Points/0024-ntdll-Add-support-for-creating-Unix-Linux-symlinks.patch index 76816804..edda5f93 100644 --- a/patches/ntdll-Junction_Points/0024-ntdll-Add-support-for-creating-Unix-Linux-symlinks.patch +++ b/patches/ntdll-Junction_Points/0024-ntdll-Add-support-for-creating-Unix-Linux-symlinks.patch @@ -1,19 +1,19 @@ -From e4b0e1bd0ae993ac209367318a98ad63a5eec62b Mon Sep 17 00:00:00 2001 +From 4d813b6202a9fb74ee1ca1573658bd27dce11f78 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Mon, 3 May 2021 09:28:08 -0600 Subject: [PATCH] ntdll: Add support for creating Unix/Linux symlinks. Signed-off-by: Erich E. Hoover --- - dlls/ntdll/unix/file.c | 38 ++++++++++++++++++++++++++------------ - include/winnt.h | 1 + - 3 files changed, 62 insertions(+), 12 deletions(-) + dlls/ntdll/unix/file.c | 38 ++++++++++++++++++++++++++------------ + include/winnt.h | 1 + + 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index fe1c50468a4..f87117438b8 100644 +index cb1932949d6..4fa7c610c46 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -3761,20 +3761,33 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) +@@ -3864,20 +3864,33 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) * *) Append the base64-url encoded reparse point buffer * *) Append the filename of the first continuing symlink (0) in case we need it */ @@ -58,7 +58,7 @@ index fe1c50468a4..f87117438b8 100644 /* Produce the link in a temporary location in the same folder */ strcpy( tmpdir, unix_src ); -@@ -3839,7 +3852,8 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) +@@ -3942,7 +3955,8 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) } /* create the very last link directory */ @@ -69,17 +69,17 @@ index fe1c50468a4..f87117438b8 100644 strcpy( link_path, target_path ); strcpy( link_dir, link_path ); diff --git a/include/winnt.h b/include/winnt.h -index 019d0b16693..469287cc0ef 100644 +index 24485ef0e39..1e31471e797 100644 --- a/include/winnt.h +++ b/include/winnt.h -@@ -2330,6 +2330,7 @@ extern struct _TEB * WINAPI NtCurrentTeb(void); +@@ -2563,6 +2563,7 @@ static FORCEINLINE struct _TEB * WINAPI NtCurrentTeb(void) #define IO_REPARSE_TAG_CLOUD_MASK __MSABI_LONG(0x0000F000) #define IO_REPARSE_TAG_APPEXECLINK __MSABI_LONG(0x8000001B) - #define IO_REPARSE_TAG_GVFS __MSABI_LONG(0x9000001C) + #define IO_REPARSE_TAG_PROJFS __MSABI_LONG(0x9000001C) +#define IO_REPARSE_TAG_LX_SYMLINK __MSABI_LONG(0xA000001D) #define IO_REPARSE_TAG_STORAGE_SYNC __MSABI_LONG(0x8000001E) #define IO_REPARSE_TAG_WCI_TOMBSTONE __MSABI_LONG(0xA000001F) #define IO_REPARSE_TAG_UNHANDLED __MSABI_LONG(0x80000020) -- -2.37.2 +2.51.0 diff --git a/patches/ws2_32-af_unix/0006-ws2_32-tests-Add-test-for-AF_UNIX-sockets.patch b/patches/ws2_32-af_unix/0006-ws2_32-tests-Add-test-for-AF_UNIX-sockets.patch deleted file mode 100644 index 7d948c73..00000000 --- a/patches/ws2_32-af_unix/0006-ws2_32-tests-Add-test-for-AF_UNIX-sockets.patch +++ /dev/null @@ -1,330 +0,0 @@ -From 967bb126734f126d3023f23b90c082e410ef177c Mon Sep 17 00:00:00 2001 -From: Ally Sommers -Date: Thu, 30 Jan 2025 23:50:25 +0100 -Subject: [PATCH] ws2_32/tests: Add test for AF_UNIX sockets. - -Bug: https://bugs.winehq.org/show_bug.cgi?id=52568 ---- - dlls/ws2_32/tests/sock.c | 292 +++++++++++++++++++++++++++++++++++++++ - 1 file changed, 292 insertions(+) - -diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c -index 2ca5b9fc8b2..c6147be7e10 100644 ---- a/dlls/ws2_32/tests/sock.c -+++ b/dlls/ws2_32/tests/sock.c -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -14463,6 +14464,296 @@ static void test_send_buffering(void) - closesocket(client); - } - -+static void test_afunix(void) -+{ -+ SOCKET listener, client, server = 0; -+ SOCKADDR_UN addr = { AF_UNIX, "test_afunix.sock" }; -+ char serverBuf[] = "ws2_32/AF_UNIX socket test"; -+ char clientBuf[sizeof(serverBuf)] = { 0 }; -+ -+ char paths[4][sizeof(addr.sun_path)] = { "./tmp.sock", "../tmp.sock" }; -+ char dosPath[sizeof(addr.sun_path)]; -+ WCHAR dosWidePath[sizeof(addr.sun_path)]; -+ UNICODE_STRING ntPath = { 0 }; -+ SOCKADDR_UN outAddr = { 0 }; -+ int outAddrSize = sizeof(outAddr); -+ SOCKADDR_UN truncatedAddr = { 0 }; -+ ULONG zero = 0; -+ ULONG one = 1; -+ int ret; -+ -+ /* Test connection and send/recv */ -+ listener = socket(AF_UNIX, SOCK_STREAM, 0); -+ if (listener == INVALID_SOCKET && GetLastError() == WSAEAFNOSUPPORT) -+ { -+ win_skip("AF_UNIX sockets are unsupported, skipping...\n"); -+ return; -+ } -+ -+ ok(listener != INVALID_SOCKET, "Could not create Unix socket: %lu\n", -+ GetLastError()); -+ -+ ret = bind(listener, (SOCKADDR *)&addr, 0); -+ ok(ret && GetLastError() == WSAEFAULT, "Incorrect error: %lu\n", GetLastError()); -+ ret = bind(listener, (SOCKADDR *)&addr, 2); -+ ok(!ret, "Could not bind Unix socket: %lu\n", GetLastError()); -+ ret = listen(listener, 1); -+ ok(!ret, "Could not listen on Unix socket: %lu\n", GetLastError()); -+ closesocket(listener); -+ -+ listener = socket(AF_UNIX, SOCK_STREAM, 0); -+ ok(listener != INVALID_SOCKET, "Could not create Unix socket: %lu\n", -+ GetLastError()); -+ ret = bind(listener, (SOCKADDR *)&addr, 3); -+ ok(!ret, "Could not bind Unix socket: %lu\n", GetLastError()); -+ -+ memcpy(&truncatedAddr, &addr, 3); -+ ret = getsockname(listener, (SOCKADDR *)&outAddr, &outAddrSize); -+ ok(!ret, "Could not get info on Unix socket: %lu\n", GetLastError()); -+ ok(!memcmp(truncatedAddr.sun_path, outAddr.sun_path, sizeof(addr.sun_path)), -+ "getsockname returned incorrect path '%s' for provided path '%s'\n", -+ outAddr.sun_path, -+ truncatedAddr.sun_path); -+ ok(outAddrSize == sizeof(outAddr.sun_family) + strlen(outAddr.sun_path) + 1, -+ "getsockname returned incorrect size '%d' for provided path '%s'\n", -+ outAddrSize, -+ truncatedAddr.sun_path); -+ closesocket(listener); -+ ret = DeleteFileA(truncatedAddr.sun_path); -+ ok(ret, "DeleteFileA on socket file failed: %lu\n", GetLastError()); -+ ok(GetFileAttributesA(truncatedAddr.sun_path) == INVALID_FILE_ATTRIBUTES && -+ GetLastError() == ERROR_FILE_NOT_FOUND, -+ "Failed to delete socket file at path '%s'\n", -+ truncatedAddr.sun_path); -+ -+ listener = socket(AF_UNIX, SOCK_STREAM, 0); -+ ok(listener != INVALID_SOCKET, "Could not create Unix socket: %lu\n", -+ GetLastError()); -+ -+ ret = bind(listener, (SOCKADDR *)&addr, sizeof(SOCKADDR_UN)); -+ ok(!ret, "Could not bind Unix socket: %lu\n", GetLastError()); -+ -+ ret = listen(listener, 1); -+ ok(!ret, "Could not listen on Unix socket: %lu\n", GetLastError()); -+ -+ client = socket(AF_UNIX, SOCK_STREAM, 0); -+ ok(client != INVALID_SOCKET, "Failed to create second Unix socket: %lu\n", -+ GetLastError()); -+ -+ ret = ioctlsocket(client, FIONBIO, &one); -+ ok(!ret, "Could not set AF_UNIX socket to nonblocking: %lu; skipping connection\n", GetLastError()); -+ if (!ret) -+ { -+ ret = connect(client, (SOCKADDR *)&addr, sizeof(addr)); -+ ok(!ret || (ret == SOCKET_ERROR && GetLastError() == WSAEWOULDBLOCK), -+ "Error when connecting to Unix socket: %lu\n", -+ GetLastError()); -+ server = accept(listener, NULL, NULL); -+ ok(server != INVALID_SOCKET, "Could not accept Unix socket connection: %lu\n", -+ GetLastError()); -+ ret = ioctlsocket(client, FIONBIO, &zero); -+ ok(!ret, "Could not set AF_UNIX socket to blocking: %lu\n", GetLastError()); -+ } -+ -+ ret = send(server, serverBuf, sizeof(serverBuf), 0); -+ ok(ret == sizeof(serverBuf), "Incorrect return value from send: %d\n", ret); -+ ret = recv(client, clientBuf, sizeof(serverBuf), 0); -+ ok(ret == sizeof(serverBuf), "Incorrect return value from recv: %d\n", ret); -+ ok(!memcmp(serverBuf, clientBuf, sizeof(serverBuf)), "Data mismatch over Unix socket\n"); -+ -+ memset(clientBuf, 0, sizeof(clientBuf)); -+ -+ ret = sendto(server, serverBuf, sizeof(serverBuf), 0, NULL, 0); -+ ok(ret == sizeof(serverBuf), "Incorrect return value from sendto: %d\n", ret); -+ ret = recvfrom(client, clientBuf, sizeof(serverBuf), 0, NULL, 0); -+ ok(ret == sizeof(serverBuf), "Incorrect return value from recvfrom: %d\n", ret); -+ ok(!memcmp(serverBuf, clientBuf, sizeof(serverBuf)), "Data mismatch over Unix socket\n"); -+ -+ memset(serverBuf, 0, sizeof(serverBuf)); -+ -+ ret = send(client, clientBuf, sizeof(clientBuf), 0); -+ ok(ret == sizeof(clientBuf), "Incorrect return value from send: %d\n", ret); -+ ret = recv(server, serverBuf, sizeof(clientBuf), 0); -+ ok(ret == sizeof(serverBuf), "Incorrect return value from recv: %d\n", ret); -+ ok(!memcmp(serverBuf, clientBuf, sizeof(clientBuf)), "Data mismatch over Unix socket\n"); -+ -+ memset(serverBuf, 0, sizeof(serverBuf)); -+ -+ ret = sendto(client, clientBuf, sizeof(clientBuf), 0, NULL, 0); -+ ok(ret == sizeof(clientBuf), "Incorrect return value from sendto: %d\n", ret); -+ ret = recvfrom(server, serverBuf, sizeof(clientBuf), 0, NULL, 0); -+ ok(ret == sizeof(serverBuf), "Incorrect return value from recvfrom: %d\n", ret); -+ ok(!memcmp(serverBuf, clientBuf, sizeof(clientBuf)), "Data mismatch over Unix socket\n"); -+ -+ closesocket(listener); -+ closesocket(client); -+ closesocket(server); -+ -+ /* Test socket file deletion */ -+ ret = DeleteFileA("test_afunix.sock"); -+ ok(ret, "DeleteFileA on socket file failed: %lu\n", GetLastError()); -+ ok(GetFileAttributesA("test_afunix.sock") == INVALID_FILE_ATTRIBUTES && -+ GetLastError() == ERROR_FILE_NOT_FOUND, -+ "Failed to delete socket file at path '%s'\n", -+ addr.sun_path); -+ -+ /* Test failure modes */ -+ listener = socket(AF_UNIX, SOCK_STREAM, 0); -+ ok(listener != INVALID_SOCKET, "Could not create Unix socket: %lu\n", -+ GetLastError()); -+ ret = bind(listener, (SOCKADDR *)&addr, sizeof(SOCKADDR_UN)); -+ ok(!ret, "Could not bind Unix socket to path '%s': %lu\n", addr.sun_path, GetLastError()); -+ closesocket(listener); -+ listener = socket(AF_UNIX, SOCK_STREAM, 0); -+ ok(listener != INVALID_SOCKET, "Could not create Unix socket: %lu\n", -+ GetLastError()); -+ ret = bind(listener, (SOCKADDR *)&addr, sizeof(SOCKADDR_UN)); -+ ok(ret && GetLastError() == WSAEADDRINUSE, -+ "Bound Unix socket to path '%s' despite existing socket file: %lu\n", -+ addr.sun_path, -+ GetLastError()); -+ closesocket(listener); -+ ret = DeleteFileA(addr.sun_path); -+ ok(ret, "DeleteFileA on socket file failed: %lu\n", GetLastError()); -+ ok(GetFileAttributesA("test_afunix.sock") == INVALID_FILE_ATTRIBUTES && -+ GetLastError() == ERROR_FILE_NOT_FOUND, -+ "Failed to delete socket file at path '%s'\n", -+ addr.sun_path); -+ -+ /* Test different path types (relative, NT, etc.) */ -+ GetTempPathA(sizeof(paths[0]) - 1, paths[2]); -+ strcat(paths[2], "tmp.sock"); -+ MultiByteToWideChar(CP_ACP, 0, paths[2], -1, dosWidePath, sizeof(dosPath)); -+ RtlDosPathNameToNtPathName_U(dosWidePath, &ntPath, NULL, NULL); -+ RtlUnicodeToMultiByteN(paths[3], sizeof(addr.sun_path) - 1, NULL, ntPath.Buffer, ntPath.Length); -+ -+ for (int i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) -+ { -+ memcpy(addr.sun_path, paths[i], sizeof(paths[i])); -+ -+ listener = socket(AF_UNIX, SOCK_STREAM, 0); -+ ok(listener != INVALID_SOCKET, "Could not create Unix socket: %lu\n", -+ GetLastError()); -+ -+ ret = bind(listener, (SOCKADDR *)&addr, sizeof(SOCKADDR_UN)); -+ ok(!ret, "Could not bind Unix socket to path '%s': %lu\n", addr.sun_path, GetLastError()); -+ -+ ret = listen(listener, 1); -+ ok(!ret, "Could not listen on Unix socket: %lu\n", GetLastError()); -+ -+ client = socket(AF_UNIX, SOCK_STREAM, 0); -+ ok(client != INVALID_SOCKET, "Failed to create second Unix socket: %lu\n", -+ GetLastError()); -+ -+ ret = ioctlsocket(client, FIONBIO, &one); -+ ok(!ret, "Could not set AF_UNIX socket to nonblocking: %lu; skipping connection\n", GetLastError()); -+ if (!ret) -+ { -+ ret = connect(client, (SOCKADDR *)&addr, sizeof(addr)); -+ ok(!ret || (ret == SOCKET_ERROR && GetLastError() == WSAEWOULDBLOCK), -+ "Error when connecting to Unix socket: %lu\n", -+ GetLastError()); -+ server = accept(listener, NULL, NULL); -+ ok(server != INVALID_SOCKET, "Could not accept Unix socket connection: %lu\n", -+ GetLastError()); -+ ret = ioctlsocket(client, FIONBIO, &zero); -+ ok(!ret, "Could not set AF_UNIX socket to blocking: %lu\n", GetLastError()); -+ } -+ -+ memset(&outAddr, 0, sizeof(outAddr)); -+ outAddrSize = sizeof(outAddr); -+ ret = getsockname(listener, (SOCKADDR *)&outAddr, &outAddrSize); -+ ok(!ret, "Could not get info on Unix socket: %lu\n", GetLastError()); -+ ok(!memcmp(addr.sun_path, outAddr.sun_path, sizeof(addr.sun_path)), -+ "getsockname returned incorrect path '%s' for provided path '%s'\n", -+ outAddr.sun_path, -+ addr.sun_path); -+ ok(outAddrSize == sizeof(outAddr.sun_family) + strlen(outAddr.sun_path) + 1, -+ "getsockname returned incorrect size '%d' for provided path '%s'\n", -+ outAddrSize, -+ addr.sun_path); -+ -+ memset(&outAddr, 0, sizeof(outAddr)); -+ outAddrSize = sizeof(outAddr); -+ ret = getsockname(client, (SOCKADDR *)&outAddr, &outAddrSize); -+ ok(!ret, "Could not get info on Unix socket: %lu\n", GetLastError()); -+ ok(!memcmp((char[108]){0}, outAddr.sun_path, sizeof(addr.sun_path)), -+ "getsockname returned incorrect path '%s' for provided path '%s'\n", -+ outAddr.sun_path, -+ addr.sun_path); -+ ok(outAddrSize == sizeof(outAddr), -+ "getsockname returned incorrect size '%d' for provided path '%s'\n", -+ outAddrSize, -+ addr.sun_path); -+ -+ memset(&outAddr, 0, sizeof(outAddr)); -+ outAddrSize = sizeof(outAddr); -+ ret = getsockname(server, (SOCKADDR *)&outAddr, &outAddrSize); -+ ok(!ret, "Could not get info on Unix socket: %lu\n", GetLastError()); -+ ok(!memcmp(addr.sun_path, outAddr.sun_path, sizeof(addr.sun_path)), -+ "getsockname returned incorrect path '%s' for provided path '%s'\n", -+ outAddr.sun_path, -+ addr.sun_path); -+ ok(outAddrSize == sizeof(outAddr.sun_family) + strlen(outAddr.sun_path) + 1, -+ "getsockname returned incorrect size '%d' for provided path '%s'\n", -+ outAddrSize, -+ addr.sun_path); -+ -+ memset(&outAddr, 0, sizeof(outAddr)); -+ outAddrSize = sizeof(outAddr); -+ ret = getpeername(listener, (SOCKADDR *)&outAddr, &outAddrSize); -+ ok(ret == -1, "Got info on Unix socket: %lu\n", GetLastError()); -+ ok(GetLastError() == WSAENOTCONN, -+ "Incorrect error returned from getpeername on Unix socket: %ld\n", -+ GetLastError()); -+ ok(!memcmp((char[108]){0}, outAddr.sun_path, sizeof(addr.sun_path)), -+ "getpeername returned incorrect path '%s' for provided path '%s'\n", -+ outAddr.sun_path, -+ addr.sun_path); -+ ok(outAddrSize == sizeof(outAddr), -+ "getpeername returned incorrect size '%d' for provided path '%s'\n", -+ outAddrSize, -+ addr.sun_path); -+ -+ memset(&outAddr, 0, sizeof(outAddr)); -+ outAddrSize = sizeof(outAddr); -+ ret = getpeername(client, (SOCKADDR *)&outAddr, &outAddrSize); -+ ok(!ret, "Could not get info on Unix socket: %lu\n", GetLastError()); -+ ok(!memcmp(addr.sun_path, outAddr.sun_path, sizeof(addr.sun_path)), -+ "getpeername returned incorrect path '%s' for provided path '%s'\n", -+ outAddr.sun_path, -+ addr.sun_path); -+ ok(outAddrSize == sizeof(outAddr), -+ "getpeername returned incorrect size '%d' for provided path '%s'\n", -+ outAddrSize, -+ addr.sun_path); -+ -+ memset(&outAddr, 0, sizeof(outAddr)); -+ outAddrSize = sizeof(outAddr); -+ ret = getpeername(server, (SOCKADDR *)&outAddr, &outAddrSize); -+ ok(!ret, "Could not get info on Unix socket: %lu\n", GetLastError()); -+ ok(!memcmp((char[108]){0}, outAddr.sun_path, sizeof(addr.sun_path)), -+ "getpeername returned incorrect path '%s' for provided path '%s'\n", -+ outAddr.sun_path, -+ addr.sun_path); -+ ok(outAddrSize == sizeof(outAddr), -+ "getpeername returned incorrect size '%d' for provided path '%s'\n", -+ outAddrSize, -+ addr.sun_path); -+ -+ closesocket(listener); -+ closesocket(client); -+ closesocket(server); -+ -+ ret = DeleteFileA(addr.sun_path); -+ ok(ret, "DeleteFileA on socket file failed: %lu\n", GetLastError()); -+ ok(GetFileAttributesA(addr.sun_path) == INVALID_FILE_ATTRIBUTES && -+ GetLastError() == ERROR_FILE_NOT_FOUND, -+ "Failed to delete socket file at path '%s'\n", -+ addr.sun_path); -+ } -+} -+ - static void test_valid_handle(void) - { - HANDLE duplicated, invalid; -@@ -14595,6 +14886,7 @@ START_TEST( sock ) - test_tcp_sendto_recvfrom(); - test_broadcast(); - test_send_buffering(); -+ test_afunix(); - test_valid_handle(); - - /* There is apparently an obscure interaction between this test and --- -2.47.2 - diff --git a/staging/upstream-commit b/staging/upstream-commit index df696c3a..a505a824 100644 --- a/staging/upstream-commit +++ b/staging/upstream-commit @@ -1 +1 @@ -bc5f39ebf5fa3e936ad8fea726441b88716724c4 +cd858d59d6532a0cf624ff1dabc57a370deb43bf