Browse Source

Merge pull request #774 from trapexit/readdir

additional readdir refactor cleanup
pull/775/head
trapexit 4 years ago
committed by GitHub
parent
commit
cb74573fc2
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      LICENSE
  2. 18
      libfuse/include/fuse_dirents.h
  3. 9
      libfuse/include/linux_dirent.h
  4. 12
      libfuse/include/linux_dirent64.h
  5. 33
      libfuse/lib/fuse_dirents.c
  6. 2
      src/config.cpp
  7. 2
      src/config.hpp
  8. 49
      src/config_readdir.cpp
  9. 29
      src/config_readdir.hpp
  10. 2
      src/enum.hpp
  11. 2
      src/fs_base_fstatat.hpp
  12. 37
      src/fs_base_getdents.cpp
  13. 27
      src/fs_base_getdents.hpp
  14. 2
      src/fs_copydata_copy_file_range.cpp
  15. 4
      src/fs_copydata_copy_file_range.hpp
  16. 2
      src/fs_glob.hpp
  17. 2
      src/fs_statvfs_cache.hpp
  18. 37
      src/fuse_readdir.cpp
  19. 50
      src/fuse_readdir_linux.cpp
  20. 33
      src/fuse_readdir_linux.hpp
  21. 45
      src/fuse_readdir_plus.cpp
  22. 4
      src/fuse_readdir_plus.hpp
  23. 58
      src/fuse_readdir_plus_linux.cpp
  24. 35
      src/fuse_readdir_plus_linux.hpp
  25. 37
      src/fuse_readdir_plus_posix.cpp
  26. 35
      src/fuse_readdir_plus_posix.hpp
  27. 29
      src/fuse_readdir_posix.cpp
  28. 33
      src/fuse_readdir_posix.hpp

2
LICENSE

@ -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

18
libfuse/include/fuse_dirents.h

@ -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,
const struct linux_dirent64 *de,
const uint64_t namelen);
int fuse_dirents_add_linux_plus(fuse_dirents_t *d,
const struct linux_dirent64 *de,
const uint64_t namelen,
const fuse_entry_t *entry,
const struct stat *st);
int fuse_dirents_add_linux(fuse_dirents_t *d,
const struct linux_dirent *de,
const uint64_t namelen);
int fuse_dirents_add_linux_plus(fuse_dirents_t *d,
const struct linux_dirent *de,
const uint64_t namelen,
const fuse_entry_t *entry,
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);

9
libfuse/include/linux_dirent.h

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

12
libfuse/include/linux_dirent64.h

@ -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[];
};

33
libfuse/lib/fuse_dirents.c

@ -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_,
const struct linux_dirent64 *dirent_,
const uint64_t namelen_)
fuse_dirents_add_linux(fuse_dirents_t *d_,
const struct linux_dirent *dirent_,
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;
memcpy(d->name,dirent_->d_name,namelen_);
d->type = *((char*)dirent_ + dirent_->reclen - 1);
memcpy(d->name,dirent_->name,namelen_);
return 0; return 0;
} }
int int
fuse_dirents_add_linux_plus(fuse_dirents_t *d_,
const struct linux_dirent64 *dirent_,
const uint64_t namelen_,
const fuse_entry_t *entry_,
const struct stat *st_)
fuse_dirents_add_linux_plus(fuse_dirents_t *d_,
const struct linux_dirent *dirent_,
const uint64_t namelen_,
const fuse_entry_t *entry_,
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;
memcpy(d->dirent.name,dirent_->d_name,namelen_);
d->dirent.type = *((char*)dirent_ + dirent_->reclen - 1);
memcpy(d->dirent.name,dirent_->name,namelen_);
d->entry = *entry_; d->entry = *entry_;

2
src/config.cpp

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

2
src/config.hpp

@ -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

@ -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

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

2
src/enum.hpp

@ -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>

2
src/fs_base_fstatat.hpp

@ -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

@ -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

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

2
src/fs_copydata_copy_file_range.cpp

@ -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

4
src/fs_copydata_copy_file_range.hpp

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

2
src/fs_glob.hpp

@ -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>

2
src/fs_statvfs_cache.hpp

@ -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>

37
src/fuse_readdir.cpp

@ -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_linux.icpp"
#else
# include "fuse_readdir_posix.icpp"
#endif
#include "fuse_readdir_posix.hpp"
#include "fuse_readdir_linux.hpp"
#include "config.hpp"
#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_);
}
}
}

