diff options
| author | Ron Yorston <rmy@pobox.com> | 2021-10-13 16:22:21 +0100 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2021-10-13 16:44:45 +0100 |
| commit | 4daf57b4fdc80422d6448c0a7914699fdedb95b8 (patch) | |
| tree | 72930a54811bcebacd06bac0d67bcec6b1da677a | |
| parent | 0ecf1aea459571b48dc68ddc2b7b9265740fa960 (diff) | |
| download | busybox-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.h | 3 | ||||
| -rw-r--r-- | libbb/get_last_path_component.c | 23 | ||||
| -rw-r--r-- | libbb/xreadlink.c | 34 | ||||
| -rw-r--r-- | win32/mingw.c | 5 |
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 | ||
| 522 | pid_t FAST_FUNC mingw_spawn(char **argv); | 524 | pid_t FAST_FUNC mingw_spawn(char **argv); |
| 523 | pid_t FAST_FUNC mingw_spawn_detach(char **argv); | 525 | pid_t FAST_FUNC mingw_spawn_detach(char **argv); |
| @@ -580,3 +582,4 @@ int skip_ansi_emulation(int reset); | |||
| 580 | int unix_path(const char *path); | 582 | int unix_path(const char *path); |
| 581 | int has_path(const char *file); | 583 | int has_path(const char *file); |
| 582 | int is_relative_path(const char *path); | 584 | int is_relative_path(const char *path); |
| 585 | char *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 | ||
| 27 | char *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. */ |
| 1885 | int unc_root_len(const char *dir) | 1884 | int unc_root_len(const char *dir) |
