aboutsummaryrefslogtreecommitdiffhomepage
path: root/cmd/sharefs/fuse-helper.c
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-12-26 03:19:32 +0900
committerOphestra <cat@gensokyo.uk>2025-12-26 03:19:32 +0900
commitd597592e1f3bd64b586257f47315390042a9def1 (patch)
treea5f925d4e6e36a58fc8eb035766e07659b3af599 /cmd/sharefs/fuse-helper.c
parent056f5b12d447e9cf113ab6fd3fbf3e9cfe0a1b18 (diff)
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 <cat@gensokyo.uk>
Diffstat (limited to 'cmd/sharefs/fuse-helper.c')
-rw-r--r--cmd/sharefs/fuse-helper.c282
1 files changed, 0 insertions, 282 deletions
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 <dirent.h>
-#include <errno.h>
-#include <unistd.h>
-
-/* TODO(ophestra): remove after 05ce67fea99ca09cd4b6625cff7aec9cc222dd5a reaches a release */
-#include <sys/syscall.h>
-
-#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;
-}