mirror of
https://github.com/trapexit/mergerfs.git
synced 2025-03-15 02:35:12 +08:00
use getdents64 on linux
This commit is contained in:
parent
d119807adb
commit
62873d2d3b
@ -54,12 +54,21 @@ int fuse_dirents_init(fuse_dirents_t *d);
|
|||||||
void fuse_dirents_free(fuse_dirents_t *d);
|
void fuse_dirents_free(fuse_dirents_t *d);
|
||||||
void fuse_dirents_reset(fuse_dirents_t *d);
|
void fuse_dirents_reset(fuse_dirents_t *d);
|
||||||
|
|
||||||
int fuse_dirents_add(fuse_dirents_t *d,
|
int fuse_dirents_add(fuse_dirents_t *d,
|
||||||
struct dirent *de);
|
const struct dirent *de);
|
||||||
int fuse_dirents_add_plus(fuse_dirents_t *d,
|
int fuse_dirents_add_plus(fuse_dirents_t *d,
|
||||||
const struct dirent *de,
|
const struct dirent *de,
|
||||||
const fuse_entry_t *entry,
|
const fuse_entry_t *entry,
|
||||||
const struct stat *st);
|
const struct stat *st);
|
||||||
|
#ifdef __linux__
|
||||||
|
struct linux_dirent64;
|
||||||
|
int fuse_dirents_add_linux(fuse_dirents_t *d,
|
||||||
|
const struct linux_dirent64 *de);
|
||||||
|
int fuse_dirents_add_linux_plus(fuse_dirents_t *d,
|
||||||
|
const struct linux_dirent64 *de,
|
||||||
|
const fuse_entry_t *entry,
|
||||||
|
const struct stat *st);
|
||||||
|
#endif
|
||||||
|
|
||||||
void *fuse_dirents_find(fuse_dirents_t *d,
|
void *fuse_dirents_find(fuse_dirents_t *d,
|
||||||
const uint64_t ino);
|
const uint64_t ino);
|
||||||
|
@ -17,10 +17,6 @@
|
|||||||
|
|
||||||
#define DEFAULT_SIZE (1024 * 16)
|
#define DEFAULT_SIZE (1024 * 16)
|
||||||
|
|
||||||
#ifndef _D_EXACT_NAMLEN
|
|
||||||
# define _D_EXACT_NAMLEN(d) ((d)->d_namlen)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static
|
static
|
||||||
uint64_t
|
uint64_t
|
||||||
align_uint64_t(uint64_t v_)
|
align_uint64_t(uint64_t v_)
|
||||||
@ -237,8 +233,8 @@ fuse_dirents_convert_plus2normal(fuse_dirents_t *d_)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
fuse_dirents_add(fuse_dirents_t *d_,
|
fuse_dirents_add(fuse_dirents_t *d_,
|
||||||
struct dirent *dirent_)
|
const struct dirent *dirent_)
|
||||||
{
|
{
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
uint64_t namelen;
|
uint64_t namelen;
|
||||||
@ -255,7 +251,7 @@ fuse_dirents_add(fuse_dirents_t *d_,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
namelen = _D_EXACT_NAMLEN(dirent_);
|
namelen = _D_ALLOC_NAMLEN(dirent_);
|
||||||
size = fuse_dirent_size(namelen);
|
size = fuse_dirent_size(namelen);
|
||||||
|
|
||||||
d = fuse_dirents_alloc(d_,size);
|
d = fuse_dirents_alloc(d_,size);
|
||||||
@ -292,7 +288,7 @@ fuse_dirents_add_plus(fuse_dirents_t *d_,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
namelen = _D_EXACT_NAMLEN(dirent_);
|
namelen = _D_ALLOC_NAMLEN(dirent_);
|
||||||
size = fuse_direntplus_size(namelen);
|
size = fuse_direntplus_size(namelen);
|
||||||
|
|
||||||
d = fuse_dirents_alloc(d_,size);
|
d = fuse_dirents_alloc(d_,size);
|
||||||
@ -312,6 +308,93 @@ fuse_dirents_add_plus(fuse_dirents_t *d_,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
struct linux_dirent64
|
||||||
|
{
|
||||||
|
uint64_t d_ino;
|
||||||
|
int64_t d_off;
|
||||||
|
uint16_t d_reclen;
|
||||||
|
uint8_t d_type;
|
||||||
|
char d_name[];
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
fuse_dirents_add_linux(fuse_dirents_t *d_,
|
||||||
|
const struct linux_dirent64 *dirent_)
|
||||||
|
{
|
||||||
|
uint64_t size;
|
||||||
|
uint64_t namelen;
|
||||||
|
fuse_dirent_t *d;
|
||||||
|
|
||||||
|
switch(d_->type)
|
||||||
|
{
|
||||||
|
case UNSET:
|
||||||
|
d_->type = NORMAL;
|
||||||
|
break;
|
||||||
|
case NORMAL:
|
||||||
|
break;
|
||||||
|
case PLUS:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
namelen = (dirent_->d_reclen - offsetof(struct linux_dirent64,d_name));
|
||||||
|
size = fuse_dirent_size(namelen);
|
||||||
|
|
||||||
|
d = fuse_dirents_alloc(d_,size);
|
||||||
|
if(d == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
d->ino = dirent_->d_ino;
|
||||||
|
d->off = d_->data_len;
|
||||||
|
d->namelen = namelen;
|
||||||
|
d->type = dirent_->d_type;
|
||||||
|
memcpy(d->name,dirent_->d_name,namelen);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
fuse_dirents_add_linux_plus(fuse_dirents_t *d_,
|
||||||
|
const struct linux_dirent64 *dirent_,
|
||||||
|
const fuse_entry_t *entry_,
|
||||||
|
const struct stat *st_)
|
||||||
|
{
|
||||||
|
uint64_t size;
|
||||||
|
uint64_t namelen;
|
||||||
|
fuse_direntplus_t *d;
|
||||||
|
|
||||||
|
switch(d_->type)
|
||||||
|
{
|
||||||
|
case UNSET:
|
||||||
|
d_->type = PLUS;
|
||||||
|
break;
|
||||||
|
case NORMAL:
|
||||||
|
return -EINVAL;
|
||||||
|
case PLUS:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
namelen = (dirent_->d_reclen - offsetof(struct linux_dirent64,d_name));
|
||||||
|
size = fuse_direntplus_size(namelen);
|
||||||
|
|
||||||
|
d = fuse_dirents_alloc(d_,size);
|
||||||
|
if(d == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
d->dirent.ino = dirent_->d_ino;
|
||||||
|
d->dirent.off = d_->data_len;
|
||||||
|
d->dirent.namelen = namelen;
|
||||||
|
d->dirent.type = dirent_->d_type;
|
||||||
|
memcpy(d->dirent.name,dirent_->d_name,namelen);
|
||||||
|
|
||||||
|
d->entry = *entry_;
|
||||||
|
|
||||||
|
fuse_dirents_fill_attr(&d->attr,st_);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
fuse_dirents_reset(fuse_dirents_t *d_)
|
fuse_dirents_reset(fuse_dirents_t *d_)
|
||||||
{
|
{
|
||||||
|
87
src/fixed_mem_pool.hpp
Normal file
87
src/fixed_mem_pool.hpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
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 <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct fixed_mem_pool_t fixed_mem_pool_t;
|
||||||
|
struct fixed_mem_pool_t
|
||||||
|
{
|
||||||
|
fixed_mem_pool_t *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<uint64_t SIZE>
|
||||||
|
class FixedMemPool
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FixedMemPool()
|
||||||
|
{
|
||||||
|
list.next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
~FixedMemPool()
|
||||||
|
{
|
||||||
|
void *mem;
|
||||||
|
while(!empty())
|
||||||
|
{
|
||||||
|
mem = alloc();
|
||||||
|
::free(mem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
empty(void)
|
||||||
|
{
|
||||||
|
return (list.next == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
size(void)
|
||||||
|
{
|
||||||
|
return SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
alloc(void)
|
||||||
|
{
|
||||||
|
void *rv;
|
||||||
|
|
||||||
|
if(list.next == NULL)
|
||||||
|
return malloc(SIZE);
|
||||||
|
|
||||||
|
rv = (void*)list.next;
|
||||||
|
list.next = list.next->next;
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
free(void *mem_)
|
||||||
|
{
|
||||||
|
fixed_mem_pool_t *next;
|
||||||
|
|
||||||
|
next = (fixed_mem_pool_t*)mem_;
|
||||||
|
next->next = list.next;
|
||||||
|
list.next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
fixed_mem_pool_t list;
|
||||||
|
};
|
@ -63,4 +63,12 @@ namespace fs
|
|||||||
{
|
{
|
||||||
return fs::open(path_.c_str(),flags_,mode_);
|
return fs::open(path_.c_str(),flags_,mode_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
inline
|
||||||
|
int
|
||||||
|
open_dir_ro(const std::string &path_)
|
||||||
|
{
|
||||||
|
return fs::open(path_,O_RDONLY|O_DIRECTORY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -372,6 +372,8 @@ namespace l
|
|||||||
l::getxattr_controlfile_bool(config.async_read,attrvalue);
|
l::getxattr_controlfile_bool(config.async_read,attrvalue);
|
||||||
else if(attr[2] == "fuse_msg_size")
|
else if(attr[2] == "fuse_msg_size")
|
||||||
l::getxattr_controlfile(config.fuse_msg_size,attrvalue);
|
l::getxattr_controlfile(config.fuse_msg_size,attrvalue);
|
||||||
|
else if(attr[2] == "readdirplus")
|
||||||
|
l::getxattr_controlfile_bool(config.readdirplus,attrvalue);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
|
@ -66,6 +66,7 @@ namespace l
|
|||||||
("user.mergerfs.pid")
|
("user.mergerfs.pid")
|
||||||
("user.mergerfs.policies")
|
("user.mergerfs.policies")
|
||||||
("user.mergerfs.posix_acl")
|
("user.mergerfs.posix_acl")
|
||||||
|
("user.mergerfs.readdirplus")
|
||||||
("user.mergerfs.security_capability")
|
("user.mergerfs.security_capability")
|
||||||
("user.mergerfs.srcmounts")
|
("user.mergerfs.srcmounts")
|
||||||
("user.mergerfs.statfs")
|
("user.mergerfs.statfs")
|
||||||
|
@ -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
|
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
|
||||||
@ -14,98 +16,8 @@
|
|||||||
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
|
#ifdef __linux__
|
||||||
|
# include "fuse_readdir_linux.icpp"
|
||||||
#include "config.hpp"
|
#else
|
||||||
#include "dirinfo.hpp"
|
# include "fuse_readdir_posix.icpp"
|
||||||
#include "errno.hpp"
|
#endif
|
||||||
#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_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
161
src/fuse_readdir_linux.icpp
Normal file
161
src/fuse_readdir_linux.icpp
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2019, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _DEFAULT_SOURCE
|
||||||
|
|
||||||
|
#include "config.hpp"
|
||||||
|
#include "dirinfo.hpp"
|
||||||
|
#include "errno.hpp"
|
||||||
|
#include "fs_base_close.hpp"
|
||||||
|
#include "fs_base_open.hpp"
|
||||||
|
#include "fs_base_stat.hpp"
|
||||||
|
#include "fs_devid.hpp"
|
||||||
|
#include "fs_inode.hpp"
|
||||||
|
#include "fs_path.hpp"
|
||||||
|
#include "hashset.hpp"
|
||||||
|
#include "mempools.hpp"
|
||||||
|
#include "rwlock.hpp"
|
||||||
|
#include "ugid.hpp"
|
||||||
|
|
||||||
|
#include <fuse.h>
|
||||||
|
#include <fuse_dirents.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
struct linux_dirent64
|
||||||
|
{
|
||||||
|
uint64_t d_ino;
|
||||||
|
int64_t d_off;
|
||||||
|
uint16_t d_reclen;
|
||||||
|
uint8_t d_type;
|
||||||
|
char d_name[];
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace l
|
||||||
|
{
|
||||||
|
static
|
||||||
|
inline
|
||||||
|
int
|
||||||
|
getdents64(unsigned int fd_,
|
||||||
|
char *dirp_,
|
||||||
|
unsigned int count_)
|
||||||
|
{
|
||||||
|
return syscall(SYS_getdents64,fd_,dirp_,count_);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
close_free_ret_enomem(int fd_,
|
||||||
|
void *buf_)
|
||||||
|
{
|
||||||
|
fs::close(fd_);
|
||||||
|
g_DENTS_BUF_POOL.free(buf_);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
readdir(const Branches &branches_,
|
||||||
|
const char *dirname_,
|
||||||
|
fuse_dirents_t *buf_)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
dev_t dev;
|
||||||
|
char *buf;
|
||||||
|
HashSet names;
|
||||||
|
string basepath;
|
||||||
|
struct linux_dirent64 *d;
|
||||||
|
|
||||||
|
buf = (char*)g_DENTS_BUF_POOL.alloc();
|
||||||
|
if(buf == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
for(size_t i = 0, ei = branches_.size(); i != ei; i++)
|
||||||
|
{
|
||||||
|
int dirfd;
|
||||||
|
int64_t nread;
|
||||||
|
uint64_t namelen;
|
||||||
|
|
||||||
|
basepath = fs::path::make(&branches_[i].path,dirname_);
|
||||||
|
|
||||||
|
dirfd = fs::open_dir_ro(basepath);
|
||||||
|
if(dirfd == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
dev = fs::devid(dirfd);
|
||||||
|
if(dev == (dev_t)-1)
|
||||||
|
dev = i;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
nread = l::getdents64(dirfd,buf,g_DENTS_BUF_POOL.size());
|
||||||
|
if(nread == -1)
|
||||||
|
break;
|
||||||
|
if(nread == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
for(int64_t pos = 0; pos < nread;)
|
||||||
|
{
|
||||||
|
d = (struct linux_dirent64*)(buf + pos);
|
||||||
|
namelen = (d->d_reclen - offsetof(struct linux_dirent64,d_name));
|
||||||
|
|
||||||
|
rv = names.put(d->d_name,namelen);
|
||||||
|
if(rv == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
d->d_ino = fs::inode::recompute(d->d_ino,dev);
|
||||||
|
|
||||||
|
rv = fuse_dirents_add_linux(buf_,d);
|
||||||
|
if(rv)
|
||||||
|
return close_free_ret_enomem(dirfd,buf);
|
||||||
|
|
||||||
|
pos += d->d_reclen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::close(dirfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_DENTS_BUF_POOL.free(buf);
|
||||||
|
|
||||||
|
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_);
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
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
|
||||||
@ -14,125 +16,8 @@
|
|||||||
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
|
#ifdef __linux__
|
||||||
|
# include "fuse_readdir_plus_linux.icpp"
|
||||||
#include "config.hpp"
|
#else
|
||||||
#include "dirinfo.hpp"
|
# include "fuse_readdir_plus_posix.icpp"
|
||||||
#include "errno.hpp"
|
#endif
|
||||||
#include "fs_base_closedir.hpp"
|
|
||||||
#include "fs_base_dirfd.hpp"
|
|
||||||
#include "fs_base_opendir.hpp"
|
|
||||||
#include "fs_base_readdir.hpp"
|
|
||||||
#include "fs_base_fstatat.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;
|
|
||||||
|
|
||||||
#define NO_OFFSET 0
|
|
||||||
|
|
||||||
|
|
||||||
static
|
|
||||||
int
|
|
||||||
dot_or_dotdot(const char *s_)
|
|
||||||
{
|
|
||||||
return ((s_[0] == '.') &&
|
|
||||||
((s_[1] == '\0') ||
|
|
||||||
((s_[1] == '.') && (s_[2] == '\0'))));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
namespace l
|
|
||||||
{
|
|
||||||
static
|
|
||||||
int
|
|
||||||
readdir_plus(const Branches &branches_,
|
|
||||||
const char *dirname_,
|
|
||||||
fuse_dirents_t *buf_)
|
|
||||||
{
|
|
||||||
dev_t dev;
|
|
||||||
HashSet names;
|
|
||||||
string basepath;
|
|
||||||
struct stat st;
|
|
||||||
fuse_entry_t entry;
|
|
||||||
|
|
||||||
entry.nodeid = 0;
|
|
||||||
entry.generation = 0;
|
|
||||||
entry.entry_valid = 1;
|
|
||||||
entry.attr_valid = 1;
|
|
||||||
entry.entry_valid_nsec = 0;
|
|
||||||
entry.attr_valid_nsec = 0;
|
|
||||||
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;
|
|
||||||
|
|
||||||
rv = fs::fstatat_nofollow(dirfd,de->d_name,&st);
|
|
||||||
if(rv == -1)
|
|
||||||
memset(&st,0,sizeof(st));
|
|
||||||
|
|
||||||
de->d_ino = fs::inode::recompute(de->d_ino,dev);
|
|
||||||
st.st_ino = fs::inode::recompute(st.st_ino,dev);
|
|
||||||
|
|
||||||
rv = fuse_dirents_add_plus(buf_,de,&entry,&st);
|
|
||||||
if(rv)
|
|
||||||
return (fs::closedir(dh),-ENOMEM);
|
|
||||||
}
|
|
||||||
|
|
||||||
fs::closedir(dh);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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::get(fc);
|
|
||||||
const ugid::Set ugid(fc->uid,fc->gid);
|
|
||||||
const rwlock::ReadGuard readlock(&config.branches_lock);
|
|
||||||
|
|
||||||
return l::readdir_plus(config.branches,
|
|
||||||
di->fusepath.c_str(),
|
|
||||||
buf_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
172
src/fuse_readdir_plus_linux.icpp
Normal file
172
src/fuse_readdir_plus_linux.icpp
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2019, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _DEFAULT_SOURCE
|
||||||
|
|
||||||
|
#include "config.hpp"
|
||||||
|
#include "dirinfo.hpp"
|
||||||
|
#include "errno.hpp"
|
||||||
|
#include "fs_base_close.hpp"
|
||||||
|
#include "fs_base_fstatat.hpp"
|
||||||
|
#include "fs_base_open.hpp"
|
||||||
|
#include "fs_base_stat.hpp"
|
||||||
|
#include "fs_devid.hpp"
|
||||||
|
#include "fs_inode.hpp"
|
||||||
|
#include "fs_path.hpp"
|
||||||
|
#include "hashset.hpp"
|
||||||
|
#include "mempools.hpp"
|
||||||
|
#include "rwlock.hpp"
|
||||||
|
#include "ugid.hpp"
|
||||||
|
|
||||||
|
#include <fuse.h>
|
||||||
|
#include <fuse_dirents.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
struct linux_dirent64
|
||||||
|
{
|
||||||
|
uint64_t d_ino;
|
||||||
|
int64_t d_off;
|
||||||
|
uint16_t d_reclen;
|
||||||
|
uint8_t d_type;
|
||||||
|
char d_name[];
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace l
|
||||||
|
{
|
||||||
|
static
|
||||||
|
inline
|
||||||
|
int
|
||||||
|
getdents64(unsigned int fd_,
|
||||||
|
char *dirp_,
|
||||||
|
unsigned int count_)
|
||||||
|
{
|
||||||
|
return syscall(SYS_getdents64,fd_,dirp_,count_);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
close_free_ret_enomem(int fd_,
|
||||||
|
void *buf_)
|
||||||
|
{
|
||||||
|
fs::close(fd_);
|
||||||
|
g_DENTS_BUF_POOL.free(buf_);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
readdir_plus(const Branches &branches_,
|
||||||
|
const char *dirname_,
|
||||||
|
fuse_dirents_t *buf_)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
dev_t dev;
|
||||||
|
char *buf;
|
||||||
|
HashSet names;
|
||||||
|
string basepath;
|
||||||
|
struct stat st;
|
||||||
|
fuse_entry_t entry;
|
||||||
|
struct linux_dirent64 *d;
|
||||||
|
|
||||||
|
buf = (char*)g_DENTS_BUF_POOL.alloc();
|
||||||
|
|
||||||
|
entry.nodeid = 0;
|
||||||
|
entry.generation = 0;
|
||||||
|
entry.entry_valid = 1;
|
||||||
|
entry.attr_valid = 1;
|
||||||
|
entry.entry_valid_nsec = 0;
|
||||||
|
entry.attr_valid_nsec = 0;
|
||||||
|
for(size_t i = 0, ei = branches_.size(); i != ei; i++)
|
||||||
|
{
|
||||||
|
int dirfd;
|
||||||
|
int64_t nread;
|
||||||
|
uint64_t namelen;
|
||||||
|
|
||||||
|
basepath = fs::path::make(&branches_[i].path,dirname_);
|
||||||
|
|
||||||
|
dirfd = fs::open_dir_ro(basepath);
|
||||||
|
if(dirfd == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
dev = fs::devid(dirfd);
|
||||||
|
if(dev == (dev_t)-1)
|
||||||
|
dev = i;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
nread = l::getdents64(dirfd,buf,g_DENTS_BUF_POOL.size());
|
||||||
|
if(nread == -1)
|
||||||
|
break;
|
||||||
|
if(nread == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
for(int64_t pos = 0; pos < nread;)
|
||||||
|
{
|
||||||
|
d = (struct linux_dirent64*)(buf + pos);
|
||||||
|
namelen = (d->d_reclen - offsetof(struct linux_dirent64,d_name));
|
||||||
|
|
||||||
|
rv = names.put(d->d_name,namelen);
|
||||||
|
if(rv == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rv = fs::fstatat_nofollow(dirfd,d->d_name,&st);
|
||||||
|
if(rv == -1)
|
||||||
|
memset(&st,0,sizeof(st));
|
||||||
|
|
||||||
|
d->d_ino = fs::inode::recompute(d->d_ino,dev);
|
||||||
|
st.st_ino = d->d_ino;
|
||||||
|
|
||||||
|
rv = fuse_dirents_add_linux_plus(buf_,d,&entry,&st);
|
||||||
|
if(rv)
|
||||||
|
return close_free_ret_enomem(dirfd,buf);
|
||||||
|
|
||||||
|
pos += d->d_reclen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::close(dirfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_DENTS_BUF_POOL.free(buf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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::get(fc);
|
||||||
|
const ugid::Set ugid(fc->uid,fc->gid);
|
||||||
|
const rwlock::ReadGuard readlock(&config.branches_lock);
|
||||||
|
|
||||||
|
return l::readdir_plus(config.branches,
|
||||||
|
di->fusepath.c_str(),
|
||||||
|
buf_);
|
||||||
|
}
|
||||||
|
}
|
125
src/fuse_readdir_plus_posix.icpp
Normal file
125
src/fuse_readdir_plus_posix.icpp
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2019, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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_fstatat.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_plus(const Branches &branches_,
|
||||||
|
const char *dirname_,
|
||||||
|
fuse_dirents_t *buf_)
|
||||||
|
{
|
||||||
|
dev_t dev;
|
||||||
|
HashSet names;
|
||||||
|
string basepath;
|
||||||
|
struct stat st;
|
||||||
|
fuse_entry_t entry;
|
||||||
|
|
||||||
|
entry.nodeid = 0;
|
||||||
|
entry.generation = 0;
|
||||||
|
entry.entry_valid = 1;
|
||||||
|
entry.attr_valid = 1;
|
||||||
|
entry.entry_valid_nsec = 0;
|
||||||
|
entry.attr_valid_nsec = 0;
|
||||||
|
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;
|
||||||
|
|
||||||
|
rv = fs::fstatat_nofollow(dirfd,de->d_name,&st);
|
||||||
|
if(rv == -1)
|
||||||
|
memset(&st,0,sizeof(st));
|
||||||
|
|
||||||
|
de->d_ino = fs::inode::recompute(de->d_ino,dev);
|
||||||
|
st.st_ino = de->d_ino;
|
||||||
|
|
||||||
|
rv = fuse_dirents_add_plus(buf_,de,&entry,&st);
|
||||||
|
if(rv)
|
||||||
|
return (fs::closedir(dh),-ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::closedir(dh);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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::get(fc);
|
||||||
|
const ugid::Set ugid(fc->uid,fc->gid);
|
||||||
|
const rwlock::ReadGuard readlock(&config.branches_lock);
|
||||||
|
|
||||||
|
return l::readdir_plus(config.branches,
|
||||||
|
di->fusepath.c_str(),
|
||||||
|
buf_);
|
||||||
|
}
|
||||||
|
}
|
111
src/fuse_readdir_posix.icpp
Normal file
111
src/fuse_readdir_posix.icpp
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2019, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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_);
|
||||||
|
}
|
||||||
|
}
|
69
src/locked_fixed_mem_pool.hpp
Normal file
69
src/locked_fixed_mem_pool.hpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
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 "fixed_mem_pool.hpp"
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
template<size_t SIZE>
|
||||||
|
class LockedFixedMemPool
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LockedFixedMemPool()
|
||||||
|
{
|
||||||
|
pthread_mutex_init(&_mutex,NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
~LockedFixedMemPool()
|
||||||
|
{
|
||||||
|
pthread_mutex_destroy(&_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void*
|
||||||
|
alloc(void)
|
||||||
|
{
|
||||||
|
void *mem;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&_mutex);
|
||||||
|
mem = _fmp.alloc();
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
free(void *mem_)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&_mutex);
|
||||||
|
_fmp.free(mem_);
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
size(void)
|
||||||
|
{
|
||||||
|
return _fmp.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
FixedMemPool<SIZE> _fmp;
|
||||||
|
pthread_mutex_t _mutex;
|
||||||
|
};
|
21
src/mempools.cpp
Normal file
21
src/mempools.cpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
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 "locked_fixed_mem_pool.hpp"
|
||||||
|
|
||||||
|
LockedFixedMemPool<128 * 1024> g_DENTS_BUF_POOL;
|
23
src/mempools.hpp
Normal file
23
src/mempools.hpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
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 "locked_fixed_mem_pool.hpp"
|
||||||
|
|
||||||
|
extern LockedFixedMemPool<128 * 1024> g_DENTS_BUF_POOL;
|
Loading…
x
Reference in New Issue
Block a user