static int do_nftw()

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;
}