Stat a path, skipping symlinks. Returns 0 on success, -1 to skip. * On POSIX, lstat + S_ISLNK avoids following symlink cycles. On Windows * we use the UTF-8-safe wide stat (mirroring discover.c's wide_stat); * reparse points (junctions/symlinks) are detected separately by * pkgmap_is_reparse_point below before we descend. Mirrors discover.c's * safe_stat. */
| 782 | * pkgmap_is_reparse_point below before we descend. Mirrors discover.c's |
| 783 | * safe_stat. */ |
| 784 | static int pkgmap_safe_stat(const char *abs_path, struct stat *st) { |
| 785 | #ifdef _WIN32 |
| 786 | wchar_t *wpath = cbm_utf8_to_wide(abs_path); |
| 787 | if (!wpath) { |
| 788 | return CBM_NOT_FOUND; |
| 789 | } |
| 790 | struct _stat64 wst; |
| 791 | int ret = _wstat64(wpath, &wst); |
| 792 | free(wpath); |
| 793 | if (ret != 0) { |
| 794 | return CBM_NOT_FOUND; |
| 795 | } |
| 796 | st->st_mode = wst.st_mode; |
| 797 | st->st_size = wst.st_size; |
| 798 | st->st_mtime = wst.st_mtime; |
| 799 | return 0; |
| 800 | #else |
| 801 | if (lstat(abs_path, st) != 0) { |
| 802 | return CBM_NOT_FOUND; |
| 803 | } |
| 804 | if (S_ISLNK(st->st_mode)) { |
| 805 | return CBM_NOT_FOUND; |
| 806 | } |
| 807 | return 0; |
| 808 | #endif |
| 809 | } |
| 810 | |
| 811 | /* True if abs_path is a Windows reparse point (directory junction or |
| 812 | * symlink). Following these is the documented cause of the historic CI |
no test coverage detected