diff options
-rw-r--r-- | Config.in | 10 | ||||
-rw-r--r-- | configs/mingw32_defconfig | 8 | ||||
-rw-r--r-- | configs/mingw64_defconfig | 8 | ||||
-rw-r--r-- | coreutils/ls.c | 2 | ||||
-rw-r--r-- | coreutils/stat.c | 4 | ||||
-rw-r--r-- | include/mingw.h | 4 | ||||
-rw-r--r-- | win32/mingw.c | 65 |
7 files changed, 92 insertions, 9 deletions
@@ -473,6 +473,16 @@ config FEATURE_IDENTIFY_OWNER | |||
473 | Try to determine if files belong to the current user. If they don't | 473 | Try to determine if files belong to the current user. If they don't |
474 | they're listed as belonging to root. | 474 | they're listed as belonging to root. |
475 | 475 | ||
476 | config FEATURE_READLINK2 | ||
477 | bool "Read the contents of symbolic links (1.1 kb)" | ||
478 | default y | ||
479 | depends on PLATFORM_MINGW32 | ||
480 | help | ||
481 | Implement the readlink(2) system call to allow applets to read | ||
482 | the contents of symbolic links. With this feature ls and stat | ||
483 | can display the target of symbolic links and it makes sense to | ||
484 | enable the readlink applet. | ||
485 | |||
476 | comment 'Build Options' | 486 | comment 'Build Options' |
477 | 487 | ||
478 | config STATIC | 488 | config STATIC |
diff --git a/configs/mingw32_defconfig b/configs/mingw32_defconfig index c30ffa1b5..a29cc164a 100644 --- a/configs/mingw32_defconfig +++ b/configs/mingw32_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Busybox version: 1.31.0.git | 3 | # Busybox version: 1.31.0.git |
4 | # Fri Mar 1 08:50:17 2019 | 4 | # Wed Mar 6 09:32:59 2019 |
5 | # | 5 | # |
6 | CONFIG_HAVE_DOT_CONFIG=y | 6 | CONFIG_HAVE_DOT_CONFIG=y |
7 | # CONFIG_PLATFORM_POSIX is not set | 7 | # CONFIG_PLATFORM_POSIX is not set |
@@ -50,6 +50,7 @@ CONFIG_FEATURE_ICON_ALL=y | |||
50 | CONFIG_FEATURE_EURO=y | 50 | CONFIG_FEATURE_EURO=y |
51 | CONFIG_FEATURE_EXTRA_FILE_DATA=y | 51 | CONFIG_FEATURE_EXTRA_FILE_DATA=y |
52 | CONFIG_FEATURE_IDENTIFY_OWNER=y | 52 | CONFIG_FEATURE_IDENTIFY_OWNER=y |
53 | CONFIG_FEATURE_READLINK2=y | ||
53 | 54 | ||
54 | # | 55 | # |
55 | # Build Options | 56 | # Build Options |
@@ -295,8 +296,8 @@ CONFIG_PASTE=y | |||
295 | CONFIG_PRINTENV=y | 296 | CONFIG_PRINTENV=y |
296 | CONFIG_PRINTF=y | 297 | CONFIG_PRINTF=y |
297 | CONFIG_PWD=y | 298 | CONFIG_PWD=y |
298 | # CONFIG_READLINK is not set | 299 | CONFIG_READLINK=y |
299 | # CONFIG_FEATURE_READLINK_FOLLOW is not set | 300 | CONFIG_FEATURE_READLINK_FOLLOW=y |
300 | CONFIG_REALPATH=y | 301 | CONFIG_REALPATH=y |
301 | CONFIG_RM=y | 302 | CONFIG_RM=y |
302 | CONFIG_RMDIR=y | 303 | CONFIG_RMDIR=y |
@@ -1113,6 +1114,7 @@ CONFIG_ASH_HELP=y | |||
1113 | CONFIG_ASH_GETOPTS=y | 1114 | CONFIG_ASH_GETOPTS=y |
1114 | CONFIG_ASH_CMDCMD=y | 1115 | CONFIG_ASH_CMDCMD=y |
1115 | CONFIG_ASH_NOCONSOLE=y | 1116 | CONFIG_ASH_NOCONSOLE=y |
1117 | CONFIG_ASH_NOCASEGLOB=y | ||
1116 | # CONFIG_CTTYHACK is not set | 1118 | # CONFIG_CTTYHACK is not set |
1117 | # CONFIG_HUSH is not set | 1119 | # CONFIG_HUSH is not set |
1118 | # CONFIG_HUSH_BASH_COMPAT is not set | 1120 | # CONFIG_HUSH_BASH_COMPAT is not set |
diff --git a/configs/mingw64_defconfig b/configs/mingw64_defconfig index 46cb6941f..3d6102f0a 100644 --- a/configs/mingw64_defconfig +++ b/configs/mingw64_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Busybox version: 1.31.0.git | 3 | # Busybox version: 1.31.0.git |
4 | # Fri Mar 1 08:50:17 2019 | 4 | # Wed Mar 6 09:32:59 2019 |
5 | # | 5 | # |
6 | CONFIG_HAVE_DOT_CONFIG=y | 6 | CONFIG_HAVE_DOT_CONFIG=y |
7 | # CONFIG_PLATFORM_POSIX is not set | 7 | # CONFIG_PLATFORM_POSIX is not set |
@@ -50,6 +50,7 @@ CONFIG_FEATURE_ICON_ALL=y | |||
50 | CONFIG_FEATURE_EURO=y | 50 | CONFIG_FEATURE_EURO=y |
51 | CONFIG_FEATURE_EXTRA_FILE_DATA=y | 51 | CONFIG_FEATURE_EXTRA_FILE_DATA=y |
52 | CONFIG_FEATURE_IDENTIFY_OWNER=y | 52 | CONFIG_FEATURE_IDENTIFY_OWNER=y |
53 | CONFIG_FEATURE_READLINK2=y | ||
53 | 54 | ||
54 | # | 55 | # |
55 | # Build Options | 56 | # Build Options |
@@ -295,8 +296,8 @@ CONFIG_PASTE=y | |||
295 | CONFIG_PRINTENV=y | 296 | CONFIG_PRINTENV=y |
296 | CONFIG_PRINTF=y | 297 | CONFIG_PRINTF=y |
297 | CONFIG_PWD=y | 298 | CONFIG_PWD=y |
298 | # CONFIG_READLINK is not set | 299 | CONFIG_READLINK=y |
299 | # CONFIG_FEATURE_READLINK_FOLLOW is not set | 300 | CONFIG_FEATURE_READLINK_FOLLOW=y |
300 | CONFIG_REALPATH=y | 301 | CONFIG_REALPATH=y |
301 | CONFIG_RM=y | 302 | CONFIG_RM=y |
302 | CONFIG_RMDIR=y | 303 | CONFIG_RMDIR=y |
@@ -1113,6 +1114,7 @@ CONFIG_ASH_HELP=y | |||
1113 | CONFIG_ASH_GETOPTS=y | 1114 | CONFIG_ASH_GETOPTS=y |
1114 | CONFIG_ASH_CMDCMD=y | 1115 | CONFIG_ASH_CMDCMD=y |
1115 | CONFIG_ASH_NOCONSOLE=y | 1116 | CONFIG_ASH_NOCONSOLE=y |
1117 | CONFIG_ASH_NOCASEGLOB=y | ||
1116 | # CONFIG_CTTYHACK is not set | 1118 | # CONFIG_CTTYHACK is not set |
1117 | # CONFIG_HUSH is not set | 1119 | # CONFIG_HUSH is not set |
1118 | # CONFIG_HUSH_BASH_COMPAT is not set | 1120 | # CONFIG_HUSH_BASH_COMPAT is not set |
diff --git a/coreutils/ls.c b/coreutils/ls.c index c5402de30..6be3eb291 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c | |||
@@ -492,7 +492,7 @@ static NOINLINE unsigned display_single(const struct dnode *dn) | |||
492 | /* Do readlink early, so that if it fails, error message | 492 | /* Do readlink early, so that if it fails, error message |
493 | * does not appear *inside* the "ls -l" line */ | 493 | * does not appear *inside* the "ls -l" line */ |
494 | lpath = NULL; | 494 | lpath = NULL; |
495 | #if !ENABLE_PLATFORM_MINGW32 | 495 | #if ENABLE_PLATFORM_POSIX || ENABLE_FEATURE_READLINK2 |
496 | if (opt & OPT_l) | 496 | if (opt & OPT_l) |
497 | if (S_ISLNK(dn->dn_mode)) | 497 | if (S_ISLNK(dn->dn_mode)) |
498 | lpath = xmalloc_readlink_or_warn(dn->fullname); | 498 | lpath = xmalloc_readlink_or_warn(dn->fullname); |
diff --git a/coreutils/stat.c b/coreutils/stat.c index 32bc5e2d3..cf13af0b6 100644 --- a/coreutils/stat.c +++ b/coreutils/stat.c | |||
@@ -317,7 +317,7 @@ static void FAST_FUNC print_stat(char *pformat, const char m, | |||
317 | printfs(pformat, filename); | 317 | printfs(pformat, filename); |
318 | } else if (m == 'N') { | 318 | } else if (m == 'N') { |
319 | strcatc(pformat, 's'); | 319 | strcatc(pformat, 's'); |
320 | #if !ENABLE_PLATFORM_MINGW32 | 320 | #if ENABLE_PLATFORM_POSIX || ENABLE_FEATURE_READLINK2 |
321 | if (S_ISLNK(statbuf->st_mode)) { | 321 | if (S_ISLNK(statbuf->st_mode)) { |
322 | char *linkname = xmalloc_readlink_or_warn(filename); | 322 | char *linkname = xmalloc_readlink_or_warn(filename); |
323 | if (linkname == NULL) | 323 | if (linkname == NULL) |
@@ -712,7 +712,7 @@ static bool do_stat(const char *filename, const char *format) | |||
712 | gw_ent = getgrgid(statbuf.st_gid); | 712 | gw_ent = getgrgid(statbuf.st_gid); |
713 | pw_ent = getpwuid(statbuf.st_uid); | 713 | pw_ent = getpwuid(statbuf.st_uid); |
714 | 714 | ||
715 | #if !ENABLE_PLATFORM_MINGW32 | 715 | #if ENABLE_PLATFORM_POSIX || ENABLE_FEATURE_READLINK2 |
716 | if (S_ISLNK(statbuf.st_mode)) | 716 | if (S_ISLNK(statbuf.st_mode)) |
717 | linkname = xmalloc_readlink_or_warn(filename); | 717 | linkname = xmalloc_readlink_or_warn(filename); |
718 | if (linkname) { | 718 | if (linkname) { |
diff --git a/include/mingw.h b/include/mingw.h index 188d4eecf..b5324e49b 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -407,7 +407,11 @@ int mingw_xopen(const char *filename, int oflags); | |||
407 | ssize_t mingw_read(int fd, void *buf, size_t count); | 407 | ssize_t mingw_read(int fd, void *buf, size_t count); |
408 | int mingw_close(int fd); | 408 | int mingw_close(int fd); |
409 | int pipe(int filedes[2]); | 409 | int pipe(int filedes[2]); |
410 | #if ENABLE_FEATURE_READLINK2 | ||
411 | ssize_t readlink(const char *pathname, char *buf, size_t bufsiz); | ||
412 | #else | ||
410 | NOIMPL(readlink,const char *path UNUSED_PARAM, char *buf UNUSED_PARAM, size_t bufsiz UNUSED_PARAM); | 413 | NOIMPL(readlink,const char *path UNUSED_PARAM, char *buf UNUSED_PARAM, size_t bufsiz UNUSED_PARAM); |
414 | #endif | ||
411 | NOIMPL(setgid,gid_t gid UNUSED_PARAM); | 415 | NOIMPL(setgid,gid_t gid UNUSED_PARAM); |
412 | NOIMPL(setegid,gid_t gid UNUSED_PARAM); | 416 | NOIMPL(setegid,gid_t gid UNUSED_PARAM); |
413 | NOIMPL(setsid,void); | 417 | NOIMPL(setsid,void); |
diff --git a/win32/mingw.c b/win32/mingw.c index dda2e9a60..c42dbed97 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -4,6 +4,9 @@ | |||
4 | #if ENABLE_FEATURE_IDENTIFY_OWNER | 4 | #if ENABLE_FEATURE_IDENTIFY_OWNER |
5 | #include <aclapi.h> | 5 | #include <aclapi.h> |
6 | #endif | 6 | #endif |
7 | #if ENABLE_FEATURE_READLINK2 | ||
8 | #include <ntdef.h> | ||
9 | #endif | ||
7 | 10 | ||
8 | #if defined(__MINGW64_VERSION_MAJOR) | 11 | #if defined(__MINGW64_VERSION_MAJOR) |
9 | #if ENABLE_GLOBBING | 12 | #if ENABLE_GLOBBING |
@@ -1060,6 +1063,68 @@ char *realpath(const char *path, char *resolved_path) | |||
1060 | return NULL; | 1063 | return NULL; |
1061 | } | 1064 | } |
1062 | 1065 | ||
1066 | #if ENABLE_FEATURE_READLINK2 | ||
1067 | static wchar_t *normalize_ntpath(wchar_t *wbuf) | ||
1068 | { | ||
1069 | int i; | ||
1070 | /* fix absolute path prefixes */ | ||
1071 | if (wbuf[0] == '\\') { | ||
1072 | /* strip NT namespace prefixes */ | ||
1073 | if (!wcsncmp(wbuf, L"\\??\\", 4) || | ||
1074 | !wcsncmp(wbuf, L"\\\\?\\", 4)) | ||
1075 | wbuf += 4; | ||
1076 | else if (!wcsnicmp(wbuf, L"\\DosDevices\\", 12)) | ||
1077 | wbuf += 12; | ||
1078 | /* replace remaining '...UNC\' with '\\' */ | ||
1079 | if (!wcsnicmp(wbuf, L"UNC\\", 4)) { | ||
1080 | wbuf += 2; | ||
1081 | *wbuf = '\\'; | ||
1082 | } | ||
1083 | } | ||
1084 | /* convert backslashes to slashes */ | ||
1085 | for (i = 0; wbuf[i]; i++) | ||
1086 | if (wbuf[i] == '\\') | ||
1087 | wbuf[i] = '/'; | ||
1088 | return wbuf; | ||
1089 | } | ||
1090 | |||
1091 | #define SRPB rptr->SymbolicLinkReparseBuffer | ||
1092 | ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) | ||
1093 | { | ||
1094 | HANDLE h; | ||
1095 | |||
1096 | h = CreateFile(pathname, 0, 0, NULL, OPEN_EXISTING, | ||
1097 | FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL); | ||
1098 | if (h != INVALID_HANDLE_VALUE) { | ||
1099 | DWORD nbytes; | ||
1100 | BYTE rbuf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; | ||
1101 | PREPARSE_DATA_BUFFER rptr = (PREPARSE_DATA_BUFFER)rbuf; | ||
1102 | BOOL status; | ||
1103 | |||
1104 | status = DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, | ||
1105 | rptr, sizeof(rbuf), &nbytes, NULL); | ||
1106 | CloseHandle(h); | ||
1107 | |||
1108 | if (status && rptr->ReparseTag == IO_REPARSE_TAG_SYMLINK) { | ||
1109 | size_t len = SRPB.SubstituteNameLength/sizeof(WCHAR); | ||
1110 | WCHAR *name = SRPB.PathBuffer + | ||
1111 | SRPB.SubstituteNameOffset/sizeof(WCHAR); | ||
1112 | |||
1113 | name[len] = 0; | ||
1114 | name = normalize_ntpath(name); | ||
1115 | len = wcslen(name); | ||
1116 | if (len > bufsiz) | ||
1117 | len = bufsiz; | ||
1118 | if (WideCharToMultiByte(CP_ACP, 0, name, len, buf, bufsiz, 0, 0)) { | ||
1119 | return len; | ||
1120 | } | ||
1121 | } | ||
1122 | } | ||
1123 | errno = err_win_to_posix(); | ||
1124 | return -1; | ||
1125 | } | ||
1126 | #endif | ||
1127 | |||
1063 | const char *get_busybox_exec_path(void) | 1128 | const char *get_busybox_exec_path(void) |
1064 | { | 1129 | { |
1065 | static char *path = NULL; | 1130 | static char *path = NULL; |