38#define FUSE_USE_VERSION FUSE_MAKE_VERSION(3, 12) 
   40#include <fuse_lowlevel.h> 
   56#include "passthrough_helpers.h" 
   62#if defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 6) && !defined __cplusplus 
   63_Static_assert(
sizeof(
fuse_ino_t) >= 
sizeof(uintptr_t),
 
   64               "fuse_ino_t too small to hold uintptr_t values!");
 
   66struct _uintptr_to_must_hold_fuse_ino_t_dummy_struct \
 
   67        { 
unsigned _uintptr_to_must_hold_fuse_ino_t:
 
   68                        ((
sizeof(
fuse_ino_t) >= 
sizeof(uintptr_t)) ? 1 : -1); };
 
   72        struct lo_inode *next; 
 
   73        struct lo_inode *prev; 
 
   87        pthread_mutex_t mutex;
 
   99static const struct fuse_opt lo_opts[] = {
 
  101          offsetof(
struct lo_data, writeback), 1 },
 
  103          offsetof(
struct lo_data, writeback), 0 },
 
  105          offsetof(
struct lo_data, source), 0 },
 
  107          offsetof(
struct lo_data, flock), 1 },
 
  109          offsetof(
struct lo_data, flock), 0 },
 
  111          offsetof(
struct lo_data, xattr), 1 },
 
  113          offsetof(
struct lo_data, xattr), 0 },
 
  115          offsetof(
struct lo_data, timeout), 0 },
 
  117          offsetof(
struct lo_data, timeout_set), 1 },
 
  119          offsetof(
struct lo_data, cache), CACHE_NEVER },
 
  121          offsetof(
struct lo_data, cache), CACHE_NORMAL },
 
  123          offsetof(
struct lo_data, cache), CACHE_ALWAYS },
 
  128static void passthrough_ll_help(
void)
 
  131"    -o writeback           Enable writeback\n" 
  132"    -o no_writeback        Disable write back\n" 
  133"    -o source=/home/dir    Source directory to be mounted\n" 
  134"    -o flock               Enable flock\n" 
  135"    -o no_flock            Disable flock\n" 
  136"    -o xattr               Enable xattr\n" 
  137"    -o no_xattr            Disable xattr\n" 
  138"    -o timeout=1.0         Caching timeout\n" 
  139"    -o timeout=0/1         Timeout is set\n" 
  140"    -o cache=never         Disable cache\n" 
  141"    -o cache=auto          Auto enable cache\n" 
  142"    -o cache=always        Cache always\n");
 
  152        if (ino == FUSE_ROOT_ID)
 
  153                return &lo_data(req)->root;
 
  155                return (
struct lo_inode *) (uintptr_t) ino;
 
  160        return lo_inode(req, ino)->fd;
 
  165        return lo_data(req)->debug != 0;
 
  168static void lo_init(
void *userdata,
 
  171        struct lo_data *lo = (
struct lo_data *)userdata;
 
  176                if (lo->debug && has_flag)
 
  178                                 "lo_init: activating writeback\n");
 
  182                if (lo->debug && has_flag)
 
  184                                 "lo_init: activating flock locks\n");
 
  191static void lo_destroy(
void *userdata)
 
  193        struct lo_data *lo = (
struct lo_data*) userdata;
 
  195        while (lo->root.next != &lo->root) {
 
  196                struct lo_inode* next = lo->root.next;
 
  197                lo->root.next = next->next;
 
  208        struct lo_data *lo = lo_data(req);
 
  209        int fd = fi ? fi->
fh : lo_fd(req, ino);
 
  213        res = fstatat(fd, 
"", &buf, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
 
  225        struct lo_inode *inode = lo_inode(req, ino);
 
  229        if (valid & FUSE_SET_ATTR_MODE) {
 
  231                        res = fchmod(fi->
fh, attr->st_mode);
 
  233                        sprintf(procname, 
"/proc/self/fd/%i", ifd);
 
  234                        res = chmod(procname, attr->st_mode);
 
  239        if (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID)) {
 
  240                uid_t uid = (valid & FUSE_SET_ATTR_UID) ?
 
  241                        attr->st_uid : (uid_t) -1;
 
  242                gid_t gid = (valid & FUSE_SET_ATTR_GID) ?
 
  243                        attr->st_gid : (gid_t) -1;
 
  245                res = fchownat(ifd, 
"", uid, gid,
 
  246                               AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
 
  250        if (valid & FUSE_SET_ATTR_SIZE) {
 
  252                        res = ftruncate(fi->
fh, attr->st_size);
 
  254                        sprintf(procname, 
"/proc/self/fd/%i", ifd);
 
  255                        res = truncate(procname, attr->st_size);
 
  260        if (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
 
  261                struct timespec tv[2];
 
  265                tv[0].tv_nsec = UTIME_OMIT;
 
  266                tv[1].tv_nsec = UTIME_OMIT;
 
  268                if (valid & FUSE_SET_ATTR_ATIME_NOW)
 
  269                        tv[0].tv_nsec = UTIME_NOW;
 
  270                else if (valid & FUSE_SET_ATTR_ATIME)
 
  271                        tv[0] = attr->st_atim;
 
  273                if (valid & FUSE_SET_ATTR_MTIME_NOW)
 
  274                        tv[1].tv_nsec = UTIME_NOW;
 
  275                else if (valid & FUSE_SET_ATTR_MTIME)
 
  276                        tv[1] = attr->st_mtim;
 
  279                        res = futimens(fi->
fh, tv);
 
  281                        sprintf(procname, 
"/proc/self/fd/%i", ifd);
 
  282                        res = utimensat(AT_FDCWD, procname, tv, 0);
 
  288        return lo_getattr(req, ino, fi);
 
  295static struct lo_inode *lo_find(
struct lo_data *lo, 
struct stat *st)
 
  298        struct lo_inode *ret = NULL;
 
  300        pthread_mutex_lock(&lo->mutex);
 
  301        for (p = lo->root.next; p != &lo->root; p = p->next) {
 
  302                if (p->ino == st->st_ino && p->dev == st->st_dev) {
 
  303                        assert(p->refcount > 0);
 
  309        pthread_mutex_unlock(&lo->mutex);
 
  314static struct lo_inode *create_new_inode(
int fd, 
struct fuse_entry_param *e, 
struct lo_data* lo)
 
  316        struct lo_inode *inode = NULL;
 
  317        struct lo_inode *prev, *next;
 
  319        inode = calloc(1, 
sizeof(
struct lo_inode));
 
  325        inode->ino = e->
attr.st_ino;
 
  326        inode->dev = e->
attr.st_dev;
 
  328        pthread_mutex_lock(&lo->mutex);
 
  335        pthread_mutex_unlock(&lo->mutex);
 
  342        struct lo_data *lo = lo_data(req);
 
  344        memset(e, 0, 
sizeof(*e));
 
  348        res = fstatat(fd, 
"", &e->
attr, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
 
  352        e->
ino = (uintptr_t) create_new_inode(dup(fd), e, lo);
 
  355                fuse_log(FUSE_LOG_DEBUG, 
"  %lli/%lli -> %lli\n",
 
  356                        (
unsigned long long) parent, fd, (
unsigned long long) e->
ino);
 
  368        struct lo_data *lo = lo_data(req);
 
  369        struct lo_inode *inode;
 
  371        memset(e, 0, 
sizeof(*e));
 
  375        newfd = openat(lo_fd(req, parent), name, O_PATH | O_NOFOLLOW);
 
  379        res = fstatat(newfd, 
"", &e->
attr, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
 
  383        inode = lo_find(lo_data(req), &e->
attr);
 
  388                inode = create_new_inode(newfd, e, lo);
 
  392        e->
ino = (uintptr_t) inode;
 
  395                fuse_log(FUSE_LOG_DEBUG, 
"  %lli/%s -> %lli\n",
 
  396                        (
unsigned long long) parent, name, (
unsigned long long) e->
ino);
 
  413                fuse_log(FUSE_LOG_DEBUG, 
"lo_lookup(parent=%" PRIu64 
", name=%s)\n",
 
  416        err = lo_do_lookup(req, parent, name, &e);
 
  424                             const char *name, mode_t mode, dev_t rdev,
 
  429        struct lo_inode *dir = lo_inode(req, parent);
 
  432        res = mknod_wrapper(dir->fd, name, link, mode, rdev);
 
  438        saverr = lo_do_lookup(req, parent, name, &e);
 
  443                fuse_log(FUSE_LOG_DEBUG, 
"  %lli/%s -> %lli\n",
 
  444                        (
unsigned long long) parent, name, (
unsigned long long) e.
ino);
 
  454                     const char *name, mode_t mode, dev_t rdev)
 
  456        lo_mknod_symlink(req, parent, name, mode, rdev, NULL);
 
  462        lo_mknod_symlink(req, parent, name, S_IFDIR | mode, 0, NULL);
 
  465static void lo_symlink(
fuse_req_t req, 
const char *link,
 
  468        lo_mknod_symlink(req, parent, name, S_IFLNK, 0, link);
 
  475        struct lo_data *lo = lo_data(req);
 
  476        struct lo_inode *inode = lo_inode(req, ino);
 
  485        sprintf(procname, 
"/proc/self/fd/%i", inode->fd);
 
  486        res = linkat(AT_FDCWD, procname, lo_fd(req, parent), name,
 
  491        res = fstatat(inode->fd, 
"", &e.
attr, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
 
  495        pthread_mutex_lock(&lo->mutex);
 
  497        pthread_mutex_unlock(&lo->mutex);
 
  498        e.
ino = (uintptr_t) inode;
 
  501                fuse_log(FUSE_LOG_DEBUG, 
"  %lli/%s -> %lli\n",
 
  502                        (
unsigned long long) parent, name,
 
  503                        (
unsigned long long) e.
ino);
 
  517        res = unlinkat(lo_fd(req, parent), name, AT_REMOVEDIR);
 
  533        res = renameat(lo_fd(req, parent), name,
 
  534                        lo_fd(req, newparent), newname);
 
  543        res = unlinkat(lo_fd(req, parent), name, 0);
 
  548static void unref_inode(
struct lo_data *lo, 
struct lo_inode *inode, uint64_t n)
 
  553        pthread_mutex_lock(&lo->mutex);
 
  554        assert(inode->refcount >= n);
 
  555        inode->refcount -= n;
 
  556        if (!inode->refcount) {
 
  557                struct lo_inode *prev, *next;
 
  564                pthread_mutex_unlock(&lo->mutex);
 
  569                pthread_mutex_unlock(&lo->mutex);
 
  575        struct lo_data *lo = lo_data(req);
 
  576        struct lo_inode *inode = lo_inode(req, ino);
 
  579                fuse_log(FUSE_LOG_DEBUG, 
"  forget %lli %lli -%lli\n",
 
  580                        (
unsigned long long) ino,
 
  581                        (
unsigned long long) inode->refcount,
 
  582                        (
unsigned long long) nlookup);
 
  585        unref_inode(lo, inode, nlookup);
 
  590        lo_forget_one(req, ino, nlookup);
 
  594static void lo_forget_multi(
fuse_req_t req, 
size_t count,
 
  595                                struct fuse_forget_data *forgets)
 
  599        for (i = 0; i < count; i++)
 
  600                lo_forget_one(req, forgets[i].ino, forgets[i].nlookup);
 
  606        char buf[PATH_MAX + 1];
 
  609        res = readlinkat(lo_fd(req, ino), 
"", buf, 
sizeof(buf));
 
  613        if (res == 
sizeof(buf))
 
  623        struct dirent *entry;
 
  629        return (
struct lo_dirp *) (uintptr_t) fi->
fh;
 
  635        struct lo_data *lo = lo_data(req);
 
  639        d = calloc(1, 
sizeof(
struct lo_dirp));
 
  643        fd = openat(lo_fd(req, ino), 
".", O_RDONLY);
 
  647        d->dp = fdopendir(fd);
 
  654        fi->
fh = (uintptr_t) d;
 
  655        if (lo->cache != CACHE_NEVER)
 
  657        if (lo->cache == CACHE_ALWAYS)
 
  673static int is_dot_or_dotdot(
const char *name)
 
  675        return name[0] == 
'.' && (name[1] == 
'\0' ||
 
  676                                  (name[1] == 
'.' && name[2] == 
'\0'));
 
  682        struct lo_dirp *d = lo_dirp(fi);
 
  690        buf = calloc(1, size);
 
  697        if (offset != d->offset) {
 
  698                seekdir(d->dp, offset);
 
  709                        d->entry = readdir(d->dp);
 
  719                nextoff = d->entry->d_off;
 
  720                name = d->entry->d_name;
 
  724                        if (is_dot_or_dotdot(name)) {
 
  726                                        .
attr.st_ino = d->entry->d_ino,
 
  727                                        .attr.st_mode = d->entry->d_type << 12,
 
  730                                err = lo_do_lookup(req, ino, name, &e);
 
  740                                .st_ino = d->entry->d_ino,
 
  741                                .st_mode = d->entry->d_type << 12,
 
  748                                lo_forget_one(req, entry_ino, 1);
 
  765    if (err && rem == size)
 
  775        lo_do_readdir(req, ino, size, offset, fi, 0);
 
  781        lo_do_readdir(req, ino, size, offset, fi, 1);
 
  786        struct lo_dirp *d = lo_dirp(fi);
 
  797        struct lo_data *lo = lo_data(req);
 
  802                fuse_log(FUSE_LOG_DEBUG, 
"lo_tmpfile(parent=%" PRIu64 
")\n",
 
  805        fd = openat(lo_fd(req, parent), 
".",
 
  806                    (fi->
flags | O_TMPFILE) & ~O_NOFOLLOW, mode);
 
  811        if (lo->cache == CACHE_NEVER)
 
  813        else if (lo->cache == CACHE_ALWAYS)
 
  821        err = fill_entry_param_new_inode(req, parent, fd, &e); 
 
  832        struct lo_data *lo = lo_data(req);
 
  837                fuse_log(FUSE_LOG_DEBUG, 
"lo_create(parent=%" PRIu64 
", name=%s)\n",
 
  840        fd = openat(lo_fd(req, parent), name,
 
  841                    (fi->
flags | O_CREAT) & ~O_NOFOLLOW, mode);
 
  846        if (lo->cache == CACHE_NEVER)
 
  848        else if (lo->cache == CACHE_ALWAYS)
 
  856        err = lo_do_lookup(req, parent, name, &e);
 
  867        int fd = dirfd(lo_dirp(fi)->dp);
 
  880        struct lo_data *lo = lo_data(req);
 
  883                fuse_log(FUSE_LOG_DEBUG, 
"lo_open(ino=%" PRIu64 
", flags=%d)\n",
 
  888        if (lo->writeback && (fi->
flags & O_ACCMODE) == O_WRONLY) {
 
  889                fi->
flags &= ~O_ACCMODE;
 
  899        if (lo->writeback && (fi->
flags & O_APPEND))
 
  900                fi->
flags &= ~O_APPEND;
 
  902        sprintf(buf, 
"/proc/self/fd/%i", lo_fd(req, ino));
 
  903        fd = open(buf, fi->
flags & ~O_NOFOLLOW);
 
  908        if (lo->cache == CACHE_NEVER)
 
  910        else if (lo->cache == CACHE_ALWAYS)
 
  916        if (fi->
flags & O_DIRECT)
 
  939        res = close(dup(fi->
fh));
 
  949                res = fdatasync(fi->
fh);
 
  961                fuse_log(FUSE_LOG_DEBUG, 
"lo_read(ino=%" PRIu64 
", size=%zd, " 
  962                        "off=%lu)\n", ino, size, (
unsigned long) offset);
 
  984                fuse_log(FUSE_LOG_DEBUG, 
"lo_write(ino=%" PRIu64 
", size=%zd, off=%lu)\n",
 
  985                        ino, out_buf.
buf[0].
size, (
unsigned long) 
off);
 
  997        struct statvfs stbuf;
 
  999        res = fstatvfs(lo_fd(req, ino), &stbuf);
 
 1009        int err = EOPNOTSUPP;
 
 1012#ifdef HAVE_FALLOCATE 
 1013        err = fallocate(fi->
fh, mode, offset, length);
 
 1017#elif defined(HAVE_POSIX_FALLOCATE) 
 1023        err = posix_fallocate(fi->
fh, offset, length);
 
 1035        res = flock(fi->
fh, op);
 
 1045        struct lo_inode *inode = lo_inode(req, ino);
 
 1050        if (!lo_data(req)->xattr)
 
 1053        if (lo_debug(req)) {
 
 1054                fuse_log(FUSE_LOG_DEBUG, 
"lo_getxattr(ino=%" PRIu64 
", name=%s size=%zd)\n",
 
 1058        sprintf(procname, 
"/proc/self/fd/%i", inode->fd);
 
 1061                value = malloc(size);
 
 1065                ret = getxattr(procname, name, value, size);
 
 1074                ret = getxattr(procname, name, NULL, 0);
 
 1095        struct lo_inode *inode = lo_inode(req, ino);
 
 1100        if (!lo_data(req)->xattr)
 
 1103        if (lo_debug(req)) {
 
 1104                fuse_log(FUSE_LOG_DEBUG, 
"lo_listxattr(ino=%" PRIu64 
", size=%zd)\n",
 
 1108        sprintf(procname, 
"/proc/self/fd/%i", inode->fd);
 
 1111                value = malloc(size);
 
 1115                ret = listxattr(procname, value, size);
 
 1124                ret = listxattr(procname, NULL, 0);
 
 1142                        const char *value, 
size_t size, 
int flags)
 
 1145        struct lo_inode *inode = lo_inode(req, ino);
 
 1150        if (!lo_data(req)->xattr)
 
 1153        if (lo_debug(req)) {
 
 1154                fuse_log(FUSE_LOG_DEBUG, 
"lo_setxattr(ino=%" PRIu64 
", name=%s value=%s size=%zd)\n",
 
 1155                        ino, name, value, size);
 
 1158        sprintf(procname, 
"/proc/self/fd/%i", inode->fd);
 
 1160        ret = setxattr(procname, name, value, size, flags);
 
 1161        saverr = ret == -1 ? errno : 0;
 
 1170        struct lo_inode *inode = lo_inode(req, ino);
 
 1175        if (!lo_data(req)->xattr)
 
 1178        if (lo_debug(req)) {
 
 1179                fuse_log(FUSE_LOG_DEBUG, 
"lo_removexattr(ino=%" PRIu64 
", name=%s)\n",
 
 1183        sprintf(procname, 
"/proc/self/fd/%i", inode->fd);
 
 1185        ret = removexattr(procname, name);
 
 1186        saverr = ret == -1 ? errno : 0;
 
 1192#ifdef HAVE_COPY_FILE_RANGE 
 1202                fuse_log(FUSE_LOG_DEBUG, 
"lo_copy_file_range(ino=%" PRIu64 
"/fd=%lu, " 
 1203                                "off=%lu, ino=%" PRIu64 
"/fd=%lu, " 
 1204                                "off=%lu, size=%zd, flags=0x%x)\n",
 
 1205                        ino_in, fi_in->
fh, off_in, ino_out, fi_out->
fh, off_out,
 
 1208        res = copy_file_range(fi_in->
fh, &off_in, fi_out->
fh, &off_out, len,
 
 1223        res = lseek(fi->
fh, off, whence);
 
 1232        .destroy        = lo_destroy,
 
 1233        .lookup         = lo_lookup,
 
 1236        .symlink        = lo_symlink,
 
 1238        .unlink         = lo_unlink,
 
 1240        .rename         = lo_rename,
 
 1241        .forget         = lo_forget,
 
 1242        .forget_multi   = lo_forget_multi,
 
 1243        .getattr        = lo_getattr,
 
 1244        .setattr        = lo_setattr,
 
 1245        .readlink       = lo_readlink,
 
 1246        .opendir        = lo_opendir,
 
 1247        .readdir        = lo_readdir,
 
 1248        .readdirplus    = lo_readdirplus,
 
 1249        .releasedir     = lo_releasedir,
 
 1250        .fsyncdir       = lo_fsyncdir,
 
 1251        .create         = lo_create,
 
 1252        .tmpfile        = lo_tmpfile,
 
 1254        .release        = lo_release,
 
 1258        .write_buf      = lo_write_buf,
 
 1259        .statfs         = lo_statfs,
 
 1260        .fallocate      = lo_fallocate,
 
 1262        .getxattr       = lo_getxattr,
 
 1263        .listxattr      = lo_listxattr,
 
 1264        .setxattr       = lo_setxattr,
 
 1265        .removexattr    = lo_removexattr,
 
 1266#ifdef HAVE_COPY_FILE_RANGE 
 1267        .copy_file_range = lo_copy_file_range,
 
 1272int main(
int argc, 
char *argv[])
 
 1275        struct fuse_session *se;
 
 1278        struct lo_data lo = { .debug = 0,
 
 1285        pthread_mutex_init(&lo.mutex, NULL);
 
 1286        lo.root.next = lo.root.prev = &lo.root;
 
 1288        lo.cache = CACHE_NORMAL;
 
 1290        if (fuse_parse_cmdline(&args, &opts) != 0)
 
 1292        if (opts.show_help) {
 
 1293                printf(
"usage: %s [options] <mountpoint>\n\n", argv[0]);
 
 1296                passthrough_ll_help();
 
 1299        } 
else if (opts.show_version) {
 
 1306        if(opts.mountpoint == NULL) {
 
 1307                printf(
"usage: %s [options] <mountpoint>\n", argv[0]);
 
 1308                printf(
"       %s --help\n", argv[0]);
 
 1316        lo.debug = opts.debug;
 
 1317        lo.root.refcount = 2;
 
 1322                res = lstat(lo.source, &stat);
 
 1324                        fuse_log(FUSE_LOG_ERR, 
"failed to stat source (\"%s\"): %m\n",
 
 1328                if (!S_ISDIR(stat.st_mode)) {
 
 1329                        fuse_log(FUSE_LOG_ERR, 
"source is not a directory\n");
 
 1334                lo.source = strdup(
"/");
 
 1336                        fuse_log(FUSE_LOG_ERR, 
"fuse: memory allocation failed\n");
 
 1340        if (!lo.timeout_set) {
 
 1351                        lo.timeout = 86400.0;
 
 1354        } 
else if (lo.timeout < 0) {
 
 1355                fuse_log(FUSE_LOG_ERR, 
"timeout is negative (%lf)\n",
 
 1360        lo.root.fd = open(lo.source, O_PATH);
 
 1361        if (lo.root.fd == -1) {
 
 1362                fuse_log(FUSE_LOG_ERR, 
"open(\"%s\", O_PATH): %m\n",
 
 1367        se = fuse_session_new(&args, &lo_oper, 
sizeof(lo_oper), &lo);
 
 1380        if (opts.singlethread)
 
 1383                config = fuse_loop_cfg_create();
 
 1384                fuse_loop_cfg_set_clone_fd(config, opts.clone_fd);
 
 1385                fuse_loop_cfg_set_max_threads(config, opts.max_threads);
 
 1386                ret = fuse_session_loop_mt(se, config);
 
 1387                fuse_loop_cfg_destroy(config);
 
 1397        free(opts.mountpoint);
 
 1400        if (lo.root.fd >= 0)
 
int fuse_set_signal_handlers(struct fuse_session *se)
@ FUSE_CAP_WRITEBACK_CACHE
size_t fuse_buf_size(const struct fuse_bufvec *bufv)
ssize_t fuse_buf_copy(struct fuse_bufvec *dst, struct fuse_bufvec *src, enum fuse_buf_copy_flags flags)
const char * fuse_pkgversion(void)
void fuse_remove_signal_handlers(struct fuse_session *se)
int fuse_daemonize(int foreground)
void fuse_log(enum fuse_log_level level, const char *fmt,...)
void fuse_session_destroy(struct fuse_session *se)
int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv, enum fuse_buf_copy_flags flags)
int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *fi)
int fuse_reply_err(fuse_req_t req, int err)
void * fuse_req_userdata(fuse_req_t req)
int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
struct fuse_req * fuse_req_t
size_t fuse_add_direntry_plus(fuse_req_t req, char *buf, size_t bufsize, const char *name, const struct fuse_entry_param *e, off_t off)
int fuse_reply_readlink(fuse_req_t req, const char *link)
int fuse_session_loop(struct fuse_session *se)
int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
void fuse_session_unmount(struct fuse_session *se)
void fuse_cmdline_help(void)
void fuse_reply_none(fuse_req_t req)
void fuse_lowlevel_help(void)
int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf)
int fuse_reply_write(fuse_req_t req, size_t count)
int fuse_session_mount(struct fuse_session *se, const char *mountpoint)
int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e, const struct fuse_file_info *fi)
int fuse_reply_lseek(fuse_req_t req, off_t off)
void fuse_lowlevel_version(void)
size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize, const char *name, const struct stat *stbuf, off_t off)
int fuse_reply_attr(fuse_req_t req, const struct stat *attr, double attr_timeout)
int fuse_reply_xattr(fuse_req_t req, size_t count)
void fuse_opt_free_args(struct fuse_args *args)
int fuse_opt_parse(struct fuse_args *args, void *data, const struct fuse_opt opts[], fuse_opt_proc_t proc)
#define FUSE_ARGS_INIT(argc, argv)
enum fuse_buf_flags flags
uint32_t parallel_direct_writes
void(* init)(void *userdata, struct fuse_conn_info *conn)