in src/libaducpal/src/ftw.c [94:210]
static int do_nftw(const char* path, NFTW_FUNC_T func, int nopenfd, int flags, int level)
{
int ret = 0;
DIR* dp = ADUCPAL_opendir(path);
if (dp == NULL)
{
return -1;
}
struct FTW ftwbuf = { 0 };
// level is the depth of fpath in the directory tree, relative to the root of the tree (dirpath, which has depth 0).
ftwbuf.level = level;
// base is the offset of the filename (i.e. basename component) in the pathname given in fpath.
ftwbuf.base = (int)strlen(path);
if (!(flags & FTW_DEPTH) && level == 0)
{
// Do an initial callback for the folder that was initially passed in
ret = do_callback(func, path, flags, &ftwbuf);
}
struct dirent* entry;
while ((entry = ADUCPAL_readdir(dp)) != NULL)
{
if (is_dots_dir(entry))
{
continue;
}
if (entry->d_type == DT_DIR)
{
if (flags & FTW_MOUNT)
{
WIN32_FILE_ATTRIBUTE_DATA wfd;
if (!GetFileAttributesEx(path, GetFileExInfoStandard, &wfd))
{
continue;
}
// If set, stay within the same filesystem (i.e., do not cross mount points).
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
{
continue;
}
}
ret = 0;
// Future optimization: remove subdir and filepath allocations; pass mutable buffer around
const size_t buffer_len = ftwbuf.base + 1 + entry->d_namlen + 1;
char* subdir = malloc(buffer_len);
sprintf_s(subdir, buffer_len, "%s/%s", path, entry->d_name);
// FTW_DEPTH
// If set, do a post-order traversal, that is, call fn() for the directory itself after handling the contents of the
// directory and its subdirectories. (By default, each directory is handled before its contents.)
if (flags & FTW_DEPTH)
{
ret = do_nftw(subdir, func, nopenfd, flags, level + 1);
if (ret != 0)
{
return ret;
}
}
if (ret == 0)
{
ret = do_callback(func, subdir, flags, &ftwbuf);
}
if (ret == 0)
{
if (!(flags & FTW_DEPTH))
{
ret = do_nftw(subdir, func, nopenfd, flags, level + 1);
}
}
free(subdir);
if (ret != 0)
{
return ret;
}
}
else if (entry->d_type == DT_REG)
{
const size_t buffer_len = ftwbuf.base + 1 + entry->d_namlen + 1;
char* filepath = malloc(buffer_len);
sprintf_s(filepath, buffer_len, "%s/%s", path, entry->d_name);
ret = do_callback(func, filepath, flags, &ftwbuf);
free(filepath);
if (ret != 0)
{
return ret;
}
}
}
if ((flags & FTW_DEPTH) && level == 0)
{
// Do a final callback for the folder that was initially passed in
ret = do_callback(func, path, flags, &ftwbuf);
}
if (dp != NULL)
{
ADUCPAL_closedir(dp);
}
return ret;
}