aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2020-08-13 13:56:17 +0100
committerRon Yorston <rmy@pobox.com>2020-08-13 14:58:01 +0100
commit6059723900f2af1fbd394c457d1feae342e344f6 (patch)
tree146c10c821977a8af0942cc930d3a4550cf4a624
parent7d639339e0c46311f8873d560e6f168e71473cd9 (diff)
downloadbusybox-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.c1
-rw-r--r--include/mingw.h2
-rw-r--r--libbb/executable.c3
-rw-r--r--libbb/lineedit.c10
-rw-r--r--shell/ash.c30
-rw-r--r--win32/mingw.c15
-rw-r--r--win32/process.c11
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);
547int unc_root_len(const char *dir); 547int unc_root_len(const char *dir);
548int root_len(const char *path); 548int root_len(const char *path);
549const char *get_system_drive(void); 549const char *get_system_drive(void);
550const char *need_system_drive(const char *path);
551char *auto_add_system_drive(const char *path);
550int chdir_system_drive(void); 552int chdir_system_drive(void);
551char *xabsolute_path(char *path); 553char *xabsolute_path(char *path);
552char *get_drive_cwd(const char *path, char *buffer, int size); 554char *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 */
1702const 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' */
1710char *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
1701int chdir_system_drive(void) 1716int 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
63parse_interpreter(const char *cmd, interp_t *interp) 63parse_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
342mingw_spawn_1(int mode, const char *cmd, char *const *argv, char *const *envp) 349mingw_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) {