26#define FUSE_USE_VERSION FUSE_MAKE_VERSION(3, 18)
32#ifdef HAVE_LIBULOCKMGR
50#include "passthrough_helpers.h"
80static int xmp_getattr(
const char *path,
struct stat *stbuf,
88 res = fstat(fi->
fh, stbuf);
90 res = lstat(path, stbuf);
97static int xmp_access(
const char *path,
int mask)
101 res = access(path, mask);
108static int xmp_readlink(
const char *path,
char *buf,
size_t size)
112 res = readlink(path, buf, size - 1);
122 struct dirent *entry;
126static int xmp_opendir(
const char *path,
struct fuse_file_info *fi)
129 struct xmp_dirp *d = malloc(
sizeof(
struct xmp_dirp));
133 d->dp = opendir(path);
142 fi->
fh = (
unsigned long) d;
148 return (
struct xmp_dirp *) (uintptr_t) fi->
fh;
151static int xmp_readdir(
const char *path,
void *buf,
fuse_fill_dir_t filler,
155 struct xmp_dirp *d = get_dirp(fi);
158 if (offset != d->offset) {
160 seekdir(d->dp, offset);
164 seekdir(d->dp, offset-1);
175 d->entry = readdir(d->dp);
180 if (flags & FUSE_READDIR_PLUS) {
183 res = fstatat(dirfd(d->dp), d->entry->d_name, &st,
184 AT_SYMLINK_NOFOLLOW);
186 fill_flags |= FUSE_FILL_DIR_PLUS;
189 if (!(fill_flags & FUSE_FILL_DIR_PLUS)) {
190 memset(&st, 0,
sizeof(st));
191 st.st_ino = d->entry->d_ino;
192 st.st_mode = d->entry->d_type << 12;
194 nextoff = telldir(d->dp);
202 if (filler(buf, d->entry->d_name, &st, nextoff, fill_flags))
212static int xmp_releasedir(
const char *path,
struct fuse_file_info *fi)
214 struct xmp_dirp *d = get_dirp(fi);
221static int xmp_mknod(
const char *path, mode_t mode, dev_t rdev)
226 res = mkfifo(path, mode);
228 res = mknod(path, mode, rdev);
235static int xmp_mkdir(
const char *path, mode_t mode)
239 res = mkdir(path, mode);
246static int xmp_unlink(
const char *path)
257static int xmp_rmdir(
const char *path)
268static int xmp_symlink(
const char *from,
const char *to)
272 res = symlink(from, to);
279static int xmp_rename(
const char *from,
const char *to,
unsigned int flags)
287 res = rename(from, to);
294static int xmp_link(
const char *from,
const char *to)
298 res = link(from, to);
305static int xmp_chmod(
const char *path, mode_t mode,
311 res = fchmod(fi->
fh, mode);
313 res = chmod(path, mode);
320static int xmp_chown(
const char *path, uid_t uid, gid_t gid,
326 res = fchown(fi->
fh, uid, gid);
328 res = lchown(path, uid, gid);
335static int xmp_truncate(
const char *path, off_t size,
341 res = ftruncate(fi->
fh, size);
343 res = truncate(path, size);
352static int xmp_utimens(
const char *path,
const struct timespec ts[2],
359 res = futimens(fi->
fh, ts);
361 res = utimensat(0, path, ts, AT_SYMLINK_NOFOLLOW);
369static int xmp_create(
const char *path, mode_t mode,
struct fuse_file_info *fi)
373 fd = open(path, fi->
flags, mode);
385 fd = open(path, fi->
flags);
392 if (fi->
flags & O_DIRECT) {
401static int xmp_read(
const char *path,
char *buf,
size_t size, off_t offset,
407 res = pread(fi->
fh, buf, size, offset);
414static int xmp_read_buf(
const char *path,
struct fuse_bufvec **bufp,
425 *src = FUSE_BUFVEC_INIT(size);
436static int xmp_write(
const char *path,
const char *
buf,
size_t size,
442 res = pwrite(fi->
fh,
buf, size, offset);
449static int xmp_write_buf(
const char *path,
struct fuse_bufvec *
buf,
463static int xmp_statfs(
const char *path,
struct statvfs *stbuf)
467 res = statvfs(path, stbuf);
484 res = close(dup(fi->
fh));
491static int xmp_release(
const char *path,
struct fuse_file_info *fi)
499static int xmp_fsync(
const char *path,
int isdatasync,
505#ifndef HAVE_FDATASYNC
509 res = fdatasync(fi->
fh);
519static int xmp_fallocate(
const char *path,
int mode,
524 return do_fallocate(fi->
fh, mode, offset, length);
529static int xmp_setxattr(
const char *path,
const char *name,
const char *value,
530 size_t size,
int flags)
532 int res = lsetxattr(path, name, value, size, flags);
538static int xmp_getxattr(
const char *path,
const char *name,
char *value,
541 int res = lgetxattr(path, name, value, size);
547static int xmp_listxattr(
const char *path,
char *list,
size_t size)
549 int res = llistxattr(path, list, size);
555static int xmp_removexattr(
const char *path,
const char *name)
557 int res = lremovexattr(path, name);
564#ifdef HAVE_LIBULOCKMGR
565static int xmp_lock(
const char *path,
struct fuse_file_info *fi,
int cmd,
575static int xmp_flock(
const char *path,
struct fuse_file_info *fi,
int op)
580 res = flock(fi->
fh, op);
587#ifdef HAVE_COPY_FILE_RANGE
588static ssize_t xmp_copy_file_range(
const char *path_in,
590 off_t off_in,
const char *path_out,
592 off_t off_out,
size_t len,
int flags)
598 res = copy_file_range(fi_in->
fh, &off_in, fi_out->
fh, &off_out, len,
607static off_t xmp_lseek(
const char *path, off_t
off,
int whence,
struct fuse_file_info *fi)
612 res = lseek(fi->
fh,
off, whence);
620static int xmp_statx(
const char *path,
int flags,
int mask,
struct statx *stxbuf,
629 res = statx(fd, path, flags | AT_SYMLINK_NOFOLLOW, mask, stxbuf);
639 .getattr = xmp_getattr,
640 .access = xmp_access,
641 .readlink = xmp_readlink,
642 .opendir = xmp_opendir,
643 .readdir = xmp_readdir,
644 .releasedir = xmp_releasedir,
647 .symlink = xmp_symlink,
648 .unlink = xmp_unlink,
650 .rename = xmp_rename,
654 .truncate = xmp_truncate,
656 .utimens = xmp_utimens,
658 .create = xmp_create,
661 .read_buf = xmp_read_buf,
663 .write_buf = xmp_write_buf,
664 .statfs = xmp_statfs,
666 .release = xmp_release,
668 .fallocate = xmp_fallocate,
670 .setxattr = xmp_setxattr,
671 .getxattr = xmp_getxattr,
672 .listxattr = xmp_listxattr,
673 .removexattr = xmp_removexattr,
675#ifdef HAVE_LIBULOCKMGR
679#ifdef HAVE_COPY_FILE_RANGE
680 .copy_file_range = xmp_copy_file_range,
688int main(
int argc,
char *argv[])
691 return fuse_main(argc, argv, &xmp_oper, NULL);
int(* fuse_fill_dir_t)(void *buf, const char *name, const struct stat *stbuf, off_t off, enum fuse_fill_dir_flags flags)
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)
@ FUSE_BUF_SPLICE_NONBLOCK
enum fuse_buf_flags flags
int32_t parallel_direct_writes
uint32_t parallel_direct_writes
void *(* init)(struct fuse_conn_info *conn, struct fuse_config *cfg)