Skip to content

Commit

Permalink
crnlib: additional way to test if a path is a directory
Browse files Browse the repository at this point in the history
For some unknown reasons open() fails at this point on macOS
if the file is on a network file system and it is not in the
current directory, same with `stat()` and variants.

But opendir() works if the path is a directory, so let's assume
what is not a directory is a regular file. This assumption
may be wrong, this is why this guess is only done if two
other implementations failed to detect the file type first.
  • Loading branch information
illwieckz committed Jul 8, 2024
1 parent c6a5d46 commit d2e90f9
Showing 1 changed file with 38 additions and 7 deletions.
45 changes: 38 additions & 7 deletions crnlib/crn_find_files.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,24 +206,55 @@ bool find_files::find_internal(const char* pBasepath, const char* pRelpath, cons
if ((strcmp(ep->d_name, ".") == 0) || (strcmp(ep->d_name, "..") == 0))
continue;

bool is_directory = 0;
bool is_file = 0;
bool is_directory = false;
bool is_file = false;
bool guessed = false;

if ( ep->d_type != 0 ) {
/* This is the faster guess as it doesn't require any
extra IO as everything is already read. */
if (ep->d_type != 0) {
is_directory = (ep->d_type & DT_DIR) != 0;
is_file = (ep->d_type & DT_REG) != 0;
} else {
guessed = true;
}

/* Not all filesystems implement d_type which is optional,
especially network file systems and non-native ones.
See https://github.com/DaemonEngine/crunch/issues/37 */
if (!guessed) {
struct stat s;
if (stat(ep->d_name, &s) == 0) {
is_directory = S_ISDIR(s.st_mode);
is_file = S_ISREG(s.st_mode);
guessed = true;
}
else {
console::error("Cannot detect if given path is a file or a directory");
return false;
}

/* Some macOS and FreeBSD versions fail to open the file on NFS
if the file is not in the current directory when running crunch.
See https://github.com/DaemonEngine/crunch/issues/63 */
if (!guessed) {
DIR* df = opendir(ep->d_name);
if (df) {
is_directory = true;
guessed = true;
} else if (errno == ENOTDIR) {
// HACK: Assume it is a regular file if not a directory.
is_file = true;
guessed = true;
}
}

if (!guessed) {
console::error("Cannot detect if the given path is a file or a directory");
return false;
}

if (!is_file && !is_directory) {
console::error("The given path is not a file neither a directory");
return false;
}

dynamic_string filename(ep->d_name);

if (is_directory) {
Expand Down

0 comments on commit d2e90f9

Please sign in to comment.