50
src/fuse_readdir_linux.icpp → src/fuse_readdir_linux.cpp

@ -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 "config.hpp"
#include "dirinfo.hpp"
#include "branch.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);
namelen = (strlen(d->d_name) + 1);
d = (struct linux_dirent*)(buf + pos);
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_,
fuse_dirents_t *buf_)
readdir_linux(const Branches &branches_,
const char *dirname_,
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 readlock(&config.branches.lock);
return l::readdir(config.branches,
di->fusepath.c_str(),
buf_);
return l::readdir(branches_,dirname_,buf_);
} }
} }

33
src/fuse_readdir_linux.hpp

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

45
src/fuse_readdir_plus.cpp

@ -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.icpp"
#else
# include "fuse_readdir_plus_posix.icpp"
#endif
#include "fuse_readdir_plus_linux.hpp"
#include "fuse_readdir_plus_posix.hpp"
#include "config.hpp"
#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_);
}
}
}

4
src/fuse_readdir_plus.hpp

@ -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

58
src/fuse_readdir_plus_linux.icpp → src/fuse_readdir_plus_linux.cpp

@ -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 "config.hpp"
#include "dirinfo.hpp"
#include "branch.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);
namelen = (strlen(d->d_name) + 1);
d = (struct linux_dirent*)(buf + pos);
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);
st.st_ino = d->d_ino;
d->ino = fs::inode::recompute(d->ino,dev);
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_,
fuse_dirents_t *buf_)
readdir_plus_linux(const Branches &branches_,
const char *dirname_,
const uint64_t entry_timeout_,
const uint64_t attr_timeout_,
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);
return l::readdir_plus(config.branches,
di->fusepath.c_str(),
config.cache_entry,
config.cache_attr,
buf_);
return l::readdir_plus(branches_,dirname_,entry_timeout_,attr_timeout_,buf_);
} }
} }

35
src/fuse_readdir_plus_linux.hpp

@ -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_);
}

37
src/fuse_readdir_plus_posix.icpp → src/fuse_readdir_plus_posix.cpp

@ -16,8 +16,7 @@
#define _DEFAULT_SOURCE #define _DEFAULT_SOURCE
#include "config.hpp"
#include "dirinfo.hpp"
#include "branch.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.attr_valid = 1;
entry.entry_valid = entry_timeout_;
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_,
fuse_dirents_t *buf_)
readdir_plus_posix(const Branches &branches_,
const char *dirname_,
const uint64_t entry_timeout_,
const uint64_t attr_timeout_,
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);
return l::readdir_plus(config.branches,
di->fusepath.c_str(),
buf_);
return l::readdir_plus(branches_,dirname_,entry_timeout_,attr_timeout_,buf_);
} }
} }

35
src/fuse_readdir_plus_posix.hpp

@ -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_);
}

29
src/fuse_readdir_posix.icpp → src/fuse_readdir_posix.cpp

@ -16,8 +16,7 @@
#define _DEFAULT_SOURCE #define _DEFAULT_SOURCE
#include "config.hpp"
#include "dirinfo.hpp"
#include "branch.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_,
fuse_dirents_t *buf_)
readdir_posix(const Branches &branches_,
const char *dirname_,
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);
return l::readdir(config.branches,
di->fusepath.c_str(),
buf_);
return l::readdir(branches_,dirname_,buf_);
} }
} }

33
src/fuse_readdir_posix.hpp

@ -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);
}
Loading…
Cancel
Save