aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-10-13 16:22:21 +0100
committerRon Yorston <rmy@pobox.com>2021-10-13 16:44:45 +0100
commit4daf57b4fdc80422d6448c0a7914699fdedb95b8 (patch)
tree72930a54811bcebacd06bac0d67bcec6b1da677a
parent0ecf1aea459571b48dc68ddc2b7b9265740fa960 (diff)
downloadbusybox-w32-4daf57b4fdc80422d6448c0a7914699fdedb95b8.tar.gz
busybox-w32-4daf57b4fdc80422d6448c0a7914699fdedb95b8.tar.bz2
busybox-w32-4daf57b4fdc80422d6448c0a7914699fdedb95b8.zip
realpath: improved support for Windows paths
Upstream commit 94eb1c4dc (libbb: better coreutils compatibility for realpath) made some changes to xmalloc_realpath_coreutils(). This now needs to be updated to handle Windows paths. - Expose the macro is_unc_path() and part of the recent change to bb_get_last_path_component_nostrip() as a separate funtion, get_last_slash(); - Convert a couple of errors relating to network filesystems to ENOENT; - Adjust xmalloc_realpath_coreutils() to handle Windows directory separators, relative paths and UNC paths.
-rw-r--r--include/mingw.h3
-rw-r--r--libbb/get_last_path_component.c23
-rw-r--r--libbb/xreadlink.c34
-rw-r--r--win32/mingw.c5
4 files changed, 55 insertions, 10 deletions
diff --git a/include/mingw.h b/include/mingw.h
index 6ace91470..06fb3b289 100644
--- a/include/mingw.h
+++ b/include/mingw.h
@@ -518,6 +518,8 @@ int utimes(const char *file_name, const struct timeval times[2]);
518 * MinGW specific 518 * MinGW specific
519 */ 519 */
520#define is_dir_sep(c) ((c) == '/' || (c) == '\\') 520#define is_dir_sep(c) ((c) == '/' || (c) == '\\')
521#define is_unc_path(x) (strlen(x) > 4 && is_dir_sep(x[0]) && \
522 is_dir_sep(x[1]) && !is_dir_sep(x[2]))
521 523
522pid_t FAST_FUNC mingw_spawn(char **argv); 524pid_t FAST_FUNC mingw_spawn(char **argv);
523pid_t FAST_FUNC mingw_spawn_detach(char **argv); 525pid_t FAST_FUNC mingw_spawn_detach(char **argv);
@@ -580,3 +582,4 @@ int skip_ansi_emulation(int reset);
580int unix_path(const char *path); 582int unix_path(const char *path);
581int has_path(const char *file); 583int has_path(const char *file);
582int is_relative_path(const char *path); 584int is_relative_path(const char *path);
585char *get_last_slash(const char *path);
diff --git a/libbb/get_last_path_component.c b/libbb/get_last_path_component.c
index 06033e139..254aabafd 100644
--- a/libbb/get_last_path_component.c
+++ b/libbb/get_last_path_component.c
@@ -23,6 +23,21 @@ const char* FAST_FUNC bb_basename(const char *name)
23 return name; 23 return name;
24} 24}
25 25
26#if ENABLE_PLATFORM_MINGW32
27char *get_last_slash(const char *path)
28{
29 const char *start = path + root_len(path);
30 char *slash = strrchr(start, '/');
31 char *bslash = strrchr(start, '\\');
32
33 if (slash && bslash)
34 slash = MAX(slash, bslash);
35 else if (!slash)
36 slash = bslash;
37 return slash;
38}
39#endif
40
26/* 41/*
27 * "/" -> "/" 42 * "/" -> "/"
28 * "abc" -> "abc" 43 * "abc" -> "abc"
@@ -33,13 +48,7 @@ char* FAST_FUNC bb_get_last_path_component_nostrip(const char *path)
33{ 48{
34#if ENABLE_PLATFORM_MINGW32 49#if ENABLE_PLATFORM_MINGW32
35 const char *start = path + root_len(path); 50 const char *start = path + root_len(path);
36 char *slash = strrchr(start, '/'); 51 char *slash = get_last_slash(path);
37 char *bslash = strrchr(start, '\\');
38
39 if (slash && bslash)
40 slash = MAX(slash, bslash);
41 else if (!slash)
42 slash = bslash;
43 52
44 if (!slash && has_dos_drive_prefix(path) && path[2] != '\0') 53 if (!slash && has_dos_drive_prefix(path) && path[2] != '\0')
45 return (char *)path + 2; 54 return (char *)path + 2;
diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c
index 024ee9047..e6cf90310 100644
--- a/libbb/xreadlink.c
+++ b/libbb/xreadlink.c
@@ -156,7 +156,11 @@ char* FAST_FUNC xmalloc_realpath_coreutils(char *path)
156 * $ realpath symlink 156 * $ realpath symlink
157 * /usr/bin/qwe 157 * /usr/bin/qwe
158 */ 158 */
159#if ENABLE_PLATFORM_MINGW32
160 if (is_relative_path(target)) {
161#else
159 if (target[0] != '/') { 162 if (target[0] != '/') {
163#endif
160 /* 164 /*
161 * $ ln -s target_does_not_exist symlink 165 * $ ln -s target_does_not_exist symlink
162 * $ readlink -f symlink 166 * $ readlink -f symlink
@@ -175,6 +179,35 @@ char* FAST_FUNC xmalloc_realpath_coreutils(char *path)
175 return buf; 179 return buf;
176 } 180 }
177 181
182#if ENABLE_PLATFORM_MINGW32
183 /* ignore leading and trailing slashes */
184 /* but keep leading slashes of UNC path */
185 if (!is_unc_path(path)) {
186 while (is_dir_sep(path[0]) && is_dir_sep(path[1]))
187 ++path;
188 }
189 i = strlen(path) - 1;
190 while (i > 0 && is_dir_sep(path[i]))
191 i--;
192 c = path[i + 1];
193 path[i + 1] = '\0';
194
195 last_slash = get_last_slash(path);
196 if (last_slash == path + root_len(path))
197 buf = xstrdup(path);
198 else if (last_slash) {
199 char c2 = *last_slash;
200 *last_slash = '\0';
201 buf = xmalloc_realpath(path);
202 *last_slash++ = c2;
203 if (buf) {
204 unsigned len = strlen(buf);
205 buf = xrealloc(buf, len + strlen(last_slash) + 2);
206 buf[len++] = c2;
207 strcpy(buf + len, last_slash);
208 }
209 }
210#else
178 /* ignore leading and trailing slashes */ 211 /* ignore leading and trailing slashes */
179 while (path[0] == '/' && path[1] == '/') 212 while (path[0] == '/' && path[1] == '/')
180 ++path; 213 ++path;
@@ -198,6 +231,7 @@ char* FAST_FUNC xmalloc_realpath_coreutils(char *path)
198 strcpy(buf + len, last_slash); 231 strcpy(buf + len, last_slash);
199 } 232 }
200 } 233 }
234#endif
201 path[i + 1] = c; 235 path[i + 1] = c;
202 } 236 }
203 237
diff --git a/win32/mingw.c b/win32/mingw.c
index fa68ea608..d4855a7e7 100644
--- a/win32/mingw.c
+++ b/win32/mingw.c
@@ -64,6 +64,8 @@ int err_win_to_posix(void)
64 case ERROR_BAD_FORMAT: error = ENOEXEC; break; 64 case ERROR_BAD_FORMAT: error = ENOEXEC; break;
65 case ERROR_BAD_LENGTH: error = EINVAL; break; 65 case ERROR_BAD_LENGTH: error = EINVAL; break;
66 case ERROR_BAD_PATHNAME: error = ENOENT; break; 66 case ERROR_BAD_PATHNAME: error = ENOENT; break;
67 case ERROR_BAD_NET_NAME: error = ENOENT; break;
68 case ERROR_BAD_NETPATH: error = ENOENT; break;
67 case ERROR_BAD_PIPE: error = EPIPE; break; 69 case ERROR_BAD_PIPE: error = EPIPE; break;
68 case ERROR_BAD_UNIT: error = ENODEV; break; 70 case ERROR_BAD_UNIT: error = ENODEV; break;
69 case ERROR_BAD_USERNAME: error = EINVAL; break; 71 case ERROR_BAD_USERNAME: error = EINVAL; break;
@@ -1877,9 +1879,6 @@ void hide_console(void)
1877} 1879}
1878#endif 1880#endif
1879 1881
1880#define is_unc_path(x) (strlen(x) > 4 && is_dir_sep(x[0]) && \
1881 is_dir_sep(x[1]) && !is_dir_sep(x[2]))
1882
1883/* Return the length of the root of a UNC path, i.e. the '//host/share' 1882/* Return the length of the root of a UNC path, i.e. the '//host/share'
1884 * component, or 0 if the path doesn't look like that. */ 1883 * component, or 0 if the path doesn't look like that. */
1885int unc_root_len(const char *dir) 1884int unc_root_len(const char *dir)