diff options
author | Ron Yorston <rmy@pobox.com> | 2022-05-22 15:59:34 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2022-05-22 15:59:34 +0100 |
commit | 09984ea741b455a4f86fe9e2022ae6ae4af9b4c4 (patch) | |
tree | f63d6b06785cb92d25af278fa7b8ed675d01b4c9 | |
parent | 32de287bb714ff185d943090622b4cb64287dd78 (diff) | |
download | busybox-w32-09984ea741b455a4f86fe9e2022ae6ae4af9b4c4.tar.gz busybox-w32-09984ea741b455a4f86fe9e2022ae6ae4af9b4c4.tar.bz2 busybox-w32-09984ea741b455a4f86fe9e2022ae6ae4af9b4c4.zip |
win32: let stat(2) return correct st_size for symlink
Previously stat(2) set st_size to the length of the canonicalised
symlink target. Call readlink(2) to get the actual length of the
target string.
-rw-r--r-- | win32/mingw.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/win32/mingw.c b/win32/mingw.c index 95f5e5687..f49d8079d 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -630,6 +630,7 @@ static int do_lstat(int follow, const char *file_name, struct mingw_stat *buf) | |||
630 | WIN32_FIND_DATAA findbuf; | 630 | WIN32_FIND_DATAA findbuf; |
631 | DWORD low, high; | 631 | DWORD low, high; |
632 | off64_t size; | 632 | off64_t size; |
633 | ssize_t len; | ||
633 | #if ENABLE_FEATURE_EXTRA_FILE_DATA | 634 | #if ENABLE_FEATURE_EXTRA_FILE_DATA |
634 | DWORD flags; | 635 | DWORD flags; |
635 | BY_HANDLE_FILE_INFORMATION hdata; | 636 | BY_HANDLE_FILE_INFORMATION hdata; |
@@ -645,20 +646,19 @@ static int do_lstat(int follow, const char *file_name, struct mingw_stat *buf) | |||
645 | get_symlink_data(fdata.dwFileAttributes, file_name, &findbuf); | 646 | get_symlink_data(fdata.dwFileAttributes, file_name, &findbuf); |
646 | 647 | ||
647 | if (buf->st_tag) { | 648 | if (buf->st_tag) { |
648 | char *name = auto_string(xmalloc_realpath(file_name)); | ||
649 | |||
650 | if (follow) { | 649 | if (follow) { |
651 | /* The file size and times are wrong when Windows follows | 650 | /* The file size and times are wrong when Windows follows |
652 | * a symlink. Use the canonicalized path to try again. */ | 651 | * a symlink. Use the canonicalized path instead. */ |
653 | err = errno; | 652 | err = errno; |
654 | file_name = name; | 653 | file_name = auto_string(xmalloc_realpath(file_name)); |
655 | continue; | 654 | continue; |
656 | } | 655 | } |
657 | 656 | ||
658 | /* Get the contents of a symlink, not its target. */ | 657 | /* Get the contents of a symlink, not its target. */ |
659 | buf->st_mode = S_IFLNK|S_IRWXU|S_IRWXG|S_IRWXO; | 658 | buf->st_mode = S_IFLNK|S_IRWXU|S_IRWXG|S_IRWXO; |
660 | buf->st_attr = fdata.dwFileAttributes; | 659 | buf->st_attr = fdata.dwFileAttributes; |
661 | buf->st_size = name ? strlen(name) : 0; /* should use readlink */ | 660 | len = readlink(file_name, NULL, 0); |
661 | buf->st_size = len == -1 ? 0 : len; | ||
662 | buf->st_atim = filetime_to_timespec(&(findbuf.ftLastAccessTime)); | 662 | buf->st_atim = filetime_to_timespec(&(findbuf.ftLastAccessTime)); |
663 | buf->st_mtim = filetime_to_timespec(&(findbuf.ftLastWriteTime)); | 663 | buf->st_mtim = filetime_to_timespec(&(findbuf.ftLastWriteTime)); |
664 | buf->st_ctim = filetime_to_timespec(&(findbuf.ftCreationTime)); | 664 | buf->st_ctim = filetime_to_timespec(&(findbuf.ftCreationTime)); |
@@ -1527,6 +1527,7 @@ char *realpath(const char *path, char *resolved_path) | |||
1527 | } | 1527 | } |
1528 | 1528 | ||
1529 | #define SRPB rptr->SymbolicLinkReparseBuffer | 1529 | #define SRPB rptr->SymbolicLinkReparseBuffer |
1530 | /* Non-standard feature: if buf is NULL just return the length. */ | ||
1530 | ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) | 1531 | ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) |
1531 | { | 1532 | { |
1532 | HANDLE h; | 1533 | HANDLE h; |
@@ -1554,6 +1555,8 @@ ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) | |||
1554 | } | 1555 | } |
1555 | 1556 | ||
1556 | if (name) { | 1557 | if (name) { |
1558 | if (buf == NULL) | ||
1559 | return len; | ||
1557 | if (len > bufsiz) | 1560 | if (len > bufsiz) |
1558 | len = bufsiz; | 1561 | len = bufsiz; |
1559 | len = WideCharToMultiByte(CP_ACP, 0, name, len, buf, bufsiz, 0, 0); | 1562 | len = WideCharToMultiByte(CP_ACP, 0, name, len, buf, bufsiz, 0, 0); |