use getdents64 on linux

This commit is contained in:
Antonio SJ Musumeci 2020-02-24 18:14:00 -05:00
parent d119807adb
commit 62873d2d3b
15 changed files with 898 additions and 229 deletions

View file

@ -1,5 +1,7 @@
/*
Copyright (c) 2019, Antonio SJ Musumeci <trapexit@spawn.link>
ISC License
Copyright (c) 2020, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -14,98 +16,8 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define _DEFAULT_SOURCE
#include "config.hpp"
#include "dirinfo.hpp"
#include "errno.hpp"
#include "fs_base_closedir.hpp"
#include "fs_base_dirfd.hpp"
#include "fs_base_opendir.hpp"
#include "fs_base_readdir.hpp"
#include "fs_base_stat.hpp"
#include "fs_devid.hpp"
#include "fs_inode.hpp"
#include "fs_path.hpp"
#include "hashset.hpp"
#include "rwlock.hpp"
#include "ugid.hpp"
#include <fuse.h>
#include <fuse_dirents.h>
#include <string>
#include <vector>
#include <dirent.h>
using std::string;
using std::vector;
namespace l
{
static
int
readdir(const Branches &branches_,
const char *dirname_,
fuse_dirents_t *buf_)
{
dev_t dev;
HashSet names;
string basepath;
for(size_t i = 0, ei = branches_.size(); i != ei; i++)
{
int rv;
int dirfd;
DIR *dh;
basepath = fs::path::make(&branches_[i].path,dirname_);
dh = fs::opendir(basepath);
if(!dh)
continue;
dirfd = fs::dirfd(dh);
dev = fs::devid(dirfd);
if(dev == (dev_t)-1)
dev = i;
rv = 0;
for(struct dirent *de = fs::readdir(dh); de && !rv; de = fs::readdir(dh))
{
rv = names.put(de->d_name,_D_EXACT_NAMLEN(de));
if(rv == 0)
continue;
de->d_ino = fs::inode::recompute(de->d_ino,dev);
rv = fuse_dirents_add(buf_,de);
if(rv)
return (fs::closedir(dh),-ENOMEM);
}
fs::closedir(dh);
}
return 0;
}
}
namespace FUSE
{
int
readdir(fuse_file_info *ffi_,
fuse_dirents_t *buf_)
{
DirInfo *di = reinterpret_cast<DirInfo*>(ffi_->fh);
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock);
return l::readdir(config.branches,
di->fusepath.c_str(),
buf_);
}
}
#ifdef __linux__
# include "fuse_readdir_linux.icpp"
#else
# include "fuse_readdir_posix.icpp"
#endif