Stat a path, skipping symlinks (POSIX) and junctions / reparse points * (Windows). Returns 0 on success, -1 to skip. Skipping reparse points keeps * discovery from walking through a junction that points outside the project * root, mirroring the POSIX S_ISLNK skip. */
| 756 | * discovery from walking through a junction that points outside the project |
| 757 | * root, mirroring the POSIX S_ISLNK skip. */ |
| 758 | static int safe_stat(const char *abs_path, struct stat *st) { |
| 759 | #ifdef _WIN32 |
| 760 | wchar_t *wpath = cbm_path_to_wide(abs_path); |
| 761 | if (wpath) { |
| 762 | DWORD attr = GetFileAttributesW(wpath); |
| 763 | free(wpath); |
| 764 | if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_REPARSE_POINT)) { |
| 765 | return CBM_NOT_FOUND; |
| 766 | } |
| 767 | } |
| 768 | return wide_stat(abs_path, st); |
| 769 | #else |
| 770 | if (lstat(abs_path, st) != 0) { |
| 771 | return CBM_NOT_FOUND; |
| 772 | } |
| 773 | if (S_ISLNK(st->st_mode)) { |
| 774 | return CBM_NOT_FOUND; |
| 775 | } |
| 776 | return 0; |
| 777 | #endif |
| 778 | } |
| 779 | |
| 780 | /* Process a single regular file entry during directory walk. */ |
| 781 | static void walk_dir_process_file(const char *abs_path, const char *rel_path, const char *name, |
no test coverage detected