Regression in current directory initialization in wine-5.11+

Puetz Kevin A PuetzKevinA at JohnDeere.com
Wed Sep 2 19:55:01 CDT 2020


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 at 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( &params->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



More information about the wine-devel mailing list