We've been having problems with a winelib tool executable (an oleaut typelib code generator somewhat like MSVC's #import) since wine-5.12, but we also have been having enough other issues that debugging it so we could upgrade to the latest wine-5.x hadn't reached the top of the pile to debug. Sorry for the delay in reporting this.
The symptom is that it is now trying to write files outside the shadow build folder. This seems to be a regression with its use of libstdc++ file I/O and std::filesystem that are looking to the posix current directory. This use of posix I/O is deliberate; although it's using some wine functions internally, it is supposed to present a posix-path command-line interface since cmake/ninja/etc won't know anything about windows paths.
However, the following change (maybe unintentionally) causes winelib executables to lose the cwd in which they were launched:
From df5e4764870e8ad1d8b206cb3475a073bc034e48 Mon Sep 17 00:00:00 2001
From: Alexandre Julliard julliard@winehq.org Date: Wed, 17 Jun 2020 16:19:38 +0200 Subject: [PATCH] ntdll: Move the current directory initialization to the Unix library.
------------------------------- dlls/ntdll/env.c ------------------------------- index 992ec19fae..38f65c89d3 100644 @@ -1550,6 +1494,5 @@ done: RtlInitUnicodeString( &curdir, windows_dir ); RtlSetCurrentDirectory_U( &curdir ); } - if (!params->CurrentDirectory.Handle) chdir("/"); /* avoid locking removable devices */ set_wow64_environment( ¶ms->Environment ); }
---------------------------- dlls/ntdll/unix/env.c ---------------------------- index 8b37d3dcca..de03bb566d 100644 @@ -919,4 +919,5 @@ void CDECL get_initial_directory
MESSAGE("Warning: could not find DOS drive for current working directory '%s', " "starting in the Windows directory.\n", cwd ? cwd : "" ); free( cwd ); + chdir( "/" ); /* avoid locking removable devices */ }
Note that the chdir("/") wasn't only moved into the unix library, it was also made unconditional instead of just being the fallback if there was no params->CurrentDirectory.Handle. So now winelib .exe.so programs are now almost always launched with their posix/win32 cwds mismatched, as can be seen with a simple test app:
#include <windows.h> #include <stdio.h> #include <unistd.h>
int main() { chdir("/tmp");
char win32_cwd[MAX_PATH]; char posix_cwd[MAX_PATH]; GetCurrentDirectory(sizeof(win32_cwd),win32_cwd); printf("win32_cwd = %s\n",win32_cwd);
getcwd(posix_cwd,sizeof(posix_cwd)); printf("posix_cwd = %s\n",posix_cwd); }
Which prints win32_cwd = Z:\home\foobar\cwd_test posix_cwd = /
Up through wine 5.10, using "/" was just the fallback if there was no windows CurrentDirectory handle, so this would usually have printed: win32_cwd = Z:\home\foobar\cwd_test posix_cwd = /home/foobar/cwd_test
Previously, if the current directory where the cwd.exe test script (or wine cwd.test.exe.so) was launched could be located by a windows path, the windows and posix cwds started out in sync with each other and with the process execution. Using Win32 or libstdc++ file I/O behaved consistently, which is what tlimport expected; if given relative paths it reads input and generates output in the current directory it was launched in.
But params->CurrentDirectory is not visible in the unix half, so the condition can't just be restored, and I assume there was a good reason for moving this and you wouldn't want to just move the chdir back to ntdll But I'm not sure what that motivation was, so a fix or any input on what form of fix you'd like to see would be very welcome.
If it *was* an intentional effect of the change, that's fine too; just say so. I can certainly adjust our tool to cope, it would just need something like chdir(wine_get_unix_file_name(GetCurrentDirectory())) in main() to get the two worlds back aligned. I'm not much concerned about the weird corner cases like running the tool in a deleted directory, where one couldn't navigate back by name. I think those would actually have had this behavior all along, since presumably wine couldn't have gotten params->CurrentDirectory.Handle