initial commit

This commit is contained in:
dasha_uwu 2025-08-03 02:24:47 +05:00
commit 220a642577

254
condviewfs.c Normal file
View file

@ -0,0 +1,254 @@
#define _GNU_SOURCE
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define FUSE_USE_VERSION 317
#include <fuse3/fuse.h>
static char *progname;
static int fd1, fd2;
static int get_fd() {
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(1);
}
if (pid == 0) {
execl(progname, progname, (char *) NULL);
exit(2);
}
int wstatus;
if (waitpid(pid, &wstatus, 0) == -1) {
perror("waitpid");
exit(1);
}
int code = WEXITSTATUS(wstatus);
if (code == 0) return fd1;
if (code == 1) return fd2;
return -1;
}
static int condviewfs_open(const char *name, struct fuse_file_info *fi) {
int dirfd = get_fd();
if (dirfd == -1)
return -ENOLINK;
int fd = openat(dirfd, &name[1], fi->flags);
if (fd < 0)
return -errno;
fi->fh = (uint64_t)fd;
return 0;
}
static int condviewfs_close(const char *name, struct fuse_file_info *fi) {
if (close((int)fi->fh))
return -errno;
return 0;
}
static int condviewfs_getattr(const char *name,
struct stat *stbuf,
struct fuse_file_info *fi) {
int dirfd = get_fd();
if (dirfd == -1)
return -ENOLINK;
int ret;
if (fi)
ret = fstat((int)fi->fh, stbuf);
else
ret = fstatat(dirfd,
&name[1],
stbuf,
AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
if (ret < 0)
return -errno;
return 0;
}
static int condviewfs_access(const char *name, int mask) {
int dirfd = get_fd();
if (dirfd == -1)
return -ENOLINK;
if ((name[0] != '/') || (name[1] != '\0'))
++name;
if (faccessat(dirfd, name, mask, AT_SYMLINK_NOFOLLOW) < 0)
return -errno;
return 0;
}
static int condviewfs_read(const char *path,
char *buf,
size_t size,
off_t off,
struct fuse_file_info *fi) {
ssize_t out;
out = pread((int)fi->fh, buf, size > INT_MAX ? INT_MAX : size, off);
if (out < 0)
return -errno;
return (int)out;
}
static int condviewfs_opendir(const char *name, struct fuse_file_info *fi) {
DIR *dirp;
int dirfd = get_fd();
if (dirfd == -1)
return -ENOLINK;
int fd, err;
if ((name[0] == '/') && (name[1] == '\0'))
fd = dup(dirfd);
else
fd = openat(dirfd, &name[1], O_DIRECTORY);
if (fd < 0)
return -errno;
dirp = fdopendir(fd);
if (!dirp) {
err = -errno;
close(fd);
return err;
}
fi->fh = (uint64_t)dirp;
return 0;
}
static int condviewfs_closedir(const char *name, struct fuse_file_info *fi) {
if (closedir((DIR *)(uintptr_t)fi->fh) < 0)
return -errno;
return 0;
}
static int condviewfs_readdir(const char *path,
void *buf,
fuse_fill_dir_t filler,
off_t offset,
struct fuse_file_info *fi,
enum fuse_readdir_flags flags) {
int dirfd = get_fd();
if (dirfd == -1)
return -ENOLINK;
DIR *dirp = (DIR *)(uintptr_t)fi->fh;
if (offset == 0)
rewinddir(dirp);
struct stat stbuf;
struct dirent *dent;
while (1) {
errno = 0;
dent = readdir(dirp);
if (!dent) {
if (errno == 0)
break;
return -errno;
}
if (fstatat(dirfd,
dent->d_name,
&stbuf,
AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW) < 0)
return -errno;
if (filler(buf, dent->d_name, &stbuf, 0, FUSE_FILL_DIR_DEFAULTS) == 1) {
return -errno;
}
}
return 0;
}
static int condviewfs_readlink(const char *name, char *buf, size_t size) {
int dirfd = get_fd();
if (dirfd == -1)
return -ENOLINK;
ssize_t len;
len = readlinkat(dirfd,
&name[1],
buf,
size - 1);
if (len < 0)
return -errno;
buf[len] = '\0';
return 0;
}
static struct fuse_operations condviewfs_oper = {
.open = condviewfs_open,
.release = condviewfs_close,
.read = condviewfs_read,
.getattr = condviewfs_getattr,
.access = condviewfs_access,
.opendir = condviewfs_opendir,
.releasedir = condviewfs_closedir,
.readdir = condviewfs_readdir,
.readlink = condviewfs_readlink,
};
int main(int argc, char *argv[]) {
char *fuse_argv[5];
if (argc != 5) {
fprintf(stderr, "Usage: %s target dir1 dir2 prog\n", argv[0]);
exit(-1);
}
fd1 = open(argv[2], O_DIRECTORY);
if (fd1 < 0) {
perror("open 1");
exit(-1);
}
fd2 = open(argv[3], O_DIRECTORY);
if (fd2 < 0) {
perror("open 2");
exit(-1);
}
progname = argv[4];
fuse_argv[0] = argv[0];
fuse_argv[1] = argv[1];
fuse_argv[2] = "-oallow_other,default_permissions";
fuse_argv[3] = "-f";
fuse_argv[4] = NULL;
return fuse_main(4, fuse_argv, &condviewfs_oper, NULL);
}