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-31467ddfcbbc433ed9ceff2eae2a359d0ca1e6d5.tar.gz busybox-w32-31467ddfcbbc433ed9ceff2eae2a359d0ca1e6d5.tar.bz2 busybox-w32-31467ddfcbbc433ed9ceff2eae2a359d0ca1e6d5.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); |
