diff options
author | Ron Yorston <rmy@pobox.com> | 2018-12-06 15:16:49 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2018-12-06 15:16:49 +0000 |
commit | 9906faf2dff6fd9033cb711619528501cae11721 (patch) | |
tree | a85bb3ee78f5d58378f23842e0e762e879db23bc | |
parent | d257c7f2b6c44662c793d00d0b9286d6246b84a3 (diff) | |
download | busybox-w32-9906faf2dff6fd9033cb711619528501cae11721.tar.gz busybox-w32-9906faf2dff6fd9033cb711619528501cae11721.tar.bz2 busybox-w32-9906faf2dff6fd9033cb711619528501cae11721.zip |
win32: rework adding of extensions to filenames
Previously there was one function to handle adding extensions to
executable filenames, add_win32_extension(). Refactor this into
three functions:
add_win32_extension() appends the suffix to the argument string
in-place. The argument must be long enough to cope with this,
as is the case in ash where path_advance() adds 4 bytes to each
filename for just this reason.
alloc_win32_extension() is equivalent to the old add_win32_extension().
It allocates a string to hold the new filename then calls the new
add_win32_extension() function. The caller is responsible for
managing the returned string.
auto_win32_extension() calls alloc_win32_extension() and saves the
resulting string using auto_string(). It's used where the new
filename is consumed immediately or the actual value isn't needed.
Rewrite code to use the most appropriate function. Also reorder
some code in find_executable() and find_command().
-rw-r--r-- | debianutils/which.c | 3 | ||||
-rw-r--r-- | include/mingw.h | 11 | ||||
-rw-r--r-- | libbb/executable.c | 32 | ||||
-rw-r--r-- | shell/ash.c | 60 | ||||
-rw-r--r-- | win32/mingw.c | 52 | ||||
-rw-r--r-- | win32/process.c | 4 |
6 files changed, 64 insertions, 98 deletions
diff --git a/debianutils/which.c b/debianutils/which.c index 0b0a6a645..9b10b62f9 100644 --- a/debianutils/which.c +++ b/debianutils/which.c | |||
@@ -67,10 +67,9 @@ int which_main(int argc UNUSED_PARAM, char **argv) | |||
67 | /* If file contains a slash don't use PATH */ | 67 | /* If file contains a slash don't use PATH */ |
68 | if (strchr(*argv, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(*argv, '\\'))) { | 68 | if (strchr(*argv, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(*argv, '\\'))) { |
69 | #if ENABLE_PLATFORM_MINGW32 | 69 | #if ENABLE_PLATFORM_MINGW32 |
70 | if ((p=add_win32_extension(*argv)) != NULL) { | 70 | if ((p=auto_win32_extension(*argv)) != NULL) { |
71 | missing = 0; | 71 | missing = 0; |
72 | puts(p); | 72 | puts(p); |
73 | free(p); | ||
74 | } | 73 | } |
75 | else | 74 | else |
76 | #endif | 75 | #endif |
diff --git a/include/mingw.h b/include/mingw.h index 025c4e22b..543172075 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -457,7 +457,16 @@ void init_winsock(void); | |||
457 | int has_bat_suffix(const char *p); | 457 | int has_bat_suffix(const char *p); |
458 | int has_exe_suffix(const char *p); | 458 | int has_exe_suffix(const char *p); |
459 | int has_exe_suffix_or_dot(const char *name); | 459 | int has_exe_suffix_or_dot(const char *name); |
460 | char *add_win32_extension(const char *p); | 460 | char *alloc_win32_extension(const char *p); |
461 | int add_win32_extension(char *p); | ||
462 | |||
463 | static inline char *auto_win32_extension(const char *p) | ||
464 | { | ||
465 | extern char *auto_string(char *str) FAST_FUNC; | ||
466 | char *s = alloc_win32_extension(p); | ||
467 | return s ? auto_string(s) : NULL; | ||
468 | } | ||
469 | |||
461 | void FAST_FUNC convert_slashes(char *p); | 470 | void FAST_FUNC convert_slashes(char *p); |
462 | 471 | ||
463 | int err_win_to_posix(DWORD winerr); | 472 | int err_win_to_posix(DWORD winerr); |
diff --git a/libbb/executable.c b/libbb/executable.c index aec829945..835341ed9 100644 --- a/libbb/executable.c +++ b/libbb/executable.c | |||
@@ -28,10 +28,6 @@ int FAST_FUNC file_is_executable(const char *name) | |||
28 | * in all cases (*PATHp) contents are temporarily modified | 28 | * in all cases (*PATHp) contents are temporarily modified |
29 | * but are restored on return (s/:/NUL/ and back). | 29 | * but are restored on return (s/:/NUL/ and back). |
30 | */ | 30 | */ |
31 | #if !ENABLE_PLATFORM_MINGW32 | ||
32 | #define next_path_sep(s) strchr(s, ':') | ||
33 | #endif | ||
34 | |||
35 | char* FAST_FUNC find_executable(const char *filename, char **PATHp) | 31 | char* FAST_FUNC find_executable(const char *filename, char **PATHp) |
36 | { | 32 | { |
37 | /* About empty components in $PATH: | 33 | /* About empty components in $PATH: |
@@ -44,38 +40,32 @@ char* FAST_FUNC find_executable(const char *filename, char **PATHp) | |||
44 | */ | 40 | */ |
45 | char *p, *n; | 41 | char *p, *n; |
46 | #if ENABLE_PLATFORM_MINGW32 | 42 | #if ENABLE_PLATFORM_MINGW32 |
47 | char *w; | 43 | char sep, *w; |
48 | #endif | 44 | #endif |
49 | 45 | ||
50 | p = *PATHp; | 46 | p = *PATHp; |
51 | while (p) { | 47 | while (p) { |
52 | int ex; | 48 | int ex; |
53 | #if ENABLE_PLATFORM_MINGW32 | ||
54 | char sep; | ||
55 | 49 | ||
56 | n = (char*)next_path_sep(p); | 50 | #if !ENABLE_PLATFORM_MINGW32 |
57 | if (n) { | ||
58 | sep = *n; | ||
59 | *n = '\0'; | ||
60 | } | ||
61 | #else | ||
62 | n = strchr(p, ':'); | 51 | n = strchr(p, ':'); |
63 | if (n) *n = '\0'; | 52 | if (n) *n = '\0'; |
53 | #else | ||
54 | n = (char*)next_path_sep(p); | ||
55 | if (n) { sep = *n; *n = '\0'; } | ||
64 | #endif | 56 | #endif |
65 | p = concat_path_file( | 57 | p = concat_path_file( |
66 | p[0] ? p : ".", /* handle "::" case */ | 58 | p[0] ? p : ".", /* handle "::" case */ |
67 | filename | 59 | filename |
68 | ); | 60 | ); |
69 | #if ENABLE_PLATFORM_MINGW32 | 61 | #if !ENABLE_PLATFORM_MINGW32 |
70 | if (n) *n++ = sep; | ||
71 | #else | ||
72 | if (n) *n++ = ':'; | 62 | if (n) *n++ = ':'; |
73 | #endif | 63 | #else |
74 | #if ENABLE_PLATFORM_MINGW32 | 64 | if (n) *n++ = sep; |
75 | if ((w=add_win32_extension(p))) { | 65 | if ((w=alloc_win32_extension(p))) { |
76 | *PATHp = n; | ||
77 | free(p); | 66 | free(p); |
78 | return w; | 67 | p = w; |
68 | /* following test will succeed */ | ||
79 | } | 69 | } |
80 | #endif | 70 | #endif |
81 | ex = file_is_executable(p); | 71 | ex = file_is_executable(p); |
diff --git a/shell/ash.c b/shell/ash.c index cbe30a78b..587cf2abb 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -8405,7 +8405,7 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c | |||
8405 | 8405 | ||
8406 | #if ENABLE_PLATFORM_MINGW32 | 8406 | #if ENABLE_PLATFORM_MINGW32 |
8407 | { | 8407 | { |
8408 | char *new_cmd = add_win32_extension(cmd); | 8408 | char *new_cmd = alloc_win32_extension(cmd); |
8409 | execve(new_cmd ? new_cmd : cmd, argv, envp); | 8409 | execve(new_cmd ? new_cmd : cmd, argv, envp); |
8410 | free(new_cmd); | 8410 | free(new_cmd); |
8411 | } | 8411 | } |
@@ -8516,9 +8516,6 @@ printentry(struct tblentry *cmdp) | |||
8516 | int idx; | 8516 | int idx; |
8517 | const char *path; | 8517 | const char *path; |
8518 | char *name; | 8518 | char *name; |
8519 | #if ENABLE_PLATFORM_MINGW32 | ||
8520 | char *n; | ||
8521 | #endif | ||
8522 | 8519 | ||
8523 | idx = cmdp->param.index; | 8520 | idx = cmdp->param.index; |
8524 | path = pathval(); | 8521 | path = pathval(); |
@@ -8527,13 +8524,9 @@ printentry(struct tblentry *cmdp) | |||
8527 | stunalloc(name); | 8524 | stunalloc(name); |
8528 | } while (--idx >= 0); | 8525 | } while (--idx >= 0); |
8529 | #if ENABLE_PLATFORM_MINGW32 | 8526 | #if ENABLE_PLATFORM_MINGW32 |
8530 | if ((n=add_win32_extension(name)) != NULL) | 8527 | add_win32_extension(name); |
8531 | name = n; | ||
8532 | #endif | 8528 | #endif |
8533 | out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr)); | 8529 | out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr)); |
8534 | #if ENABLE_PLATFORM_MINGW32 | ||
8535 | free(n); | ||
8536 | #endif | ||
8537 | } | 8530 | } |
8538 | 8531 | ||
8539 | /* | 8532 | /* |
@@ -8921,9 +8914,6 @@ describe_command(char *command, const char *path, int describe_command_verbose) | |||
8921 | case CMDNORMAL: { | 8914 | case CMDNORMAL: { |
8922 | int j = entry.u.index; | 8915 | int j = entry.u.index; |
8923 | char *p; | 8916 | char *p; |
8924 | #if ENABLE_PLATFORM_MINGW32 | ||
8925 | char *q; | ||
8926 | #endif | ||
8927 | if (j < 0) { | 8917 | if (j < 0) { |
8928 | p = command; | 8918 | p = command; |
8929 | } else { | 8919 | } else { |
@@ -8933,17 +8923,13 @@ describe_command(char *command, const char *path, int describe_command_verbose) | |||
8933 | } while (--j >= 0); | 8923 | } while (--j >= 0); |
8934 | } | 8924 | } |
8935 | #if ENABLE_PLATFORM_MINGW32 | 8925 | #if ENABLE_PLATFORM_MINGW32 |
8936 | if ((q=add_win32_extension(p)) != NULL) | 8926 | add_win32_extension(p); |
8937 | p = q; | ||
8938 | #endif | 8927 | #endif |
8939 | if (describe_command_verbose) { | 8928 | if (describe_command_verbose) { |
8940 | out1fmt(" is %s", p); | 8929 | out1fmt(" is %s", p); |
8941 | } else { | 8930 | } else { |
8942 | out1str(p); | 8931 | out1str(p); |
8943 | } | 8932 | } |
8944 | #if ENABLE_PLATFORM_MINGW32 | ||
8945 | free(q); | ||
8946 | #endif | ||
8947 | break; | 8933 | break; |
8948 | } | 8934 | } |
8949 | 8935 | ||
@@ -13826,36 +13812,28 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
13826 | struct tblentry *cmdp; | 13812 | struct tblentry *cmdp; |
13827 | int idx; | 13813 | int idx; |
13828 | int prev; | 13814 | int prev; |
13829 | char *fullname IF_PLATFORM_MINGW32(= NULL); | 13815 | char *fullname; |
13830 | struct stat statb; | 13816 | struct stat statb; |
13831 | int e; | 13817 | int e; |
13832 | int updatetbl; | 13818 | int updatetbl; |
13833 | struct builtincmd *bcmd; | 13819 | struct builtincmd *bcmd; |
13834 | #if ENABLE_PLATFORM_MINGW32 | ||
13835 | extern const char win_suffix[4][4]; | ||
13836 | int i, len; | ||
13837 | #endif | ||
13838 | 13820 | ||
13839 | /* If name contains a slash, don't use PATH or hash table */ | 13821 | /* If name contains a slash, don't use PATH or hash table */ |
13840 | if (strchr(name, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(name, '\\'))) { | 13822 | if (strchr(name, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(name, '\\'))) { |
13841 | entry->u.index = -1; | 13823 | entry->u.index = -1; |
13842 | if (act & DO_ABS) { | 13824 | if (act & DO_ABS) { |
13843 | #if ENABLE_PLATFORM_MINGW32 | 13825 | #if ENABLE_PLATFORM_MINGW32 |
13844 | while ((fullname=add_win32_extension(name)) == NULL && | 13826 | if (auto_win32_extension(name) == NULL && stat(name, &statb) < 0) { |
13845 | stat(name, &statb) < 0 ) { | ||
13846 | #else | 13827 | #else |
13847 | while (stat(name, &statb) < 0) { | 13828 | while (stat(name, &statb) < 0) { |
13848 | #endif | ||
13849 | #ifdef SYSV | 13829 | #ifdef SYSV |
13850 | if (errno == EINTR) | 13830 | if (errno == EINTR) |
13851 | continue; | 13831 | continue; |
13852 | #endif | 13832 | #endif |
13833 | #endif | ||
13853 | entry->cmdtype = CMDUNKNOWN; | 13834 | entry->cmdtype = CMDUNKNOWN; |
13854 | return; | 13835 | return; |
13855 | } | 13836 | } |
13856 | #if ENABLE_PLATFORM_MINGW32 | ||
13857 | free(fullname); | ||
13858 | #endif | ||
13859 | } | 13837 | } |
13860 | entry->cmdtype = CMDNORMAL; | 13838 | entry->cmdtype = CMDNORMAL; |
13861 | return; | 13839 | return; |
@@ -13959,29 +13937,8 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
13959 | goto success; | 13937 | goto success; |
13960 | } | 13938 | } |
13961 | #if ENABLE_PLATFORM_MINGW32 | 13939 | #if ENABLE_PLATFORM_MINGW32 |
13962 | /* first try appending suffixes (unless there's one already) */ | 13940 | add_win32_extension(fullname); |
13963 | i = 4; | 13941 | #endif |
13964 | len = strlen(fullname); | ||
13965 | if (!has_exe_suffix_or_dot(fullname)) { | ||
13966 | /* path_advance() has reserved space for suffix */ | ||
13967 | fullname[len] = '.'; | ||
13968 | for (i=0; i<4; ++i) { | ||
13969 | memcpy(fullname+len+1, win_suffix[i], 4); | ||
13970 | if (stat(fullname, &statb) == 0) | ||
13971 | break; | ||
13972 | } | ||
13973 | } | ||
13974 | |||
13975 | if (i == 4) { | ||
13976 | /* adding a suffix failed (or wasn't tried), try original */ | ||
13977 | fullname[len] = '\0'; | ||
13978 | if (stat(fullname, &statb) < 0) { | ||
13979 | if (errno != ENOENT && errno != ENOTDIR) | ||
13980 | e = errno; | ||
13981 | goto loop; | ||
13982 | } | ||
13983 | } | ||
13984 | #else | ||
13985 | while (stat(fullname, &statb) < 0) { | 13942 | while (stat(fullname, &statb) < 0) { |
13986 | #ifdef SYSV | 13943 | #ifdef SYSV |
13987 | if (errno == EINTR) | 13944 | if (errno == EINTR) |
@@ -13991,7 +13948,6 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
13991 | e = errno; | 13948 | e = errno; |
13992 | goto loop; | 13949 | goto loop; |
13993 | } | 13950 | } |
13994 | #endif | ||
13995 | e = EACCES; /* if we fail, this will be the error */ | 13951 | e = EACCES; /* if we fail, this will be the error */ |
13996 | if (!S_ISREG(statb.st_mode)) | 13952 | if (!S_ISREG(statb.st_mode)) |
13997 | continue; | 13953 | continue; |
diff --git a/win32/mingw.c b/win32/mingw.c index 707e6a3d2..08d955527 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -1160,7 +1160,7 @@ int mingw_rmdir(const char *path) | |||
1160 | return rmdir(path); | 1160 | return rmdir(path); |
1161 | } | 1161 | } |
1162 | 1162 | ||
1163 | const char win_suffix[4][4] = { "com", "exe", "bat", "cmd" }; | 1163 | static const char win_suffix[4][4] = { "com", "exe", "bat", "cmd" }; |
1164 | 1164 | ||
1165 | static int has_win_suffix(const char *name, int start) | 1165 | static int has_win_suffix(const char *name, int start) |
1166 | { | 1166 | { |
@@ -1191,33 +1191,45 @@ int has_exe_suffix_or_dot(const char *name) | |||
1191 | return last_char_is(name, '.') || has_win_suffix(name, 0); | 1191 | return last_char_is(name, '.') || has_win_suffix(name, 0); |
1192 | } | 1192 | } |
1193 | 1193 | ||
1194 | /* check if path can be made into an executable by adding a suffix; | 1194 | /* Check if path can be made into an executable by adding a suffix. |
1195 | * return an allocated string containing the path if it can; | 1195 | * The suffix is added to the end of the argument which must be |
1196 | * return NULL if not. | 1196 | * long enough to allow this. |
1197 | * | 1197 | * |
1198 | * if path already has a suffix don't even bother trying | 1198 | * If the return value is TRUE the argument contains the new path, |
1199 | * if FALSE the argument is unchanged. | ||
1199 | */ | 1200 | */ |
1200 | char *add_win32_extension(const char *p) | 1201 | int add_win32_extension(char *p) |
1201 | { | 1202 | { |
1202 | char *path; | 1203 | if (!has_exe_suffix_or_dot(p)) { |
1203 | int i, len; | 1204 | int i, len = strlen(p); |
1204 | 1205 | ||
1205 | if (has_exe_suffix_or_dot(p)) { | 1206 | p[len] = '.'; |
1206 | return NULL; | 1207 | for (i=0; i<4; ++i) { |
1208 | memcpy(p+len+1, win_suffix[i], 4); | ||
1209 | if (file_is_executable(p)) | ||
1210 | return TRUE; | ||
1211 | } | ||
1212 | p[len] = '\0'; | ||
1207 | } | 1213 | } |
1214 | return FALSE; | ||
1215 | } | ||
1208 | 1216 | ||
1209 | len = strlen(p); | 1217 | /* Check if path can be made into an executable by adding a suffix. |
1210 | path = xasprintf("%s.com", p); | 1218 | * Return an allocated string containing the path if it can; |
1219 | * return NULL if not. | ||
1220 | * | ||
1221 | * If path already has a suffix don't even bother trying. | ||
1222 | */ | ||
1223 | char *alloc_win32_extension(const char *p) | ||
1224 | { | ||
1225 | if (!has_exe_suffix_or_dot(p)) { | ||
1226 | int len = strlen(p); | ||
1227 | char *path = strcpy(xmalloc(len+5), p); | ||
1211 | 1228 | ||
1212 | for (i=0; i<4; ++i) { | 1229 | if (add_win32_extension(path)) |
1213 | memcpy(path+len+1, win_suffix[i], 4); | ||
1214 | if (file_is_executable(path)) { | ||
1215 | return path; | 1230 | return path; |
1216 | } | 1231 | free(path); |
1217 | } | 1232 | } |
1218 | |||
1219 | free(path); | ||
1220 | |||
1221 | return NULL; | 1233 | return NULL; |
1222 | } | 1234 | } |
1223 | 1235 | ||
diff --git a/win32/process.c b/win32/process.c index e9b34b56d..b7f02e431 100644 --- a/win32/process.c +++ b/win32/process.c | |||
@@ -240,7 +240,7 @@ spawnveq(int mode, const char *path, char *const *argv, char *const *env) | |||
240 | p = strdup(new_argv[0]); | 240 | p = strdup(new_argv[0]); |
241 | } | 241 | } |
242 | else { | 242 | else { |
243 | p = add_win32_extension(new_argv[0]); | 243 | p = alloc_win32_extension(new_argv[0]); |
244 | } | 244 | } |
245 | 245 | ||
246 | if (p != NULL && has_bat_suffix(p)) { | 246 | if (p != NULL && has_bat_suffix(p)) { |
@@ -307,7 +307,7 @@ mingw_spawn_interpreter(int mode, const char *prog, char *const *argv, char *con | |||
307 | new_argv[nopts+1] = (char *)prog; /* pass absolute path */ | 307 | new_argv[nopts+1] = (char *)prog; /* pass absolute path */ |
308 | memcpy(new_argv+nopts+2, argv+1, sizeof(*argv)*argc); | 308 | memcpy(new_argv+nopts+2, argv+1, sizeof(*argv)*argc); |
309 | 309 | ||
310 | if ((fullpath=add_win32_extension(interp.path)) != NULL || | 310 | if ((fullpath=alloc_win32_extension(interp.path)) != NULL || |
311 | file_is_executable(interp.path)) { | 311 | file_is_executable(interp.path)) { |
312 | new_argv[0] = fullpath ? fullpath : interp.path; | 312 | new_argv[0] = fullpath ? fullpath : interp.path; |
313 | ret = spawnveq(mode, new_argv[0], new_argv, envp); | 313 | ret = spawnveq(mode, new_argv[0], new_argv, envp); |