[PATCH 0/1] MR9881: cmd: Replace '/' to '\' for path in 'WCMD_pushd'
The parameter of the 'pushd' command may contain the character ‘/’, which is compatible with Windows. Signed-off-by: YeshunYe <yeyeshun@uniontech.com> -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9881
From: YeshunYe <yeyeshun@uniontech.com> The parameter of the 'pushd' command may contain the character ‘/’, which is compatible with Windows. Signed-off-by: YeshunYe <yeyeshun@uniontech.com> --- programs/cmd/builtins.c | 10 +++++----- programs/cmd/wcmd.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index 7d1ad5c1e15..447ddacc9f8 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -1774,19 +1774,19 @@ RETURN_CODE WCMD_goto(void) * Push a directory onto the stack */ -RETURN_CODE WCMD_pushd(const WCHAR *args) +RETURN_CODE WCMD_pushd(WCHAR *args) { struct env_stack *curdir; WCHAR *thisdir; RETURN_CODE return_code; + WCHAR *backslask; if (!*args) return errorlevel = NO_ERROR; - if (wcschr(args, '/') != NULL) { - SetLastError(ERROR_INVALID_PARAMETER); - WCMD_print_error(); - return errorlevel = ERROR_INVALID_FUNCTION; + while ((backslask = wcschr(args, '/'))) + { + *backslask = '\\'; } curdir = xalloc(sizeof(struct env_stack)); diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index c8d0d03e9e6..ee11d83c920 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h @@ -193,7 +193,7 @@ RETURN_CODE WCMD_output_asis_stderr(const WCHAR *message); RETURN_CODE WCMD_pause(void); RETURN_CODE WCMD_popd(void); void WCMD_print_error (void); -RETURN_CODE WCMD_pushd(const WCHAR *args); +RETURN_CODE WCMD_pushd(WCHAR *args); RETURN_CODE WCMD_remove_dir(WCHAR *command); RETURN_CODE WCMD_rename(void); RETURN_CODE WCMD_setlocal(WCHAR *args); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9881
even if Wine kernel APIs accept both '/' and '\\' in pathnames, always enforcing in cmd raises some other issues: * '/' is also used as the start of a (builtin) command option, so '/foo' can either be interpreted as unix absolute path /foo (expecting / to be mounted in Wine) or as option '/foo' * and '/' is interpreted as a separator in interactive prompr, not a part of a path * and native doesn't accept it as a path name did the error stem from interactive cmd usage or do you have an app which uses it? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9881#note_126900
On Wed Jan 14 08:22:37 2026 +0000, eric pouech wrote:
even if Wine kernel APIs accept both '/' and '\\' in pathnames, always enforcing in cmd raises some other issues: * '/' is also used as the start of a (builtin) command option, so '/foo' can either be interpreted as unix absolute path /foo (expecting / to be mounted in Wine) or as option '/foo' * and '/' is interpreted as a separator in interactive prompr, not a part of a path * and native doesn't accept it as a path name did the error stem from interactive cmd usage or do you have an app which uses it? In a batch script of an installer, there is a command `pushd "C:\Program Files\some path/"`. This works correctly on Windows. I have only modified the functions related to `pushd`, and the changes do not affect other parts of the code.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9881#note_126903
On Wed Jan 14 08:22:37 2026 +0000, Yeshun Ye wrote:
In a batch script of an installer, there is a command `pushd "C:\Program Files\some path/"`. This works correctly on Windows. I have only modified the functions related to `pushd`, and the changes do not affect other parts of the code. hmm native is even funkier than I ever thought
retested on native: `pushd c:/users` fails but `pushd "c:/users"` succeeds and `pushd "/users"` fails (even if on c: drive) this would require some more testings (as I fear this is not related to pushd but generic to all buitin commands), but it looks like current arg parsing code for builtin commands has to be revamped (it correctly stripes the ", but doesn't inform caller) as an example: `dir /users` fails with 'invalid switch' error, while `dir "/users"` succeeds (and lists `c:\users` directory) until we come up with a plan to a better interface to parse builin args, what you could do is: * use WCMD_parameter to get the argument (passing false to the unquote parameter) * and have different code paths (fail if not quoted and has a '/'; pass path after removing the quotes) * you could eventually also ensure that pushd is called with a single arg, which isn't done yet (but that's not mandatory) * and that would tests (to be added in success/failure parts of test_builtin.cmd and test_builtin.bat) -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9881#note_126912
On Wed Jan 14 09:34:50 2026 +0000, eric pouech wrote:
hmm native is even funkier than I ever thought retested on native: `pushd c:/users` fails but `pushd "c:/users"` succeeds and `pushd "/users"` fails (even if on c: drive) this would require some more testings (as I fear this is not related to pushd but generic to all buitin commands), but it looks like current arg parsing code for builtin commands has to be revamped (it correctly stripes the ", but doesn't inform caller) as an example: `dir /users` fails with 'invalid switch' error, while `dir "/users"` succeeds (and lists `c:\users` directory) until we come up with a plan to a better interface to parse builin args, what you could do is: * use WCMD_parameter to get the argument (passing false to the unquote parameter) * and have different code paths (fail if not quoted and has a '/'; pass path after removing the quotes) * you could eventually also ensure that pushd is called with a single arg, which isn't done yet (but that's not mandatory) * and that would tests (to be added in success/failure parts of test_builtin.cmd and test_builtin.bat) I've discovered that the behavior of `pushd` on Windows 7 is indeed quite complex. I need to conduct more tests to understand the rules behind how `pushd` handles quotes and `/`.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9881#note_127292
participants (3)
-
eric pouech (@epo) -
Yeshun Ye (@yeyeshun) -
YeshunYe