From d597592e1f3bd64b586257f47315390042a9def1 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Fri, 26 Dec 2025 03:19:32 +0900 Subject: cmd/sharefs: rename fuse-helper to fuse-operations This is not really just library wrapper functions, but instead implements the callbacks, so fuse-operations makes more sense. Signed-off-by: Ophestra --- cmd/sharefs/fuse-helper.c | 282 ------------------------------------------ cmd/sharefs/fuse-helper.h | 33 ----- cmd/sharefs/fuse-operations.c | 282 ++++++++++++++++++++++++++++++++++++++++++ cmd/sharefs/fuse-operations.h | 33 +++++ cmd/sharefs/fuse.go | 7 +- cmd/sharefs/main.go | 4 - 6 files changed, 320 insertions(+), 321 deletions(-) delete mode 100644 cmd/sharefs/fuse-helper.c delete mode 100644 cmd/sharefs/fuse-helper.h create mode 100644 cmd/sharefs/fuse-operations.c create mode 100644 cmd/sharefs/fuse-operations.h (limited to 'cmd') diff --git a/cmd/sharefs/fuse-helper.c b/cmd/sharefs/fuse-helper.c deleted file mode 100644 index a1c511b4..00000000 --- a/cmd/sharefs/fuse-helper.c +++ /dev/null @@ -1,282 +0,0 @@ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE /* O_DIRECT */ -#endif - -#include -#include -#include - -/* TODO(ophestra): remove after 05ce67fea99ca09cd4b6625cff7aec9cc222dd5a reaches a release */ -#include - -#include "fuse-helper.h" - -/* MUST_TRANSLATE_PATHNAME translates a userspace pathname to a relative pathname; - * the resulting address points to a constant string or part of pathname, it is never heap allocated. */ -#define MUST_TRANSLATE_PATHNAME(pathname) \ - do { \ - if (pathname == NULL) \ - return -EINVAL; \ - while (*pathname == '/') \ - pathname++; \ - if (*pathname == '\0') \ - pathname = "."; \ - } while (0) - -/* GET_CONTEXT_PRIV obtains fuse context and private data for the calling thread. */ -#define GET_CONTEXT_PRIV(ctx, priv) \ - do { \ - ctx = fuse_get_context(); \ - priv = ctx->private_data; \ - } while (0) - -/* impl_getattr modifies a struct stat from the kernel to present to userspace; - * impl_getattr returns a negative errno style error code. */ -static int impl_getattr(struct fuse_context *ctx, struct stat *statbuf) { - /* allowlist of permitted types */ - if (!S_ISDIR(statbuf->st_mode) && !S_ISREG(statbuf->st_mode) && !S_ISLNK(statbuf->st_mode)) { - return -ENOTRECOVERABLE; /* returning an errno causes all operations on the file to return EIO */ - } - -#define OVERRIDE_PERM(v) (statbuf->st_mode & ~0777) | (v & 0777) - if (S_ISDIR(statbuf->st_mode)) - statbuf->st_mode = OVERRIDE_PERM(SHAREFS_PERM_DIR); - else if (S_ISREG(statbuf->st_mode)) - statbuf->st_mode = OVERRIDE_PERM(SHAREFS_PERM_REG); - else - statbuf->st_mode = 0; /* should always be symlink in this case */ - - statbuf->st_uid = ctx->uid; - statbuf->st_gid = SHAREFS_MEDIA_RW_ID; - statbuf->st_ctim = statbuf->st_mtim; - statbuf->st_nlink = 1; - return 0; -} - -/* fuse_operations implementation */ - -int sharefs_getattr(const char *pathname, struct stat *statbuf, struct fuse_file_info *fi) { - struct fuse_context *ctx; - struct sharefs_private *priv; - GET_CONTEXT_PRIV(ctx, priv); - MUST_TRANSLATE_PATHNAME(pathname); - - (void)fi; - - if (fstatat(priv->dirfd, pathname, statbuf, AT_SYMLINK_NOFOLLOW) == -1) - return -errno; - return impl_getattr(ctx, statbuf); -} - -int sharefs_readdir(const char *pathname, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi, enum fuse_readdir_flags flags) { - int fd; - DIR *dp; - struct stat st; - int ret = 0; - struct dirent *de; - - struct fuse_context *ctx; - struct sharefs_private *priv; - GET_CONTEXT_PRIV(ctx, priv); - MUST_TRANSLATE_PATHNAME(pathname); - - (void)offset; - (void)fi; - - if ((fd = openat(priv->dirfd, pathname, O_RDONLY | O_DIRECTORY | O_CLOEXEC)) == -1) - return -errno; - if ((dp = fdopendir(fd)) == NULL) { - close(fd); - return -errno; - } - - errno = 0; /* for the next readdir call */ - while ((de = readdir(dp)) != NULL) { - if (flags & FUSE_READDIR_PLUS) { - if (fstatat(dirfd(dp), de->d_name, &st, AT_SYMLINK_NOFOLLOW) == -1) { - ret = -errno; - break; - } - - if ((ret = impl_getattr(ctx, &st)) < 0) - break; - - errno = 0; - ret = filler(buf, de->d_name, &st, 0, FUSE_FILL_DIR_PLUS); - } else - ret = filler(buf, de->d_name, NULL, 0, 0); - - if (ret != 0) { - ret = errno != 0 ? -errno : -EIO; /* filler */ - break; - } - - errno = 0; /* for the next readdir call */ - } - if (ret == 0 && errno != 0) - ret = -errno; /* readdir */ - - closedir(dp); - return ret; -} - -int sharefs_mkdir(const char *pathname, mode_t mode) { - struct fuse_context *ctx; - struct sharefs_private *priv; - GET_CONTEXT_PRIV(ctx, priv); - MUST_TRANSLATE_PATHNAME(pathname); - - (void)mode; - - if (mkdirat(priv->dirfd, pathname, SHAREFS_PERM_DIR) == -1) - return -errno; - return 0; -} - -int sharefs_unlink(const char *pathname) { - struct fuse_context *ctx; - struct sharefs_private *priv; - GET_CONTEXT_PRIV(ctx, priv); - MUST_TRANSLATE_PATHNAME(pathname); - - if (unlinkat(priv->dirfd, pathname, 0) == -1) - return -errno; - return 0; -} - -int sharefs_rmdir(const char *pathname) { - struct fuse_context *ctx; - struct sharefs_private *priv; - GET_CONTEXT_PRIV(ctx, priv); - MUST_TRANSLATE_PATHNAME(pathname); - - if (unlinkat(priv->dirfd, pathname, AT_REMOVEDIR) == -1) - return -errno; - return 0; -} - -int sharefs_rename(const char *oldpath, const char *newpath, unsigned int flags) { - struct fuse_context *ctx; - struct sharefs_private *priv; - GET_CONTEXT_PRIV(ctx, priv); - MUST_TRANSLATE_PATHNAME(oldpath); - MUST_TRANSLATE_PATHNAME(newpath); - - /* TODO(ophestra): replace with wrapper after 05ce67fea99ca09cd4b6625cff7aec9cc222dd5a reaches a release */ - if (syscall(__NR_renameat2, priv->dirfd, oldpath, priv->dirfd, newpath, flags) == -1) - return -errno; - return 0; -} - -int sharefs_truncate(const char *pathname, off_t length, struct fuse_file_info *fi) { - int fd; - int ret; - - struct fuse_context *ctx; - struct sharefs_private *priv; - GET_CONTEXT_PRIV(ctx, priv); - MUST_TRANSLATE_PATHNAME(pathname); - - (void)fi; - - if ((fd = openat(priv->dirfd, pathname, O_WRONLY | O_CLOEXEC)) == -1) - return -errno; - if ((ret = ftruncate(fd, length)) == -1) - ret = -errno; - close(fd); - return ret; -} - -int sharefs_utimens(const char *pathname, const struct timespec times[2], struct fuse_file_info *fi) { - struct fuse_context *ctx; - struct sharefs_private *priv; - GET_CONTEXT_PRIV(ctx, priv); - MUST_TRANSLATE_PATHNAME(pathname); - - (void)fi; - - if (utimensat(priv->dirfd, pathname, times, AT_SYMLINK_NOFOLLOW) == -1) - return -errno; - return 0; -} - -int sharefs_create(const char *pathname, mode_t mode, struct fuse_file_info *fi) { - int fd; - - struct fuse_context *ctx; - struct sharefs_private *priv; - GET_CONTEXT_PRIV(ctx, priv); - MUST_TRANSLATE_PATHNAME(pathname); - - (void)mode; - - if ((fd = openat(priv->dirfd, pathname, fi->flags & ~SHAREFS_FORBIDDEN_FLAGS, SHAREFS_PERM_REG)) == -1) - return -errno; - fi->fh = fd; - return 0; -} - -int sharefs_open(const char *pathname, struct fuse_file_info *fi) { - int fd; - - struct fuse_context *ctx; - struct sharefs_private *priv; - GET_CONTEXT_PRIV(ctx, priv); - MUST_TRANSLATE_PATHNAME(pathname); - - if ((fd = openat(priv->dirfd, pathname, fi->flags & ~SHAREFS_FORBIDDEN_FLAGS)) == -1) - return -errno; - fi->fh = fd; - return 0; -} - -int sharefs_read(const char *pathname, char *buf, size_t count, off_t offset, struct fuse_file_info *fi) { - int ret; - - (void)pathname; - - if ((ret = pread(fi->fh, buf, count, offset)) == -1) - return -errno; - return ret; -} - -int sharefs_write(const char *pathname, const char *buf, size_t count, off_t offset, struct fuse_file_info *fi) { - int ret; - - (void)pathname; - - if ((ret = pwrite(fi->fh, buf, count, offset)) == -1) - return -errno; - return ret; -} - -int sharefs_statfs(const char *pathname, struct statvfs *statbuf) { - int fd; - int ret; - - struct fuse_context *ctx; - struct sharefs_private *priv; - GET_CONTEXT_PRIV(ctx, priv); - MUST_TRANSLATE_PATHNAME(pathname); - - if ((fd = openat(priv->dirfd, pathname, O_RDONLY | O_CLOEXEC)) == -1) - return -errno; - if ((ret = fstatvfs(fd, statbuf)) == -1) - ret = -errno; - close(fd); - return ret; -} - -int sharefs_release(const char *pathname, struct fuse_file_info *fi) { - (void)pathname; - - return close(fi->fh); -} - -int sharefs_fsync(const char *pathname, int datasync, struct fuse_file_info *fi) { - (void)pathname; - - if (datasync ? fdatasync(fi->fh) : fsync(fi->fh) == -1) - return -errno; - return 0; -} diff --git a/cmd/sharefs/fuse-helper.h b/cmd/sharefs/fuse-helper.h deleted file mode 100644 index 34f388b3..00000000 --- a/cmd/sharefs/fuse-helper.h +++ /dev/null @@ -1,33 +0,0 @@ -#define FUSE_USE_VERSION FUSE_MAKE_VERSION(3, 4) -#include -#include /* for fuse_cmdline_help */ - -#if (FUSE_VERSION < FUSE_MAKE_VERSION(3, 4)) -#error This package requires libfuse >= v3.4 -#endif - -#define SHAREFS_MEDIA_RW_ID (1 << 10) - 1 /* owning gid presented to userspace */ -#define SHAREFS_PERM_DIR 0700 /* permission bits for directories presented to userspace */ -#define SHAREFS_PERM_REG 0600 /* permission bits for regular files presented to userspace */ -#define SHAREFS_FORBIDDEN_FLAGS O_DIRECT /* these open flags are cleared unconditionally */ - -/* sharefs_private is populated by sharefs_init and contains process-wide context */ -struct sharefs_private { - int dirfd; /* source dirfd opened during sharefs_init */ -}; - -int sharefs_getattr(const char *pathname, struct stat *statbuf, struct fuse_file_info *fi); -int sharefs_readdir(const char *pathname, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi, enum fuse_readdir_flags flags); -int sharefs_mkdir(const char *pathname, mode_t mode); -int sharefs_unlink(const char *pathname); -int sharefs_rmdir(const char *pathname); -int sharefs_rename(const char *oldpath, const char *newpath, unsigned int flags); -int sharefs_truncate(const char *pathname, off_t length, struct fuse_file_info *fi); -int sharefs_utimens(const char *pathname, const struct timespec times[2], struct fuse_file_info *fi); -int sharefs_create(const char *pathname, mode_t mode, struct fuse_file_info *fi); -int sharefs_open(const char *pathname, struct fuse_file_info *fi); -int sharefs_read(const char *pathname, char *buf, size_t count, off_t offset, struct fuse_file_info *fi); -int sharefs_write(const char *pathname, const char *buf, size_t count, off_t offset, struct fuse_file_info *fi); -int sharefs_statfs(const char *pathname, struct statvfs *statbuf); -int sharefs_release(const char *pathname, struct fuse_file_info *fi); -int sharefs_fsync(const char *pathname, int datasync, struct fuse_file_info *fi); diff --git a/cmd/sharefs/fuse-operations.c b/cmd/sharefs/fuse-operations.c new file mode 100644 index 00000000..ecff1ad6 --- /dev/null +++ b/cmd/sharefs/fuse-operations.c @@ -0,0 +1,282 @@ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE /* O_DIRECT */ +#endif + +#include +#include +#include + +/* TODO(ophestra): remove after 05ce67fea99ca09cd4b6625cff7aec9cc222dd5a reaches a release */ +#include + +#include "fuse-operations.h" + +/* MUST_TRANSLATE_PATHNAME translates a userspace pathname to a relative pathname; + * the resulting address points to a constant string or part of pathname, it is never heap allocated. */ +#define MUST_TRANSLATE_PATHNAME(pathname) \ + do { \ + if (pathname == NULL) \ + return -EINVAL; \ + while (*pathname == '/') \ + pathname++; \ + if (*pathname == '\0') \ + pathname = "."; \ + } while (0) + +/* GET_CONTEXT_PRIV obtains fuse context and private data for the calling thread. */ +#define GET_CONTEXT_PRIV(ctx, priv) \ + do { \ + ctx = fuse_get_context(); \ + priv = ctx->private_data; \ + } while (0) + +/* impl_getattr modifies a struct stat from the kernel to present to userspace; + * impl_getattr returns a negative errno style error code. */ +static int impl_getattr(struct fuse_context *ctx, struct stat *statbuf) { + /* allowlist of permitted types */ + if (!S_ISDIR(statbuf->st_mode) && !S_ISREG(statbuf->st_mode) && !S_ISLNK(statbuf->st_mode)) { + return -ENOTRECOVERABLE; /* returning an errno causes all operations on the file to return EIO */ + } + +#define OVERRIDE_PERM(v) (statbuf->st_mode & ~0777) | (v & 0777) + if (S_ISDIR(statbuf->st_mode)) + statbuf->st_mode = OVERRIDE_PERM(SHAREFS_PERM_DIR); + else if (S_ISREG(statbuf->st_mode)) + statbuf->st_mode = OVERRIDE_PERM(SHAREFS_PERM_REG); + else + statbuf->st_mode = 0; /* should always be symlink in this case */ + + statbuf->st_uid = ctx->uid; + statbuf->st_gid = SHAREFS_MEDIA_RW_ID; + statbuf->st_ctim = statbuf->st_mtim; + statbuf->st_nlink = 1; + return 0; +} + +/* fuse_operations implementation */ + +int sharefs_getattr(const char *pathname, struct stat *statbuf, struct fuse_file_info *fi) { + struct fuse_context *ctx; + struct sharefs_private *priv; + GET_CONTEXT_PRIV(ctx, priv); + MUST_TRANSLATE_PATHNAME(pathname); + + (void)fi; + + if (fstatat(priv->dirfd, pathname, statbuf, AT_SYMLINK_NOFOLLOW) == -1) + return -errno; + return impl_getattr(ctx, statbuf); +} + +int sharefs_readdir(const char *pathname, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi, enum fuse_readdir_flags flags) { + int fd; + DIR *dp; + struct stat st; + int ret = 0; + struct dirent *de; + + struct fuse_context *ctx; + struct sharefs_private *priv; + GET_CONTEXT_PRIV(ctx, priv); + MUST_TRANSLATE_PATHNAME(pathname); + + (void)offset; + (void)fi; + + if ((fd = openat(priv->dirfd, pathname, O_RDONLY | O_DIRECTORY | O_CLOEXEC)) == -1) + return -errno; + if ((dp = fdopendir(fd)) == NULL) { + close(fd); + return -errno; + } + + errno = 0; /* for the next readdir call */ + while ((de = readdir(dp)) != NULL) { + if (flags & FUSE_READDIR_PLUS) { + if (fstatat(dirfd(dp), de->d_name, &st, AT_SYMLINK_NOFOLLOW) == -1) { + ret = -errno; + break; + } + + if ((ret = impl_getattr(ctx, &st)) < 0) + break; + + errno = 0; + ret = filler(buf, de->d_name, &st, 0, FUSE_FILL_DIR_PLUS); + } else + ret = filler(buf, de->d_name, NULL, 0, 0); + + if (ret != 0) { + ret = errno != 0 ? -errno : -EIO; /* filler */ + break; + } + + errno = 0; /* for the next readdir call */ + } + if (ret == 0 && errno != 0) + ret = -errno; /* readdir */ + + closedir(dp); + return ret; +} + +int sharefs_mkdir(const char *pathname, mode_t mode) { + struct fuse_context *ctx; + struct sharefs_private *priv; + GET_CONTEXT_PRIV(ctx, priv); + MUST_TRANSLATE_PATHNAME(pathname); + + (void)mode; + + if (mkdirat(priv->dirfd, pathname, SHAREFS_PERM_DIR) == -1) + return -errno; + return 0; +} + +int sharefs_unlink(const char *pathname) { + struct fuse_context *ctx; + struct sharefs_private *priv; + GET_CONTEXT_PRIV(ctx, priv); + MUST_TRANSLATE_PATHNAME(pathname); + + if (unlinkat(priv->dirfd, pathname, 0) == -1) + return -errno; + return 0; +} + +int sharefs_rmdir(const char *pathname) { + struct fuse_context *ctx; + struct sharefs_private *priv; + GET_CONTEXT_PRIV(ctx, priv); + MUST_TRANSLATE_PATHNAME(pathname); + + if (unlinkat(priv->dirfd, pathname, AT_REMOVEDIR) == -1) + return -errno; + return 0; +} + +int sharefs_rename(const char *oldpath, const char *newpath, unsigned int flags) { + struct fuse_context *ctx; + struct sharefs_private *priv; + GET_CONTEXT_PRIV(ctx, priv); + MUST_TRANSLATE_PATHNAME(oldpath); + MUST_TRANSLATE_PATHNAME(newpath); + + /* TODO(ophestra): replace with wrapper after 05ce67fea99ca09cd4b6625cff7aec9cc222dd5a reaches a release */ + if (syscall(__NR_renameat2, priv->dirfd, oldpath, priv->dirfd, newpath, flags) == -1) + return -errno; + return 0; +} + +int sharefs_truncate(const char *pathname, off_t length, struct fuse_file_info *fi) { + int fd; + int ret; + + struct fuse_context *ctx; + struct sharefs_private *priv; + GET_CONTEXT_PRIV(ctx, priv); + MUST_TRANSLATE_PATHNAME(pathname); + + (void)fi; + + if ((fd = openat(priv->dirfd, pathname, O_WRONLY | O_CLOEXEC)) == -1) + return -errno; + if ((ret = ftruncate(fd, length)) == -1) + ret = -errno; + close(fd); + return ret; +} + +int sharefs_utimens(const char *pathname, const struct timespec times[2], struct fuse_file_info *fi) { + struct fuse_context *ctx; + struct sharefs_private *priv; + GET_CONTEXT_PRIV(ctx, priv); + MUST_TRANSLATE_PATHNAME(pathname); + + (void)fi; + + if (utimensat(priv->dirfd, pathname, times, AT_SYMLINK_NOFOLLOW) == -1) + return -errno; + return 0; +} + +int sharefs_create(const char *pathname, mode_t mode, struct fuse_file_info *fi) { + int fd; + + struct fuse_context *ctx; + struct sharefs_private *priv; + GET_CONTEXT_PRIV(ctx, priv); + MUST_TRANSLATE_PATHNAME(pathname); + + (void)mode; + + if ((fd = openat(priv->dirfd, pathname, fi->flags & ~SHAREFS_FORBIDDEN_FLAGS, SHAREFS_PERM_REG)) == -1) + return -errno; + fi->fh = fd; + return 0; +} + +int sharefs_open(const char *pathname, struct fuse_file_info *fi) { + int fd; + + struct fuse_context *ctx; + struct sharefs_private *priv; + GET_CONTEXT_PRIV(ctx, priv); + MUST_TRANSLATE_PATHNAME(pathname); + + if ((fd = openat(priv->dirfd, pathname, fi->flags & ~SHAREFS_FORBIDDEN_FLAGS)) == -1) + return -errno; + fi->fh = fd; + return 0; +} + +int sharefs_read(const char *pathname, char *buf, size_t count, off_t offset, struct fuse_file_info *fi) { + int ret; + + (void)pathname; + + if ((ret = pread(fi->fh, buf, count, offset)) == -1) + return -errno; + return ret; +} + +int sharefs_write(const char *pathname, const char *buf, size_t count, off_t offset, struct fuse_file_info *fi) { + int ret; + + (void)pathname; + + if ((ret = pwrite(fi->fh, buf, count, offset)) == -1) + return -errno; + return ret; +} + +int sharefs_statfs(const char *pathname, struct statvfs *statbuf) { + int fd; + int ret; + + struct fuse_context *ctx; + struct sharefs_private *priv; + GET_CONTEXT_PRIV(ctx, priv); + MUST_TRANSLATE_PATHNAME(pathname); + + if ((fd = openat(priv->dirfd, pathname, O_RDONLY | O_CLOEXEC)) == -1) + return -errno; + if ((ret = fstatvfs(fd, statbuf)) == -1) + ret = -errno; + close(fd); + return ret; +} + +int sharefs_release(const char *pathname, struct fuse_file_info *fi) { + (void)pathname; + + return close(fi->fh); +} + +int sharefs_fsync(const char *pathname, int datasync, struct fuse_file_info *fi) { + (void)pathname; + + if (datasync ? fdatasync(fi->fh) : fsync(fi->fh) == -1) + return -errno; + return 0; +} diff --git a/cmd/sharefs/fuse-operations.h b/cmd/sharefs/fuse-operations.h new file mode 100644 index 00000000..34f388b3 --- /dev/null +++ b/cmd/sharefs/fuse-operations.h @@ -0,0 +1,33 @@ +#define FUSE_USE_VERSION FUSE_MAKE_VERSION(3, 4) +#include +#include /* for fuse_cmdline_help */ + +#if (FUSE_VERSION < FUSE_MAKE_VERSION(3, 4)) +#error This package requires libfuse >= v3.4 +#endif + +#define SHAREFS_MEDIA_RW_ID (1 << 10) - 1 /* owning gid presented to userspace */ +#define SHAREFS_PERM_DIR 0700 /* permission bits for directories presented to userspace */ +#define SHAREFS_PERM_REG 0600 /* permission bits for regular files presented to userspace */ +#define SHAREFS_FORBIDDEN_FLAGS O_DIRECT /* these open flags are cleared unconditionally */ + +/* sharefs_private is populated by sharefs_init and contains process-wide context */ +struct sharefs_private { + int dirfd; /* source dirfd opened during sharefs_init */ +}; + +int sharefs_getattr(const char *pathname, struct stat *statbuf, struct fuse_file_info *fi); +int sharefs_readdir(const char *pathname, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi, enum fuse_readdir_flags flags); +int sharefs_mkdir(const char *pathname, mode_t mode); +int sharefs_unlink(const char *pathname); +int sharefs_rmdir(const char *pathname); +int sharefs_rename(const char *oldpath, const char *newpath, unsigned int flags); +int sharefs_truncate(const char *pathname, off_t length, struct fuse_file_info *fi); +int sharefs_utimens(const char *pathname, const struct timespec times[2], struct fuse_file_info *fi); +int sharefs_create(const char *pathname, mode_t mode, struct fuse_file_info *fi); +int sharefs_open(const char *pathname, struct fuse_file_info *fi); +int sharefs_read(const char *pathname, char *buf, size_t count, off_t offset, struct fuse_file_info *fi); +int sharefs_write(const char *pathname, const char *buf, size_t count, off_t offset, struct fuse_file_info *fi); +int sharefs_statfs(const char *pathname, struct statvfs *statbuf); +int sharefs_release(const char *pathname, struct fuse_file_info *fi); +int sharefs_fsync(const char *pathname, int datasync, struct fuse_file_info *fi); diff --git a/cmd/sharefs/fuse.go b/cmd/sharefs/fuse.go index c9b24b27..1a17f800 100644 --- a/cmd/sharefs/fuse.go +++ b/cmd/sharefs/fuse.go @@ -3,12 +3,12 @@ package main /* #cgo pkg-config: --static fuse3 -#include "fuse-helper.h" +#include "fuse-operations.h" #include #include extern void *sharefs_init(struct fuse_conn_info *conn, struct fuse_config *cfg); -void sharefs_destroy(void *private_data); +extern void sharefs_destroy(void *private_data); typedef void (*closure)(); static inline struct fuse_opt _FUSE_OPT_END() { return (struct fuse_opt)FUSE_OPT_END; }; @@ -202,6 +202,9 @@ func unsafeAddArgument(args *fuseArgs, arg string) { } func _main(argc int, argv **C.char) int { + // don't mask creation mode, kernel already did that + syscall.Umask(0) + args := C.struct_fuse_args{argc: C.int(argc), argv: argv, allocated: 1} // this causes the kernel to enforce access control based on diff --git a/cmd/sharefs/main.go b/cmd/sharefs/main.go index 44a7e510..60924e06 100644 --- a/cmd/sharefs/main.go +++ b/cmd/sharefs/main.go @@ -5,7 +5,6 @@ import ( "os" "path" "runtime" - "syscall" ) // executableName is the [path.Base] name of the executable that started the current process. @@ -24,8 +23,5 @@ func main() { log.SetFlags(0) log.SetPrefix(executableName + ": ") - // don't mask creation mode, kernel already did that - syscall.Umask(0) - os.Exit(_main(len(os.Args), copyStrings(os.Args...))) } -- cgit v1.3.1