aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2022-05-22 15:59:34 +0100
committerRon Yorston <rmy@pobox.com>2022-05-22 15:59:34 +0100
commit09984ea741b455a4f86fe9e2022ae6ae4af9b4c4 (patch)
treef63d6b06785cb92d25af278fa7b8ed675d01b4c9
parent32de287bb714ff185d943090622b4cb64287dd78 (diff)
downloadbusybox-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.c13
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. */
1530ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) 1531ssize_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);