| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "build-defs.h" | ||
| 2 | #include <sys/stat.h> | ||
| 3 | #include "xdirent.h" | ||
| 4 | |||
| 5 | 53 | MaybeBool is_dir_or_symlink_to_dir(const struct dirent *ent, int dir_fd) | |
| 6 | { | ||
| 7 | // The dirent::d_type field is a Linux/BSD extension and may always | ||
| 8 | // be set to DT_UNKNOWN, depending on the filesystem. Thus, we need | ||
| 9 | // check if the platform supports it (at compile-time) and whether | ||
| 10 | // it provides useful information (at run-time). If either of these | ||
| 11 | // is lacking or symbolic link resolution is needed, an extra call | ||
| 12 | // to fstatat(3) is used as a fallback. | ||
| 13 | |||
| 14 | #if HAVE_DIRENT_D_TYPE | ||
| 15 |
2/3✓ Branch 2 → 3 taken 52 times.
✗ Branch 2 → 4 not taken.
✓ Branch 2 → 7 taken 1 time.
|
53 | switch (ent->d_type) { |
| 16 | case DT_UNKNOWN: break; // Extra syscall needed for type info | ||
| 17 | case DT_LNK: break; // Symlink (extra syscall needed to follow) | ||
| 18 | case DT_DIR: return MB_TRUE; // Definitely a directory | ||
| 19 | 52 | default: return MB_FALSE; // Definitely not a directory | |
| 20 | } | ||
| 21 | #endif | ||
| 22 | |||
| 23 | ✗ | struct stat st; | |
| 24 | ✗ | if (fstatat(dir_fd, ent->d_name, &st, 0) != 0) { | |
| 25 | // If fstatat(3) fails then no determination can be made, since | ||
| 26 | // `ent` could be e.g. a symlink to a directory that the calling | ||
| 27 | // user has insufficient permissions for (errno == EACCES) | ||
| 28 | return MB_INDETERMINATE; | ||
| 29 | } | ||
| 30 | |||
| 31 | ✗ | return S_ISDIR(st.st_mode) ? MB_TRUE : MB_FALSE; | |
| 32 | } | ||
| 33 |