diff options
author | Ron Yorston <rmy@pobox.com> | 2018-06-09 09:51:46 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2018-06-09 09:51:46 +0100 |
commit | 83f299376147a26436bc668ebcf0966a05010951 (patch) | |
tree | 4c5570695a931afa2a97f5769657fc096f5c20ec | |
parent | e6863d2959f6c85998b1bff5557e35f568332bc6 (diff) | |
download | busybox-w32-realpath.tar.gz busybox-w32-realpath.tar.bz2 busybox-w32-realpath.zip |
realpath: implement realpath(3) and enable realpath(1)realpath
The implementation of realpath(3) is based on code by Stuart Dootson
(studoot on GitHub).
-rw-r--r-- | configs/mingw32_defconfig | 2 | ||||
-rw-r--r-- | configs/mingw64_defconfig | 2 | ||||
-rw-r--r-- | win32/mingw.c | 59 |
3 files changed, 58 insertions, 5 deletions
diff --git a/configs/mingw32_defconfig b/configs/mingw32_defconfig index b0bdb25cb..249ae2072 100644 --- a/configs/mingw32_defconfig +++ b/configs/mingw32_defconfig | |||
@@ -288,7 +288,7 @@ CONFIG_PRINTF=y | |||
288 | CONFIG_PWD=y | 288 | CONFIG_PWD=y |
289 | # CONFIG_READLINK is not set | 289 | # CONFIG_READLINK is not set |
290 | # CONFIG_FEATURE_READLINK_FOLLOW is not set | 290 | # CONFIG_FEATURE_READLINK_FOLLOW is not set |
291 | # CONFIG_REALPATH is not set | 291 | CONFIG_REALPATH=y |
292 | CONFIG_RM=y | 292 | CONFIG_RM=y |
293 | CONFIG_RMDIR=y | 293 | CONFIG_RMDIR=y |
294 | CONFIG_SEQ=y | 294 | CONFIG_SEQ=y |
diff --git a/configs/mingw64_defconfig b/configs/mingw64_defconfig index 8cb8431d0..147e1e266 100644 --- a/configs/mingw64_defconfig +++ b/configs/mingw64_defconfig | |||
@@ -288,7 +288,7 @@ CONFIG_PRINTF=y | |||
288 | CONFIG_PWD=y | 288 | CONFIG_PWD=y |
289 | # CONFIG_READLINK is not set | 289 | # CONFIG_READLINK is not set |
290 | # CONFIG_FEATURE_READLINK_FOLLOW is not set | 290 | # CONFIG_FEATURE_READLINK_FOLLOW is not set |
291 | # CONFIG_REALPATH is not set | 291 | CONFIG_REALPATH=y |
292 | CONFIG_RM=y | 292 | CONFIG_RM=y |
293 | CONFIG_RMDIR=y | 293 | CONFIG_RMDIR=y |
294 | CONFIG_SEQ=y | 294 | CONFIG_SEQ=y |
diff --git a/win32/mingw.c b/win32/mingw.c index 8141e45a5..b75565fc2 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #include "libbb.h" | 1 | #include "libbb.h" |
2 | #include <userenv.h> | 2 | #include <userenv.h> |
3 | #include "lazyload.h" | ||
3 | 4 | ||
4 | #if defined(__MINGW64_VERSION_MAJOR) | 5 | #if defined(__MINGW64_VERSION_MAJOR) |
5 | #if ENABLE_GLOBBING | 6 | #if ENABLE_GLOBBING |
@@ -886,10 +887,63 @@ int link(const char *oldpath, const char *newpath) | |||
886 | return 0; | 887 | return 0; |
887 | } | 888 | } |
888 | 889 | ||
890 | static char *resolve_symlinks(char *path) | ||
891 | { | ||
892 | HANDLE h = INVALID_HANDLE_VALUE; | ||
893 | DECLARE_PROC_ADDR(kernel32.dll, DWORD, GetFinalPathNameByHandleA, HANDLE, | ||
894 | LPSTR, DWORD, DWORD); | ||
895 | |||
896 | if (!INIT_PROC_ADDR(GetFinalPathNameByHandleA)) { | ||
897 | errno = ENOSYS; | ||
898 | return NULL; | ||
899 | } | ||
900 | |||
901 | /* need a file handle to resolve symlinks */ | ||
902 | h = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, | ||
903 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, | ||
904 | NULL); | ||
905 | if (h != INVALID_HANDLE_VALUE) { | ||
906 | /* normalize the path and return it on success */ | ||
907 | DWORD status = GetFinalPathNameByHandleA(h, path, MAX_PATH, | ||
908 | FILE_NAME_NORMALIZED|VOLUME_NAME_DOS); | ||
909 | CloseHandle(h); | ||
910 | if (status != 0 && status < MAX_PATH) { | ||
911 | /* skip '\\?\' prefix */ | ||
912 | return (!strncmp(path, "\\\\?\\", 4)) ? (path + 4) : path; | ||
913 | } | ||
914 | } | ||
915 | |||
916 | errno = err_win_to_posix(GetLastError()); | ||
917 | return NULL; | ||
918 | } | ||
919 | |||
920 | /* | ||
921 | * Emulate realpath in two stages: | ||
922 | * | ||
923 | * - _fullpath handles './', '../' and extra '/' characters. The | ||
924 | * resulting path may not refer to an actual file. | ||
925 | * | ||
926 | * - resolve_symlinks checks that the file exists (by opening it) and | ||
927 | * resolves symlinks by calling GetFinalPathNameByHandleA. | ||
928 | */ | ||
889 | char *realpath(const char *path, char *resolved_path) | 929 | char *realpath(const char *path, char *resolved_path) |
890 | { | 930 | { |
891 | /* FIXME: need normalization */ | 931 | char buffer[MAX_PATH]; |
892 | return strcpy(resolved_path, path); | 932 | char *real_path; |
933 | |||
934 | /* enforce glibc pre-2.3 behaviour */ | ||
935 | if (path == NULL || resolved_path == NULL) { | ||
936 | errno = EINVAL; | ||
937 | return NULL; | ||
938 | } | ||
939 | |||
940 | if (_fullpath(buffer, path, MAX_PATH) && | ||
941 | (real_path=resolve_symlinks(buffer))) { | ||
942 | strcpy(resolved_path, real_path); | ||
943 | convert_slashes(resolved_path); | ||
944 | return resolved_path; | ||
945 | } | ||
946 | return NULL; | ||
893 | } | 947 | } |
894 | 948 | ||
895 | const char *get_busybox_exec_path(void) | 949 | const char *get_busybox_exec_path(void) |
@@ -1208,7 +1262,6 @@ off_t mingw_lseek(int fd, off_t offset, int whence) | |||
1208 | 1262 | ||
1209 | #if ENABLE_FEATURE_PS_TIME || ENABLE_FEATURE_PS_LONG | 1263 | #if ENABLE_FEATURE_PS_TIME || ENABLE_FEATURE_PS_LONG |
1210 | #undef GetTickCount64 | 1264 | #undef GetTickCount64 |
1211 | #include "lazyload.h" | ||
1212 | 1265 | ||
1213 | ULONGLONG CompatGetTickCount64(void) | 1266 | ULONGLONG CompatGetTickCount64(void) |
1214 | { | 1267 | { |