fedir
bfc22c79e0
Passthrough is usable now. There have been issues with the `access` operation: it's unclear what it must return, since the answer isn't known at the time when it is called. If it always returns "denied", many applications would finish without trying to open a file, thinking the access would not be granted after `access` call. Although always returning "permitted" seems like a better choice, it still might cause unexpected behaviour. Perhaps one way to solve this, is actually asking user whether to allow access. In any case, this issue needs to be looked into.
117 lines
3.5 KiB
C
117 lines
3.5 KiB
C
#define _GNU_SOURCE
|
|
|
|
#include "sourcefs.h"
|
|
#include <dirent.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
|
|
static struct source_files_handle {
|
|
int root_fd;
|
|
} handle;
|
|
|
|
const char *source_fname_translate(const char *filename) {
|
|
if (strcmp("/", filename) == 0) {
|
|
return ".";
|
|
} else {
|
|
return filename + 1;
|
|
}
|
|
}
|
|
|
|
int source_init(const char *root_path) {
|
|
int root_fd = open(root_path, O_PATH);
|
|
|
|
if (root_fd == -1) {
|
|
return -1;
|
|
}
|
|
|
|
handle.root_fd = root_fd;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int source_mkdir(const char *filename, mode_t mode) {
|
|
const char *relative_filename = source_fname_translate(filename);
|
|
return mkdirat(handle.root_fd, relative_filename, mode);
|
|
}
|
|
|
|
int source_unlink(const char *filename) {
|
|
const char *relative_filename = source_fname_translate(filename);
|
|
return unlinkat(handle.root_fd, relative_filename, 0);
|
|
}
|
|
|
|
int source_stat(const char *restrict filename, struct stat *restrict statbuf) {
|
|
const char *relative_filename = source_fname_translate(filename);
|
|
return fstatat(handle.root_fd, relative_filename, statbuf, 0);
|
|
}
|
|
|
|
int source_rmdir(const char *filename) {
|
|
const char *relative_filename = source_fname_translate(filename);
|
|
return unlinkat(handle.root_fd, relative_filename, AT_REMOVEDIR);
|
|
}
|
|
|
|
int source_symlink(const char *target, const char *linkpath) {
|
|
const char *relative_linkpath = source_fname_translate(linkpath);
|
|
return symlinkat(target, handle.root_fd, relative_linkpath);
|
|
}
|
|
|
|
DIR *source_opendir(const char *filename) {
|
|
const char *relative_filename = source_fname_translate(filename);
|
|
int fd = openat(handle.root_fd, relative_filename, NULL);
|
|
if (fd < 0) {
|
|
perror("Openat failed");
|
|
return NULL;
|
|
}
|
|
DIR *dir_pointer = fdopendir(fd);
|
|
return dir_pointer;
|
|
}
|
|
|
|
int source_rename(const char *oldpath, const char *newpath) {
|
|
const char *relative_oldpath = source_fname_translate(oldpath);
|
|
const char *relative_newpath = source_fname_translate(newpath);
|
|
return renameat(handle.root_fd, relative_oldpath, handle.root_fd,
|
|
relative_newpath);
|
|
}
|
|
|
|
int source_link(const char *oldpath, const char *newpath) {
|
|
const char *relative_oldpath = source_fname_translate(oldpath);
|
|
const char *relative_newpath = source_fname_translate(newpath);
|
|
return linkat(handle.root_fd, relative_oldpath, handle.root_fd,
|
|
relative_newpath, 0);
|
|
// NOTE: perhaps the flags here need to be reevaluated.
|
|
}
|
|
|
|
int source_chmod(const char *filename, mode_t mode) {
|
|
const char *relative_filename = source_fname_translate(filename);
|
|
return fchmodat(handle.root_fd, relative_filename, mode, 0);
|
|
// NOTE: perhaps the flags here need to be reevaluated.
|
|
}
|
|
|
|
int source_chown(const char *filename, uid_t owner, gid_t group) {
|
|
const char *relative_filename = source_fname_translate(filename);
|
|
return fchownat(handle.root_fd, filename, owner, group, AT_SYMLINK_NOFOLLOW);
|
|
}
|
|
|
|
int source_truncate(const char *filename, off_t length) {
|
|
const char *relative_filename = source_fname_translate(filename);
|
|
int fd = openat(handle.root_fd, relative_filename, NULL);
|
|
if (fd < 0) {
|
|
perror("Openat failed");
|
|
return -1;
|
|
}
|
|
return ftruncate(fd, length);
|
|
}
|
|
|
|
int source_open(const char *filename, int flags) {
|
|
const char *relative_filename = source_fname_translate(filename);
|
|
return openat(handle.root_fd, relative_filename, flags);
|
|
}
|
|
|
|
int source_create(const char *filename, int flags, mode_t mode) {
|
|
const char *relative_filename = source_fname_translate(filename);
|
|
return openat(handle.root_fd, relative_filename, flags, mode);
|
|
}
|