additional readdir refactor cleanup

Differences between readdir and getdents is minimal at best. Leaving code
for now to allow for possible expansion later.
This commit is contained in:
Antonio SJ Musumeci 2020-06-26 16:50:49 -04:00
parent 4160a8e2f8
commit dbdd3e22fc
28 changed files with 453 additions and 177 deletions

View File

@ -1,7 +1,7 @@
/* /*
ISC License ISC License
Copyright (c) 2019, Antonio SJ Musumeci <trapexit@spawn.link> Copyright (c) 2020, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above

View File

@ -25,7 +25,7 @@ extern "C" {
#include "fuse_dirent.h" #include "fuse_dirent.h"
#include "fuse_direntplus.h" #include "fuse_direntplus.h"
#include "fuse_entry.h" #include "fuse_entry.h"
#include "linux_dirent64.h" #include "linux_dirent.h"
#include <dirent.h> #include <dirent.h>
#include <stdint.h> #include <stdint.h>
@ -63,14 +63,14 @@ int fuse_dirents_add_plus(fuse_dirents_t *d,
const uint64_t namelen, const uint64_t namelen,
const fuse_entry_t *entry, const fuse_entry_t *entry,
const struct stat *st); const struct stat *st);
int fuse_dirents_add_linux(fuse_dirents_t *d, int fuse_dirents_add_linux(fuse_dirents_t *d,
const struct linux_dirent64 *de, const struct linux_dirent *de,
const uint64_t namelen); const uint64_t namelen);
int fuse_dirents_add_linux_plus(fuse_dirents_t *d, int fuse_dirents_add_linux_plus(fuse_dirents_t *d,
const struct linux_dirent64 *de, const struct linux_dirent *de,
const uint64_t namelen, const uint64_t namelen,
const fuse_entry_t *entry, const fuse_entry_t *entry,
const struct stat *st); const struct stat *st);
void *fuse_dirents_find(fuse_dirents_t *d, void *fuse_dirents_find(fuse_dirents_t *d,
const uint64_t ino); const uint64_t ino);

View File

@ -0,0 +1,9 @@
#pragma once
struct linux_dirent
{
unsigned long ino;
unsigned long off;
unsigned short reclen;
char name[];
};

View File

@ -1,12 +0,0 @@
#pragma once
#include <stdint.h>
struct linux_dirent64
{
uint64_t d_ino;
int64_t d_off;
uint16_t d_reclen;
uint8_t d_type;
char d_name[];
};

View File

@ -5,7 +5,7 @@
#include "fuse_direntplus.h" #include "fuse_direntplus.h"
#include "fuse_dirents.h" #include "fuse_dirents.h"
#include "fuse_entry.h" #include "fuse_entry.h"
#include "linux_dirent64.h" #include "linux_dirent.h"
#include "stat_utils.h" #include "stat_utils.h"
#include <dirent.h> #include <dirent.h>
@ -16,7 +16,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define DEFAULT_SIZE (1024 * 16) /* 32KB - same as glibc getdents buffer size */
#define DEFAULT_SIZE (1024 * 32)
static static
uint64_t uint64_t
@ -308,9 +309,9 @@ fuse_dirents_add_plus(fuse_dirents_t *d_,
} }
int int
fuse_dirents_add_linux(fuse_dirents_t *d_, fuse_dirents_add_linux(fuse_dirents_t *d_,
const struct linux_dirent64 *dirent_, const struct linux_dirent *dirent_,
const uint64_t namelen_) const uint64_t namelen_)
{ {
uint64_t size; uint64_t size;
fuse_dirent_t *d; fuse_dirent_t *d;
@ -332,21 +333,21 @@ fuse_dirents_add_linux(fuse_dirents_t *d_,
if(d == NULL) if(d == NULL)
return -ENOMEM; return -ENOMEM;
d->ino = dirent_->d_ino; d->ino = dirent_->ino;
d->off = d_->data_len; d->off = d_->data_len;
d->namelen = namelen_; d->namelen = namelen_;
d->type = dirent_->d_type; d->type = *((char*)dirent_ + dirent_->reclen - 1);
memcpy(d->name,dirent_->d_name,namelen_); memcpy(d->name,dirent_->name,namelen_);
return 0; return 0;
} }
int int
fuse_dirents_add_linux_plus(fuse_dirents_t *d_, fuse_dirents_add_linux_plus(fuse_dirents_t *d_,
const struct linux_dirent64 *dirent_, const struct linux_dirent *dirent_,
const uint64_t namelen_, const uint64_t namelen_,
const fuse_entry_t *entry_, const fuse_entry_t *entry_,
const struct stat *st_) const struct stat *st_)
{ {
uint64_t size; uint64_t size;
fuse_direntplus_t *d; fuse_direntplus_t *d;
@ -368,11 +369,11 @@ fuse_dirents_add_linux_plus(fuse_dirents_t *d_,
if(d == NULL) if(d == NULL)
return -ENOMEM; return -ENOMEM;
d->dirent.ino = dirent_->d_ino; d->dirent.ino = dirent_->ino;
d->dirent.off = d_->data_len; d->dirent.off = d_->data_len;
d->dirent.namelen = namelen_; d->dirent.namelen = namelen_;
d->dirent.type = dirent_->d_type; d->dirent.type = *((char*)dirent_ + dirent_->reclen - 1);
memcpy(d->dirent.name,dirent_->d_name,namelen_); memcpy(d->dirent.name,dirent_->name,namelen_);
d->entry = *entry_; d->entry = *entry_;

View File

@ -90,6 +90,7 @@ Config::Config()
nullrw(false), nullrw(false),
pid(::getpid()), pid(::getpid()),
posix_acl(false), posix_acl(false),
readdir(ReadDir::ENUM::POSIX),
readdirplus(false), readdirplus(false),
security_capability(true), security_capability(true),
srcmounts(branches), srcmounts(branches),
@ -149,6 +150,7 @@ Config::Config()
_map["nullrw"] = &nullrw; _map["nullrw"] = &nullrw;
_map["pid"] = &pid; _map["pid"] = &pid;
_map["posix_acl"] = &posix_acl; _map["posix_acl"] = &posix_acl;
// _map["readdir"] = &readdir;
_map["readdirplus"] = &readdirplus; _map["readdirplus"] = &readdirplus;
_map["security_capability"] = &security_capability; _map["security_capability"] = &security_capability;
_map["srcmounts"] = &srcmounts; _map["srcmounts"] = &srcmounts;

View File

@ -17,6 +17,7 @@
#pragma once #pragma once
#include "branch.hpp" #include "branch.hpp"
#include "config_readdir.hpp"
#include "enum.hpp" #include "enum.hpp"
#include "errno.hpp" #include "errno.hpp"
#include "func_category.hpp" #include "func_category.hpp"
@ -110,6 +111,7 @@ public:
ConfigBOOL nullrw; ConfigBOOL nullrw;
ConfigUINT64 pid; ConfigUINT64 pid;
ConfigBOOL posix_acl; ConfigBOOL posix_acl;
ReadDir readdir;
ConfigBOOL readdirplus; ConfigBOOL readdirplus;
ConfigBOOL security_capability; ConfigBOOL security_capability;
SrcMounts srcmounts; SrcMounts srcmounts;

49
src/config_readdir.cpp Normal file
View File

@ -0,0 +1,49 @@
/*
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
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config_readdir.hpp"
#include "ef.hpp"
template<>
int
ReadDir::from_string(const std::string &s_)
{
if(s_ == "posix")
_data = ReadDir::ENUM::POSIX;
ef(s_ == "linux")
_data = ReadDir::ENUM::LINUX;
else
return -EINVAL;
return 0;
}
template<>
std::string
ReadDir::to_string(void) const
{
switch(_data)
{
case ReadDir::ENUM::POSIX:
return "posix";
case ReadDir::ENUM::LINUX:
return "linux";
}
return "invalid";
}

29
src/config_readdir.hpp Normal file
View File

@ -0,0 +1,29 @@
/*
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
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include "enum.hpp"
enum class ReadDirEnum
{
POSIX,
LINUX
};
typedef Enum<ReadDirEnum> ReadDir;

View File

@ -16,6 +16,8 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#pragma once
#include "tofrom_string.hpp" #include "tofrom_string.hpp"
#include <string> #include <string>

View File

@ -16,6 +16,8 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#pragma once
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>

37
src/fs_base_getdents.cpp Normal file
View File

@ -0,0 +1,37 @@
/*
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
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#if defined __linux__
#include <unistd.h>
#include <sys/syscall.h>
#endif
namespace fs
{
int
getdents(unsigned int fd_,
void *dirp_,
unsigned int count_)
{
#if defined SYS_getdents64
return ::syscall(SYS_getdents,fd_,dirp_,count_);
#else
return (errno=ENOTSUP,-1);
#endif
}
}

27
src/fs_base_getdents.hpp Normal file
View File

@ -0,0 +1,27 @@
/*
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
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
namespace fs
{
int
getdents(unsigned int fd,
void *dirp,
unsigned int count);
}

View File

@ -18,6 +18,8 @@
#include "fs_base_stat.hpp" #include "fs_base_stat.hpp"
#include "fs_copy_file_range.hpp" #include "fs_copy_file_range.hpp"
#include <stdint.h>
namespace l namespace l
{ {
int64_t int64_t

View File

@ -16,9 +16,11 @@
#pragma once #pragma once
#include <stdint.h>
namespace fs namespace fs
{ {
int int64_t
copydata_copy_file_range(const int src_fd, copydata_copy_file_range(const int src_fd,
const int dst_fd); const int dst_fd);
} }

View File

@ -14,6 +14,8 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#pragma once
#include <string> #include <string>
#include <vector> #include <vector>

View File

@ -16,6 +16,8 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#pragma once
#include <stdint.h> #include <stdint.h>
#include <sys/statvfs.h> #include <sys/statvfs.h>

View File

@ -16,8 +16,35 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#ifdef __linux__ #include "fuse_readdir_posix.hpp"
# include "fuse_readdir_linux.icpp" #include "fuse_readdir_linux.hpp"
#else
# include "fuse_readdir_posix.icpp" #include "config.hpp"
#endif #include "dirinfo.hpp"
#include "rwlock.hpp"
#include "ugid.hpp"
#include <fuse.h>
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::ro();
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard guard(&config.branches.lock);
switch(config.readdir)
{
case ReadDir::ENUM::LINUX:
return FUSE::readdir_linux(config.branches,di->fusepath.c_str(),buf_);
default:
case ReadDir::ENUM::POSIX:
return FUSE::readdir_posix(config.branches,di->fusepath.c_str(),buf_);
}
}
}

View File

@ -14,22 +14,18 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#define _DEFAULT_SOURCE #include "branch.hpp"
#include "config.hpp"
#include "dirinfo.hpp"
#include "errno.hpp" #include "errno.hpp"
#include "fs_base_close.hpp" #include "fs_base_close.hpp"
#include "fs_base_getdents.hpp"
#include "fs_base_open.hpp" #include "fs_base_open.hpp"
#include "fs_base_stat.hpp" #include "fs_base_stat.hpp"
#include "fs_devid.hpp" #include "fs_devid.hpp"
#include "fs_inode.hpp" #include "fs_inode.hpp"
#include "fs_path.hpp" #include "fs_path.hpp"
#include "hashset.hpp" #include "hashset.hpp"
#include "linux_dirent64.h" #include "linux_dirent.h"
#include "mempools.hpp" #include "mempools.hpp"
#include "rwlock.hpp"
#include "ugid.hpp"
#include <fuse.h> #include <fuse.h>
#include <fuse_dirents.h> #include <fuse_dirents.h>
@ -38,23 +34,12 @@
#include <vector> #include <vector>
#include <stddef.h> #include <stddef.h>
#include <sys/syscall.h>
using std::string; using std::string;
using std::vector; using std::vector;
namespace l namespace l
{ {
static
inline
int
getdents64(unsigned int fd_,
char *dirp_,
unsigned int count_)
{
return syscall(SYS_getdents64,fd_,dirp_,count_);
}
static static
int int
close_free_ret_enomem(int fd_, close_free_ret_enomem(int fd_,
@ -77,7 +62,7 @@ namespace l
HashSet names; HashSet names;
string basepath; string basepath;
uint64_t namelen; uint64_t namelen;
struct linux_dirent64 *d; struct linux_dirent *d;
buf = (char*)g_DENTS_BUF_POOL.alloc(); buf = (char*)g_DENTS_BUF_POOL.alloc();
if(buf == NULL) if(buf == NULL)
@ -100,22 +85,22 @@ namespace l
for(;;) for(;;)
{ {
nread = l::getdents64(dirfd,buf,g_DENTS_BUF_POOL.size()); nread = fs::getdents(dirfd,buf,g_DENTS_BUF_POOL.size());
if(nread == -1) if(nread == -1)
break; break;
if(nread == 0) if(nread == 0)
break; break;
for(int64_t pos = 0; pos < nread; pos += d->d_reclen) for(int64_t pos = 0; pos < nread; pos += d->reclen)
{ {
d = (struct linux_dirent64*)(buf + pos); d = (struct linux_dirent*)(buf + pos);
namelen = (strlen(d->d_name) + 1); namelen = strlen(d->name);
rv = names.put(d->d_name,namelen); rv = names.put(d->name,namelen);
if(rv == 0) if(rv == 0)
continue; continue;
d->d_ino = fs::inode::recompute(d->d_ino,dev); d->ino = fs::inode::recompute(d->ino,dev);
rv = fuse_dirents_add_linux(buf_,d,namelen); rv = fuse_dirents_add_linux(buf_,d,namelen);
if(rv) if(rv)
@ -135,17 +120,10 @@ namespace l
namespace FUSE namespace FUSE
{ {
int int
readdir(fuse_file_info *ffi_, readdir_linux(const Branches &branches_,
fuse_dirents_t *buf_) const char *dirname_,
fuse_dirents_t *buf_)
{ {
DirInfo *di = reinterpret_cast<DirInfo*>(ffi_->fh); return l::readdir(branches_,dirname_,buf_);
const fuse_context *fc = fuse_get_context();
const Config &config = Config::ro();
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_);
} }
} }

View File

@ -0,0 +1,33 @@
/*
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
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include "branch.hpp"
#include <fuse.h>
#include <stdint.h>
namespace FUSE
{
int
readdir_linux(const Branches &branches,
const char *dirname,
fuse_dirents_t *buf);
}

View File

@ -16,8 +16,43 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#ifdef __linux__ #include "fuse_readdir_plus_linux.hpp"
# include "fuse_readdir_plus_linux.icpp" #include "fuse_readdir_plus_posix.hpp"
#else
# include "fuse_readdir_plus_posix.icpp" #include "config.hpp"
#endif #include "dirinfo.hpp"
#include "rwlock.hpp"
#include "ugid.hpp"
#include <fuse.h>
namespace FUSE
{
int
readdir_plus(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::ro();
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard guard(&config.branches.lock);
switch(config.readdir)
{
case ReadDir::ENUM::LINUX:
return FUSE::readdir_plus_linux(config.branches,
di->fusepath.c_str(),
config.cache_entry,
config.cache_attr,
buf_);
default:
case ReadDir::ENUM::POSIX:
return FUSE::readdir_plus_posix(config.branches,
di->fusepath.c_str(),
config.cache_entry,
config.cache_attr,
buf_);
}
}
}

View File

@ -18,10 +18,6 @@
#include <fuse.h> #include <fuse.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
namespace FUSE namespace FUSE
{ {
int int

View File

@ -14,23 +14,19 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#define _DEFAULT_SOURCE #include "branch.hpp"
#include "config.hpp"
#include "dirinfo.hpp"
#include "errno.hpp" #include "errno.hpp"
#include "fs_base_close.hpp" #include "fs_base_close.hpp"
#include "fs_base_fstatat.hpp" #include "fs_base_fstatat.hpp"
#include "fs_base_getdents.hpp"
#include "fs_base_open.hpp" #include "fs_base_open.hpp"
#include "fs_base_stat.hpp" #include "fs_base_stat.hpp"
#include "fs_devid.hpp" #include "fs_devid.hpp"
#include "fs_inode.hpp" #include "fs_inode.hpp"
#include "fs_path.hpp" #include "fs_path.hpp"
#include "hashset.hpp" #include "hashset.hpp"
#include "linux_dirent64.h" #include "linux_dirent.h"
#include "mempools.hpp" #include "mempools.hpp"
#include "rwlock.hpp"
#include "ugid.hpp"
#include <fuse.h> #include <fuse.h>
#include <fuse_dirents.h> #include <fuse_dirents.h>
@ -39,23 +35,12 @@
#include <vector> #include <vector>
#include <stddef.h> #include <stddef.h>
#include <sys/syscall.h>
using std::string; using std::string;
using std::vector; using std::vector;
namespace l namespace l
{ {
static
inline
int
getdents64(unsigned int fd_,
char *dirp_,
unsigned int count_)
{
return syscall(SYS_getdents64,fd_,dirp_,count_);
}
int int
close_free_ret_enomem(int fd_, close_free_ret_enomem(int fd_,
void *buf_) void *buf_)
@ -81,7 +66,7 @@ namespace l
uint64_t namelen; uint64_t namelen;
struct stat st; struct stat st;
fuse_entry_t entry; fuse_entry_t entry;
struct linux_dirent64 *d; struct linux_dirent *d;
buf = (char*)g_DENTS_BUF_POOL.alloc(); buf = (char*)g_DENTS_BUF_POOL.alloc();
@ -108,27 +93,27 @@ namespace l
for(;;) for(;;)
{ {
nread = l::getdents64(dirfd,buf,g_DENTS_BUF_POOL.size()); nread = fs::getdents(dirfd,buf,g_DENTS_BUF_POOL.size());
if(nread == -1) if(nread == -1)
break; break;
if(nread == 0) if(nread == 0)
break; break;
for(int64_t pos = 0; pos < nread; pos += d->d_reclen) for(int64_t pos = 0; pos < nread; pos += d->reclen)
{ {
d = (struct linux_dirent64*)(buf + pos); d = (struct linux_dirent*)(buf + pos);
namelen = (strlen(d->d_name) + 1); namelen = (strlen(d->name) + 1);
rv = names.put(d->d_name,namelen); rv = names.put(d->name,namelen);
if(rv == 0) if(rv == 0)
continue; continue;
rv = fs::fstatat_nofollow(dirfd,d->d_name,&st); rv = fs::fstatat_nofollow(dirfd,d->name,&st);
if(rv == -1) if(rv == -1)
memset(&st,0,sizeof(st)); memset(&st,0,sizeof(st));
d->d_ino = fs::inode::recompute(d->d_ino,dev); d->ino = fs::inode::recompute(d->ino,dev);
st.st_ino = d->d_ino; st.st_ino = d->ino;
rv = fuse_dirents_add_linux_plus(buf_,d,namelen,&entry,&st); rv = fuse_dirents_add_linux_plus(buf_,d,namelen,&entry,&st);
if(rv) if(rv)
@ -148,19 +133,12 @@ namespace l
namespace FUSE namespace FUSE
{ {
int int
readdir_plus(fuse_file_info *ffi_, readdir_plus_linux(const Branches &branches_,
fuse_dirents_t *buf_) const char *dirname_,
const uint64_t entry_timeout_,
const uint64_t attr_timeout_,
fuse_dirents_t *buf_)
{ {
DirInfo *di = reinterpret_cast<DirInfo*>(ffi_->fh); return l::readdir_plus(branches_,dirname_,entry_timeout_,attr_timeout_,buf_);
const fuse_context *fc = fuse_get_context();
const Config &config = Config::ro();
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard guard(&config.branches.lock);
return l::readdir_plus(config.branches,
di->fusepath.c_str(),
config.cache_entry,
config.cache_attr,
buf_);
} }
} }

View File

@ -0,0 +1,35 @@
/*
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
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include "branch.hpp"
#include <fuse.h>
#include <stdint.h>
namespace FUSE
{
int
readdir_plus_linux(const Branches &branches_,
const char *dirname_,
const uint64_t entry_timeout_,
const uint64_t attr_timeout_,
fuse_dirents_t *buf_);
}

View File

@ -16,8 +16,7 @@
#define _DEFAULT_SOURCE #define _DEFAULT_SOURCE
#include "config.hpp" #include "branch.hpp"
#include "dirinfo.hpp"
#include "errno.hpp" #include "errno.hpp"
#include "fs_base_closedir.hpp" #include "fs_base_closedir.hpp"
#include "fs_base_dirfd.hpp" #include "fs_base_dirfd.hpp"
@ -29,8 +28,6 @@
#include "fs_inode.hpp" #include "fs_inode.hpp"
#include "fs_path.hpp" #include "fs_path.hpp"
#include "hashset.hpp" #include "hashset.hpp"
#include "rwlock.hpp"
#include "ugid.hpp"
#include <fuse.h> #include <fuse.h>
#include <fuse_dirents.h> #include <fuse_dirents.h>
@ -58,17 +55,12 @@ namespace l
#endif #endif
} }
static
uint64_t
dirent_alloc_namelen(const struct dirent *d_)
{
return (dirent_exact_namelen(d_) + 1);
}
static static
int int
readdir_plus(const Branches &branches_, readdir_plus(const Branches &branches_,
const char *dirname_, const char *dirname_,
const uint64_t entry_timeout_,
const uint64_t attr_timeout_,
fuse_dirents_t *buf_) fuse_dirents_t *buf_)
{ {
dev_t dev; dev_t dev;
@ -80,8 +72,8 @@ namespace l
entry.nodeid = 0; entry.nodeid = 0;
entry.generation = 0; entry.generation = 0;
entry.entry_valid = 1; entry.entry_valid = entry_timeout_;
entry.attr_valid = 1; entry.attr_valid = attr_timeout_;
entry.entry_valid_nsec = 0; entry.entry_valid_nsec = 0;
entry.attr_valid_nsec = 0; entry.attr_valid_nsec = 0;
for(size_t i = 0, ei = branches_.size(); i != ei; i++) for(size_t i = 0, ei = branches_.size(); i != ei; i++)
@ -104,7 +96,7 @@ namespace l
rv = 0; rv = 0;
for(struct dirent *de = fs::readdir(dh); de && !rv; de = fs::readdir(dh)) for(struct dirent *de = fs::readdir(dh); de && !rv; de = fs::readdir(dh))
{ {
namelen = l::dirent_alloc_namelen(de); namelen = l::dirent_exact_namelen(de);
rv = names.put(de->d_name,namelen); rv = names.put(de->d_name,namelen);
if(rv == 0) if(rv == 0)
@ -132,17 +124,12 @@ namespace l
namespace FUSE namespace FUSE
{ {
int int
readdir_plus(fuse_file_info *ffi_, readdir_plus_posix(const Branches &branches_,
fuse_dirents_t *buf_) const char *dirname_,
const uint64_t entry_timeout_,
const uint64_t attr_timeout_,
fuse_dirents_t *buf_)
{ {
DirInfo *di = reinterpret_cast<DirInfo*>(ffi_->fh); return l::readdir_plus(branches_,dirname_,entry_timeout_,attr_timeout_,buf_);
const fuse_context *fc = fuse_get_context();
const Config &config = Config::ro();
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard guard(&config.branches.lock);
return l::readdir_plus(config.branches,
di->fusepath.c_str(),
buf_);
} }
} }

View File

@ -0,0 +1,35 @@
/*
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
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include "branch.hpp"
#include <fuse.h>
#include <stdint.h>
namespace FUSE
{
int
readdir_plus_posix(const Branches &branches_,
const char *dirname_,
const uint64_t entry_timeout_,
const uint64_t attr_timeout_,
fuse_dirents_t *buf_);
}

View File

@ -16,8 +16,7 @@
#define _DEFAULT_SOURCE #define _DEFAULT_SOURCE
#include "config.hpp" #include "branch.hpp"
#include "dirinfo.hpp"
#include "errno.hpp" #include "errno.hpp"
#include "fs_base_closedir.hpp" #include "fs_base_closedir.hpp"
#include "fs_base_dirfd.hpp" #include "fs_base_dirfd.hpp"
@ -28,8 +27,6 @@
#include "fs_inode.hpp" #include "fs_inode.hpp"
#include "fs_path.hpp" #include "fs_path.hpp"
#include "hashset.hpp" #include "hashset.hpp"
#include "rwlock.hpp"
#include "ugid.hpp"
#include <fuse.h> #include <fuse.h>
#include <fuse_dirents.h> #include <fuse_dirents.h>
@ -57,13 +54,6 @@ namespace l
#endif #endif
} }
static
uint64_t
dirent_alloc_namelen(const struct dirent *d_)
{
return (dirent_exact_namelen(d_) + 1);
}
static static
int int
readdir(const Branches &branches_, readdir(const Branches &branches_,
@ -95,7 +85,7 @@ namespace l
rv = 0; rv = 0;
for(struct dirent *de = fs::readdir(dh); de && !rv; de = fs::readdir(dh)) for(struct dirent *de = fs::readdir(dh); de && !rv; de = fs::readdir(dh))
{ {
namelen = l::dirent_alloc_namelen(de); namelen = l::dirent_exact_namelen(de);
rv = names.put(de->d_name,namelen); rv = names.put(de->d_name,namelen);
if(rv == 0) if(rv == 0)
@ -118,17 +108,10 @@ namespace l
namespace FUSE namespace FUSE
{ {
int int
readdir(fuse_file_info *ffi_, readdir_posix(const Branches &branches_,
fuse_dirents_t *buf_) const char *dirname_,
fuse_dirents_t *buf_)
{ {
DirInfo *di = reinterpret_cast<DirInfo*>(ffi_->fh); return l::readdir(branches_,dirname_,buf_);
const fuse_context *fc = fuse_get_context();
const Config &config = Config::ro();
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard guard(&config.branches.lock);
return l::readdir(config.branches,
di->fusepath.c_str(),
buf_);
} }
} }

View File

@ -0,0 +1,33 @@
/*
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
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include "branch.hpp"
#include <fuse.h>
#include <stdint.h>
namespace FUSE
{
int
readdir_posix(const Branches &branches,
const char *dirname,
fuse_dirents_t *buf);
}