summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2022-05-23 15:10:49 +0100
committerRon Yorston <rmy@pobox.com>2022-05-23 15:25:00 +0100
commit31467ddfcbbc433ed9ceff2eae2a359d0ca1e6d5 (patch)
tree6d9a94cbe34a04972b01d41529fe74ea5d3da59c
parent70c17b9fc0b9052b757603f7d139f898eb92606e (diff)
downloadbusybox-w32-FRP-4716-g31467ddfc.tar.gz
busybox-w32-FRP-4716-g31467ddfc.tar.bz2
busybox-w32-FRP-4716-g31467ddfc.zip
win32: changes to stat(2) implementationFRP-4716-g31467ddfc
- Use repeated calls to readlink(2) rather than xmalloc_realpath() when asked to follow symlinks. - Drop the non-standard feature that caused readlink(2) to return only the target string length. This improves compatibility with BusyBox on Linux at a cost of 16-32 bytes.
-rw-r--r--win32/mingw.c37
1 files changed, 22 insertions, 15 deletions
diff --git a/win32/mingw.c b/win32/mingw.c
index 01d935eb9..72165cdd7 100644
--- a/win32/mingw.c
+++ b/win32/mingw.c
@@ -625,40 +625,51 @@ static int count_subdirs(const char *pathname)
625 */ 625 */
626static int do_lstat(int follow, const char *file_name, struct mingw_stat *buf) 626static int do_lstat(int follow, const char *file_name, struct mingw_stat *buf)
627{ 627{
628 int err = EINVAL; 628 int err;
629 WIN32_FILE_ATTRIBUTE_DATA fdata; 629 WIN32_FILE_ATTRIBUTE_DATA fdata;
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 char lname[PATH_MAX];
634#if ENABLE_FEATURE_EXTRA_FILE_DATA 634#if ENABLE_FEATURE_EXTRA_FILE_DATA
635 DWORD flags; 635 DWORD flags;
636 BY_HANDLE_FILE_INFORMATION hdata; 636 BY_HANDLE_FILE_INFORMATION hdata;
637 HANDLE fh; 637 HANDLE fh;
638#endif 638#endif
639 639
640 while (file_name && !(err=get_file_attr(file_name, &fdata))) { 640 while (!(err=get_file_attr(file_name, &fdata))) {
641 buf->st_ino = 0; 641 buf->st_ino = 0;
642 buf->st_uid = DEFAULT_UID; 642 buf->st_uid = DEFAULT_UID;
643 buf->st_gid = DEFAULT_GID; 643 buf->st_gid = DEFAULT_GID;
644 buf->st_dev = buf->st_rdev = 0; 644 buf->st_dev = buf->st_rdev = 0;
645 buf->st_tag = 645 buf->st_attr = fdata.dwFileAttributes;
646 get_symlink_data(fdata.dwFileAttributes, file_name, &findbuf); 646 buf->st_tag = get_symlink_data(buf->st_attr, file_name, &findbuf);
647 647
648 if (buf->st_tag) { 648 if (buf->st_tag) {
649 ssize_t len = readlink(file_name, lname, PATH_MAX);
650 if (len < 0) {
651 err = errno;
652 break;
653 } else if (len == PATH_MAX) {
654 errno = ENAMETOOLONG;
655 break;
656 }
657
649 if (follow) { 658 if (follow) {
650 /* The file size and times are wrong when Windows follows 659 /* The file size and times are wrong when Windows follows
651 * a symlink. Use the canonicalized path instead. */ 660 * a symlink. Use the symlink target instead. */
652 err = errno; 661 if (follow++ > MAXSYMLINKS) {
653 file_name = auto_string(xmalloc_realpath(file_name)); 662 err = ELOOP;
663 break;
664 }
665 lname[len] = '\0';
666 file_name = lname;
654 continue; 667 continue;
655 } 668 }
656 669
657 /* Get the contents of a symlink, not its target. */ 670 /* Get the contents of a symlink, not its target. */
658 buf->st_mode = S_IFLNK|S_IRWXU|S_IRWXG|S_IRWXO; 671 buf->st_mode = S_IFLNK|S_IRWXU|S_IRWXG|S_IRWXO;
659 buf->st_attr = fdata.dwFileAttributes; 672 buf->st_size = len;
660 len = readlink(file_name, NULL, 0);
661 buf->st_size = len == -1 ? 0 : len;
662 buf->st_atim = filetime_to_timespec(&(findbuf.ftLastAccessTime)); 673 buf->st_atim = filetime_to_timespec(&(findbuf.ftLastAccessTime));
663 buf->st_mtim = filetime_to_timespec(&(findbuf.ftLastWriteTime)); 674 buf->st_mtim = filetime_to_timespec(&(findbuf.ftLastWriteTime));
664 buf->st_ctim = filetime_to_timespec(&(findbuf.ftCreationTime)); 675 buf->st_ctim = filetime_to_timespec(&(findbuf.ftCreationTime));
@@ -666,7 +677,6 @@ static int do_lstat(int follow, const char *file_name, struct mingw_stat *buf)
666 else { 677 else {
667 /* The file is not a symlink. */ 678 /* The file is not a symlink. */
668 buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes); 679 buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
669 buf->st_attr = fdata.dwFileAttributes;
670 if (S_ISREG(buf->st_mode) && 680 if (S_ISREG(buf->st_mode) &&
671 !(buf->st_attr & FILE_ATTRIBUTE_DEVICE) && 681 !(buf->st_attr & FILE_ATTRIBUTE_DEVICE) &&
672 (has_exe_suffix(file_name) || has_exec_format(file_name))) 682 (has_exe_suffix(file_name) || has_exec_format(file_name)))
@@ -1524,7 +1534,6 @@ char *realpath(const char *path, char *resolved_path)
1524} 1534}
1525 1535
1526#define SRPB rptr->SymbolicLinkReparseBuffer 1536#define SRPB rptr->SymbolicLinkReparseBuffer
1527/* Non-standard feature: if buf is NULL just return the length. */
1528ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) 1537ssize_t readlink(const char *pathname, char *buf, size_t bufsiz)
1529{ 1538{
1530 HANDLE h; 1539 HANDLE h;
@@ -1552,8 +1561,6 @@ ssize_t readlink(const char *pathname, char *buf, size_t bufsiz)
1552 } 1561 }
1553 1562
1554 if (name) { 1563 if (name) {
1555 if (buf == NULL)
1556 return len;
1557 if (len > bufsiz) 1564 if (len > bufsiz)
1558 len = bufsiz; 1565 len = bufsiz;
1559 len = WideCharToMultiByte(CP_ACP, 0, name, len, buf, bufsiz, 0, 0); 1566 len = WideCharToMultiByte(CP_ACP, 0, name, len, buf, bufsiz, 0, 0);