diff options
author | Ron Yorston <rmy@pobox.com> | 2022-05-23 15:10:49 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2022-05-23 15:25:00 +0100 |
commit | 31467ddfcbbc433ed9ceff2eae2a359d0ca1e6d5 (patch) | |
tree | 6d9a94cbe34a04972b01d41529fe74ea5d3da59c | |
parent | 70c17b9fc0b9052b757603f7d139f898eb92606e (diff) | |
download | busybox-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.c | 37 |
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 | */ |
626 | static int do_lstat(int follow, const char *file_name, struct mingw_stat *buf) | 626 | static 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. */ | ||
1528 | ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) | 1537 | ssize_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); |