diff --git a/src/filesrch.c b/src/filesrch.c index eff1fef20..9c55cd008 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -428,9 +428,30 @@ filestatus_t filesearch(char *filename, const char *startpath, UINT64 wantedhash // okay, now we actually want searchpath to incorporate d_name strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name); - if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat +#if defined(__linux__) || defined(__FreeBSD__) + if (dent->d_type == DT_UNKNOWN && lstat(searchpath, &fsstat) == 0) + { + if (S_ISDIR(fsstat.st_mode)) + dent->d_type = DT_DIR; + else if (S_ISLNK(fsstat.st_mode)) + dent->d_type = DT_LNK; + } + + // Symlinks aren't always directory symlinks. Dunno if this would resolve recursive + // symlinks, but i think stat already does that + if (dent->d_type == DT_LNK && stat(searchpath, &fsstat) == 0 && !S_ISDIR(fsstat.st_mode)) + { + dent->d_type = DT_UNKNOWN; + } + + // Linux and FreeBSD has a special field for file type on dirent, so use that to speed up lookups. + // FIXME: should we also follow symlinks? + if ((dent->d_type == DT_DIR && depthleft) || (dent->d_type == DT_LNK && depthleft)) +#else + if (stat(searchpath, &fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat ; // was the file (re)moved? can't stat it else if (S_ISDIR(fsstat.st_mode) && depthleft) +#endif { searchpathindex[--depthleft] = strlen(searchpath) + 1; dirhandle[depthleft] = opendir(searchpath);