aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2018-12-06 15:16:49 +0000
committerRon Yorston <rmy@pobox.com>2018-12-06 15:16:49 +0000
commit9906faf2dff6fd9033cb711619528501cae11721 (patch)
treea85bb3ee78f5d58378f23842e0e762e879db23bc
parentd257c7f2b6c44662c793d00d0b9286d6246b84a3 (diff)
downloadbusybox-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.c3
-rw-r--r--include/mingw.h11
-rw-r--r--libbb/executable.c32
-rw-r--r--shell/ash.c60
-rw-r--r--win32/mingw.c52
-rw-r--r--win32/process.c4
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);
457int has_bat_suffix(const char *p); 457int has_bat_suffix(const char *p);
458int has_exe_suffix(const char *p); 458int has_exe_suffix(const char *p);
459int has_exe_suffix_or_dot(const char *name); 459int has_exe_suffix_or_dot(const char *name);
460char *add_win32_extension(const char *p); 460char *alloc_win32_extension(const char *p);
461int add_win32_extension(char *p);
462
463static 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
461void FAST_FUNC convert_slashes(char *p); 470void FAST_FUNC convert_slashes(char *p);
462 471
463int err_win_to_posix(DWORD winerr); 472int 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
35char* FAST_FUNC find_executable(const char *filename, char **PATHp) 31char* 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
1163const char win_suffix[4][4] = { "com", "exe", "bat", "cmd" }; 1163static const char win_suffix[4][4] = { "com", "exe", "bat", "cmd" };
1164 1164
1165static int has_win_suffix(const char *name, int start) 1165static 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 */
1200char *add_win32_extension(const char *p) 1201int 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 */
1223char *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);