mirror of
https://github.com/trapexit/mergerfs.git
synced 2026-10-26 19:01:56 -04:00
Some checks are pending
mkdocs / deploy (push) Waiting to run
Run in an elevated credential mode (root) and let the kernel manage entitlements. Will result in slightly different behavior but should not be noticed by most.
118 lines
2.3 KiB
Text
118 lines
2.3 KiB
Text
#pragma message "using readdir"
|
|
|
|
#include "error.hpp"
|
|
#include "fs_closedir.hpp"
|
|
#include "fs_inode.hpp"
|
|
#include "fs_opendir.hpp"
|
|
#include "fs_readdir.hpp"
|
|
#include "hashset.hpp"
|
|
#include "scope_guard.hpp"
|
|
#include "ugid.hpp"
|
|
|
|
#include "fuse_dirents.hpp"
|
|
|
|
|
|
struct DirRV
|
|
{
|
|
const fs::path *branch_path;
|
|
DIR *dir;
|
|
int err;
|
|
};
|
|
|
|
static
|
|
uint64_t
|
|
_dirent_exact_namelen(const struct dirent *d_)
|
|
{
|
|
#ifdef _D_EXACT_NAMLEN
|
|
return _D_EXACT_NAMLEN(d_);
|
|
#elif defined _DIRENT_HAVE_D_NAMLEN
|
|
return d_->d_namlen;
|
|
#else
|
|
return strlen(d_->d_name);
|
|
#endif
|
|
}
|
|
|
|
static
|
|
inline
|
|
std::vector<std::future<DirRV>>
|
|
_opendir(ThreadPool &tp_,
|
|
const Branches::Ptr &branches_,
|
|
const fs::path &rel_dirpath_)
|
|
{
|
|
std::vector<std::future<DirRV>> futures;
|
|
|
|
futures.reserve(branches_->size());
|
|
|
|
for(const auto &branch : *branches_)
|
|
{
|
|
auto func =
|
|
[&branch,&rel_dirpath_]()
|
|
{
|
|
DIR *dir;
|
|
fs::path abs_dirpath;
|
|
|
|
abs_dirpath = branch.path / rel_dirpath_;
|
|
|
|
errno = 0;
|
|
dir = fs::opendir(abs_dirpath);
|
|
|
|
return DirRV{&branch.path,dir,-errno};
|
|
};
|
|
|
|
auto rv = tp_.enqueue_task(std::move(func));
|
|
|
|
futures.emplace_back(std::move(rv));
|
|
}
|
|
|
|
return futures;
|
|
}
|
|
|
|
static
|
|
inline
|
|
int
|
|
_readdir(std::vector<std::future<DirRV>> &dh_futures_,
|
|
const fs::path &rel_dirpath_,
|
|
fuse_dirents_t *dirents_)
|
|
{
|
|
Err err;
|
|
HashSet names;
|
|
fs::path rel_filepath;
|
|
|
|
rel_filepath = rel_dirpath_ / "dummy";
|
|
for(auto &dh_future : dh_futures_)
|
|
{
|
|
DirRV dirrv;
|
|
|
|
dirrv = dh_future.get();
|
|
|
|
err = dirrv.err;
|
|
if(dirrv.dir == NULL)
|
|
continue;
|
|
DEFER { fs::closedir(dirrv.dir); };
|
|
|
|
for(dirent *de = fs::readdir(dirrv.dir);
|
|
de;
|
|
de = fs::readdir(dirrv.dir))
|
|
{
|
|
int rv;
|
|
int namelen;
|
|
|
|
namelen = ::_dirent_exact_namelen(de);
|
|
|
|
rv = names.put(de->d_name,namelen);
|
|
if(rv == 0)
|
|
continue;
|
|
|
|
rel_filepath.replace_filename(de->d_name);
|
|
|
|
de->d_ino = fs::inode::calc(*dirrv.branch_path,
|
|
rel_filepath,
|
|
DTTOIF(de->d_type),
|
|
de->d_ino);
|
|
|
|
fuse_dirents_add(dirents_,de,namelen);
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|