diff options
author | Ron Yorston <rmy@pobox.com> | 2020-08-13 13:56:17 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2020-08-13 14:58:01 +0100 |
commit | 6059723900f2af1fbd394c457d1feae342e344f6 (patch) | |
tree | 146c10c821977a8af0942cc930d3a4550cf4a624 | |
parent | 7d639339e0c46311f8873d560e6f168e71473cd9 (diff) | |
download | busybox-w32-6059723900f2af1fbd394c457d1feae342e344f6.tar.gz busybox-w32-6059723900f2af1fbd394c457d1feae342e344f6.tar.bz2 busybox-w32-6059723900f2af1fbd394c457d1feae342e344f6.zip |
win32: handle Unix-style absolute paths for executables
As noted in commit 548ec7045 (win32: interpret absolute paths as
relative to %SYSTEMDRIVE%) a path starting with a '/' in the Unix
world is treated as relative to the current drive by Windows.
To avoid ambiguity that commit considered certain such paths to
be relative to %SYSTEMDRIVE%. Extend this to paths representing
executables.
Add the functions need_system_drive() and auto_add_system_drive()
to detect the need for a system drive prefix and to add it if
necessary. Use these functions in:
- the 'which' applet
- the find_executable() function
- tab-completion code
- PATH look-up, shellexec(), describe_command() and find_command() in ash
- parse_interpreter() and mingw_spawn_1()
With these changes executable paths starting with a slash are
handled consistently, whatever the current drive.
-rw-r--r-- | debianutils/which.c | 1 | ||||
-rw-r--r-- | include/mingw.h | 2 | ||||
-rw-r--r-- | libbb/executable.c | 3 | ||||
-rw-r--r-- | libbb/lineedit.c | 10 | ||||
-rw-r--r-- | shell/ash.c | 30 | ||||
-rw-r--r-- | win32/mingw.c | 15 | ||||
-rw-r--r-- | win32/process.c | 11 |
7 files changed, 68 insertions, 4 deletions
diff --git a/debianutils/which.c b/debianutils/which.c index 1f8c1a538..c8e99acda 100644 --- a/debianutils/which.c +++ b/debianutils/which.c | |||
@@ -71,6 +71,7 @@ int which_main(int argc UNUSED_PARAM, char **argv) | |||
71 | if (strchr(*argv, '/')) { | 71 | if (strchr(*argv, '/')) { |
72 | #else | 72 | #else |
73 | if (has_path(*argv)) { | 73 | if (has_path(*argv)) { |
74 | *argv = auto_add_system_drive(*argv); | ||
74 | if ((p=auto_win32_extension(*argv)) != NULL) { | 75 | if ((p=auto_win32_extension(*argv)) != NULL) { |
75 | missing = 0; | 76 | missing = 0; |
76 | puts(bs_to_slash(p)); | 77 | puts(bs_to_slash(p)); |
diff --git a/include/mingw.h b/include/mingw.h index 91e4dc1a5..434f3a474 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -547,6 +547,8 @@ void hide_console(void); | |||
547 | int unc_root_len(const char *dir); | 547 | int unc_root_len(const char *dir); |
548 | int root_len(const char *path); | 548 | int root_len(const char *path); |
549 | const char *get_system_drive(void); | 549 | const char *get_system_drive(void); |
550 | const char *need_system_drive(const char *path); | ||
551 | char *auto_add_system_drive(const char *path); | ||
550 | int chdir_system_drive(void); | 552 | int chdir_system_drive(void); |
551 | char *xabsolute_path(char *path); | 553 | char *xabsolute_path(char *path); |
552 | char *get_drive_cwd(const char *path, char *buffer, int size); | 554 | char *get_drive_cwd(const char *path, char *buffer, int size); |
diff --git a/libbb/executable.c b/libbb/executable.c index 87a40eeda..0a0769ef3 100644 --- a/libbb/executable.c +++ b/libbb/executable.c | |||
@@ -49,6 +49,9 @@ char* FAST_FUNC find_executable(const char *filename, char **PATHp) | |||
49 | 49 | ||
50 | n = strchr(p, PATH_SEP); | 50 | n = strchr(p, PATH_SEP); |
51 | if (n) *n = '\0'; | 51 | if (n) *n = '\0'; |
52 | #if ENABLE_PLATFORM_MINGW32 | ||
53 | p = auto_add_system_drive(p); | ||
54 | #endif | ||
52 | p = concat_path_file( | 55 | p = concat_path_file( |
53 | p[0] ? p : ".", /* handle "::" case */ | 56 | p[0] ? p : ".", /* handle "::" case */ |
54 | filename | 57 | filename |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index a36a1647d..f6577e372 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -913,8 +913,12 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
913 | struct dirent *next; | 913 | struct dirent *next; |
914 | struct stat st; | 914 | struct stat st; |
915 | char *found; | 915 | char *found; |
916 | 916 | #if ENABLE_PLATFORM_MINGW32 | |
917 | char *lpath = auto_add_system_drive(paths[i]); | ||
918 | dir = opendir(lpath); | ||
919 | #else | ||
917 | dir = opendir(paths[i]); | 920 | dir = opendir(paths[i]); |
921 | #endif | ||
918 | if (!dir) | 922 | if (!dir) |
919 | continue; /* don't print an error */ | 923 | continue; /* don't print an error */ |
920 | 924 | ||
@@ -929,7 +933,11 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
929 | if (!is_prefixed_with(name_found, pfind)) | 933 | if (!is_prefixed_with(name_found, pfind)) |
930 | continue; /* no */ | 934 | continue; /* no */ |
931 | 935 | ||
936 | #if ENABLE_PLATFORM_MINGW32 | ||
937 | found = concat_path_file(lpath, name_found); | ||
938 | #else | ||
932 | found = concat_path_file(paths[i], name_found); | 939 | found = concat_path_file(paths[i], name_found); |
940 | #endif | ||
933 | /* NB: stat() first so that we see is it a directory; | 941 | /* NB: stat() first so that we see is it a directory; |
934 | * but if that fails, use lstat() so that | 942 | * but if that fails, use lstat() so that |
935 | * we still match dangling links */ | 943 | * we still match dangling links */ |
diff --git a/shell/ash.c b/shell/ash.c index 7a2d0ab68..0a638b1df 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -2828,6 +2828,10 @@ padvance_magic(const char **path, const char *name, int magic) | |||
2828 | const char *start; | 2828 | const char *start; |
2829 | size_t qlen; | 2829 | size_t qlen; |
2830 | size_t len; | 2830 | size_t len; |
2831 | #if ENABLE_PLATFORM_MINGW32 | ||
2832 | size_t sdlen = 0; | ||
2833 | const char *sd; | ||
2834 | #endif | ||
2831 | 2835 | ||
2832 | if (*path == NULL) | 2836 | if (*path == NULL) |
2833 | return -1; | 2837 | return -1; |
@@ -2859,11 +2863,20 @@ padvance_magic(const char **path, const char *name, int magic) | |||
2859 | *path = *p == PATH_SEP ? p + 1 : NULL; | 2863 | *path = *p == PATH_SEP ? p + 1 : NULL; |
2860 | 2864 | ||
2861 | /* "2" is for '/' and '\0' */ | 2865 | /* "2" is for '/' and '\0' */ |
2862 | /* reserve space for suffix on WIN32 */ | 2866 | qlen = len + strlen(name) + 2; |
2863 | qlen = len + strlen(name) + 2 IF_PLATFORM_MINGW32(+ 4); | 2867 | #if ENABLE_PLATFORM_MINGW32 |
2868 | /* reserve space for system drive prefix and extension */ | ||
2869 | sd = need_system_drive(start); | ||
2870 | if (sd != NULL) | ||
2871 | sdlen = strlen(sd); | ||
2872 | qlen += 4 + sdlen; | ||
2873 | #endif | ||
2864 | q = growstackto(qlen); | 2874 | q = growstackto(qlen); |
2865 | 2875 | ||
2866 | if (len) { | 2876 | if (len) { |
2877 | #if ENABLE_PLATFORM_MINGW32 | ||
2878 | q = mempcpy(q, sd, sdlen); | ||
2879 | #endif | ||
2867 | q = mempcpy(q, start, len); | 2880 | q = mempcpy(q, start, len); |
2868 | #if ENABLE_PLATFORM_MINGW32 | 2881 | #if ENABLE_PLATFORM_MINGW32 |
2869 | if (q[-1] != '/' && q[-1] != '\\') | 2882 | if (q[-1] != '/' && q[-1] != '\\') |
@@ -8740,6 +8753,9 @@ static void shellexec(char *prog, char **argv, const char *path, int idx) | |||
8740 | || (applet_no = find_applet_by_name(prog)) >= 0 | 8753 | || (applet_no = find_applet_by_name(prog)) >= 0 |
8741 | #endif | 8754 | #endif |
8742 | ) { | 8755 | ) { |
8756 | #if ENABLE_PLATFORM_MINGW32 | ||
8757 | prog = auto_add_system_drive(prog); | ||
8758 | #endif | ||
8743 | tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp); | 8759 | tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp); |
8744 | if (applet_no >= 0) { | 8760 | if (applet_no >= 0) { |
8745 | /* We tried execing ourself, but it didn't work. | 8761 | /* We tried execing ourself, but it didn't work. |
@@ -9176,7 +9192,16 @@ describe_command(char *command, const char *path, int describe_command_verbose) | |||
9176 | int j = entry.u.index; | 9192 | int j = entry.u.index; |
9177 | char *p; | 9193 | char *p; |
9178 | if (j < 0) { | 9194 | if (j < 0) { |
9195 | #if ENABLE_PLATFORM_MINGW32 | ||
9196 | /* can't use auto_add_system_drive, need space for extension */ | ||
9197 | const char *sd = need_system_drive(command); | ||
9198 | size_t len = strlen(command) + 5 + (sd ? strlen(sd) : 0); | ||
9199 | |||
9200 | p = auto_string(xmalloc(len)); | ||
9201 | sprintf(p, "%s%s", sd ? sd : "", command); | ||
9202 | #else | ||
9179 | p = command; | 9203 | p = command; |
9204 | #endif | ||
9180 | } else { | 9205 | } else { |
9181 | do { | 9206 | do { |
9182 | padvance(&path, command); | 9207 | padvance(&path, command); |
@@ -14246,6 +14271,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
14246 | /* If name contains a slash, don't use PATH or hash table */ | 14271 | /* If name contains a slash, don't use PATH or hash table */ |
14247 | #if ENABLE_PLATFORM_MINGW32 | 14272 | #if ENABLE_PLATFORM_MINGW32 |
14248 | if (has_path(name)) { | 14273 | if (has_path(name)) { |
14274 | name = auto_add_system_drive(name); | ||
14249 | #else | 14275 | #else |
14250 | if (strchr(name, '/') != NULL) { | 14276 | if (strchr(name, '/') != NULL) { |
14251 | #endif | 14277 | #endif |
diff --git a/win32/mingw.c b/win32/mingw.c index 8501ecdd4..e63ffa0ac 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -1698,6 +1698,21 @@ const char *get_system_drive(void) | |||
1698 | return drive; | 1698 | return drive; |
1699 | } | 1699 | } |
1700 | 1700 | ||
1701 | /* Return pointer to system drive if path is of form '/file', else NULL */ | ||
1702 | const char *need_system_drive(const char *path) | ||
1703 | { | ||
1704 | if (root_len(path) == 0 && (path[0] == '/' || path[0] == '\\')) | ||
1705 | return get_system_drive(); | ||
1706 | return NULL; | ||
1707 | } | ||
1708 | |||
1709 | /* Add a system drive prefix to 'path' if necessary, else return 'path' */ | ||
1710 | char *auto_add_system_drive(const char *path) | ||
1711 | { | ||
1712 | const char *sd = need_system_drive(path); | ||
1713 | return sd ? auto_string(concat_path_file(sd, path)) : (char *)path; | ||
1714 | } | ||
1715 | |||
1701 | int chdir_system_drive(void) | 1716 | int chdir_system_drive(void) |
1702 | { | 1717 | { |
1703 | const char *sd = get_system_drive(); | 1718 | const char *sd = get_system_drive(); |
diff --git a/win32/process.c b/win32/process.c index 1118eb18a..cd164e0ed 100644 --- a/win32/process.c +++ b/win32/process.c | |||
@@ -63,6 +63,7 @@ static int | |||
63 | parse_interpreter(const char *cmd, interp_t *interp) | 63 | parse_interpreter(const char *cmd, interp_t *interp) |
64 | { | 64 | { |
65 | char *path, *t; | 65 | char *path, *t; |
66 | const char *sd; | ||
66 | int n; | 67 | int n; |
67 | 68 | ||
68 | while (TRUE) { | 69 | while (TRUE) { |
@@ -88,6 +89,12 @@ parse_interpreter(const char *cmd, interp_t *interp) | |||
88 | if (*t == '\0') | 89 | if (*t == '\0') |
89 | break; | 90 | break; |
90 | 91 | ||
92 | sd = need_system_drive(path); | ||
93 | if (sd && strlen(sd) == 2) { | ||
94 | path -= 2; | ||
95 | memcpy(path, sd, 2); | ||
96 | } | ||
97 | |||
91 | interp->path = path; | 98 | interp->path = path; |
92 | interp->name = t; | 99 | interp->name = t; |
93 | interp->opts = strtok(NULL, "\r\n"); | 100 | interp->opts = strtok(NULL, "\r\n"); |
@@ -342,6 +349,7 @@ static intptr_t | |||
342 | mingw_spawn_1(int mode, const char *cmd, char *const *argv, char *const *envp) | 349 | mingw_spawn_1(int mode, const char *cmd, char *const *argv, char *const *envp) |
343 | { | 350 | { |
344 | char *prog; | 351 | char *prog; |
352 | const char *path; | ||
345 | 353 | ||
346 | #if ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE | 354 | #if ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE |
347 | if (find_applet_by_name(cmd) >= 0) | 355 | if (find_applet_by_name(cmd) >= 0) |
@@ -349,7 +357,8 @@ mingw_spawn_1(int mode, const char *cmd, char *const *argv, char *const *envp) | |||
349 | else | 357 | else |
350 | #endif | 358 | #endif |
351 | if (has_path(cmd)) { | 359 | if (has_path(cmd)) { |
352 | const char *path = auto_win32_extension(cmd); | 360 | cmd = auto_add_system_drive(cmd); |
361 | path = auto_win32_extension(cmd); | ||
353 | return mingw_spawn_interpreter(mode, path ? path : cmd, argv, envp, 0); | 362 | return mingw_spawn_interpreter(mode, path ? path : cmd, argv, envp, 0); |
354 | } | 363 | } |
355 | else if ((prog=find_first_executable(cmd)) != NULL) { | 364 | else if ((prog=find_first_executable(cmd)) != NULL) { |