Last active
August 29, 2015 14:01
-
-
Save cat-in-136/cb78f3c93fdada6b3e3b to your computer and use it in GitHub Desktop.
Transparent Filesystem, for study FUSE
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Transparent Filesystem, for study FUSE | |
* Copyright (C) 2014 @cat_in_136 | |
* | |
* Avarilable under MIT License <http://opensource.org/licenses/mit-license.php> | |
* | |
* How to build: | |
* gcc -Wall -o transparent_fuse transparent_fuse.c `pkg-config fuse --cflags --libs` | |
* | |
* How to use: | |
* % ./transparent_fuse /where/to/mount | |
* % echo hello > /where/to/mount/tmp/foobar.txt | |
* % cat /tmp/foobar.txt | |
* hello | |
* % fusermount -u /where/to/mount | |
* | |
*/ | |
#define FUSE_USE_VERSION 26 | |
#include <fuse.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <errno.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <dirent.h> | |
#include <sys/stat.h> | |
#include <sys/types.h> | |
#include <sys/xattr.h> | |
static int transfuse_getattr(const char *path, struct stat *buf) | |
{ | |
int res = 0; | |
res = lstat(path, buf); | |
if (res == -1) { | |
res = -errno; | |
} | |
return res; | |
} | |
static int transfuse_readlink(const char *path, char *buf, size_t bufsize) | |
{ | |
int res = 0; | |
res = readlink(path, buf, bufsize); | |
if (res == -1) { | |
res = -errno; | |
} else { | |
buf[res] = '\0'; | |
res = 0; | |
} | |
return res; | |
} | |
static int transfuse_mknod(const char *path, mode_t mode, dev_t dev) | |
{ | |
int res = 0; | |
if (S_ISREG(mode)) { | |
int fd = 0; | |
fd = open(path, O_CREAT | O_EXCL | O_WRONLY, mode); | |
if (fd == -1) { | |
res = -errno; | |
} else { | |
res = close(fd); | |
if (res == -1) { | |
res = -errno; | |
} | |
} | |
} else if (S_ISFIFO(mode)) { | |
res = mkfifo(path, mode); | |
if (res == -1) { | |
res = -errno; | |
} | |
} else { | |
res = mknod(path, mode, dev); | |
if (res == -1) { | |
res = -errno; | |
} | |
} | |
return res; | |
} | |
static int transfuse_mkdir(const char *path, mode_t mode) | |
{ | |
int res = 0; | |
res = mkdir(path, mode); | |
if (res == -1) { | |
res = -errno; | |
} else { | |
// chown? | |
} | |
return res; | |
} | |
static int transfuse_unlink(const char *path) | |
{ | |
int res = 0; | |
res = unlink(path); | |
if (res == -1) { | |
res = -errno; | |
} | |
return res; | |
} | |
static int transfuse_rmdir(const char *path) | |
{ | |
int res = 0; | |
res = rmdir(path); | |
if (res == -1) { | |
res = -errno; | |
} | |
return res; | |
} | |
static int transfuse_symlink(const char *path1, const char *path2) | |
{ | |
int res = 0; | |
res = symlink(path1, path2); | |
if (res == -1) { | |
res = -errno; | |
} else { | |
// chown? | |
} | |
return res; | |
} | |
static int transfuse_rename(const char *old, const char *new) | |
{ | |
int res = 0; | |
res = rename(old, new); | |
if (res == -1) { | |
res = -errno; | |
} | |
return res; | |
} | |
static int transfuse_link(const char *path1, const char *path2) | |
{ | |
int res = 0; | |
res = link(path1, path2); | |
if (res == -1) { | |
res = -errno; | |
} | |
return res; | |
} | |
static int transfuse_chmod(const char *path, mode_t mode) | |
{ | |
int res = 0; | |
res = chmod(path, mode); | |
if (res == -1) { | |
res = -errno; | |
} | |
return res; | |
} | |
static int transfuse_chown(const char *path, uid_t owner, gid_t group) | |
{ | |
int res = 0; | |
res = chown(path, owner, group); | |
if (res == -1) { | |
res = -errno; | |
} | |
return res; | |
} | |
static int transfuse_truncate(const char *path, off_t length) | |
{ | |
int res = 0; | |
res = truncate(path, length); | |
if (res == -1) { | |
res = -errno; | |
} | |
return res; | |
} | |
static int transfuse_open(const char *path, struct fuse_file_info *fi) | |
{ | |
int res = 0; | |
int fd = 0; | |
fd = open(path, fi->flags); | |
if (fd == -1) { | |
res = -errno; | |
} else { | |
close(fd); | |
} | |
return res; | |
} | |
static int transfuse_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) | |
{ | |
int res = 0; | |
int fd = 0; | |
fd = open(path, O_RDONLY); | |
if (fd == -1) { | |
res = -errno; | |
} else { | |
res = pread(fd, buf, size, offset); | |
if (res == -1) { | |
res = -errno; | |
} | |
close(fd); | |
} | |
return res; | |
} | |
static int transfuse_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) | |
{ | |
int res = 0; | |
int fd = 0; | |
fd = open(path, O_WRONLY); | |
if (fd == -1) { | |
res = -errno; | |
} else { | |
res = pwrite(fd, buf, size, offset); | |
if (res == -1) { | |
res = -errno; | |
} | |
close(fd); | |
} | |
return res; | |
} | |
static int transfuse_statfs(const char *path, struct statvfs *buf) | |
{ | |
int res = 0; | |
res = statvfs(path, buf); | |
if (res == -1) { | |
res = -errno; | |
} | |
return res; | |
} | |
static int transfuse_setxattr(const char *path, const char *name, const char *value, size_t size, int flags) | |
{ | |
int res = 0; | |
res = lsetxattr(path, name, value, size, flags); | |
if (res == -1) { | |
res = -errno; | |
} | |
return res; | |
} | |
static int transfuse_getxattr(const char *path, const char *name, char *value, size_t size) | |
{ | |
int res = 0; | |
res = lgetxattr(path, name, value, size); | |
if (res == -1) { | |
res = -errno; | |
} | |
return res; | |
} | |
static int transfuse_listxattr(const char *path, char *list, size_t size) | |
{ | |
int res = 0; | |
res = listxattr(path, list, size); | |
if (res == -1) { | |
res = -errno; | |
} | |
return res; | |
} | |
static int transfuse_removexattr(const char *path, const char *name) | |
{ | |
int res = 0; | |
res = lremovexattr(path, name); | |
if (res == -1) { | |
res = -errno; | |
} | |
return res; | |
} | |
static int transfuse_opendir(const char *path, struct fuse_file_info *fi) | |
{ | |
int res = 0; | |
DIR *dir = NULL; | |
dir = opendir(path); | |
if (dir == NULL) { | |
res = -errno; | |
} else { | |
res = closedir(dir); | |
if (res == -1) { | |
res = -errno; | |
} | |
} | |
return res; | |
} | |
static int transfuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) | |
{ | |
int res = 0; | |
DIR *dir = NULL; | |
dir = opendir(path); | |
if (dir == NULL) { | |
res = -errno; | |
} else { | |
struct dirent *entry = NULL; | |
while ((entry = readdir(dir)) != NULL) { | |
struct stat statbuf; | |
int stat_res = 0; | |
stat_res = stat(entry->d_name, &statbuf); | |
filler(buf, entry->d_name, (stat_res == -1)? NULL : &statbuf, 0); | |
} | |
res = closedir(dir); | |
if (res == -1) { | |
res = -errno; | |
} | |
} | |
return res; | |
} | |
static int transfuse_access(const char *path, int amode) | |
{ | |
int res = 0; | |
res = access(path, amode); | |
if (res == -1) { | |
res = -errno; | |
} | |
return res; | |
} | |
static int transfuse_utimens(const char *path, const struct timespec tv[2]) | |
{ | |
int res = 0; | |
res = utimensat(-1, path, tv, AT_SYMLINK_NOFOLLOW); | |
if (res == -1) { | |
if (errno == EBADF || errno == ENOTDIR) { | |
res = -ENOENT; | |
} else { | |
res = -errno; | |
} | |
} | |
return res; | |
} | |
static const struct fuse_operations transfuse_oper = { | |
.getattr = transfuse_getattr, | |
.readlink = transfuse_readlink, | |
.mknod = transfuse_mknod, | |
.mkdir = transfuse_mkdir, | |
.unlink = transfuse_unlink, | |
.rmdir = transfuse_rmdir, | |
.symlink = transfuse_symlink, | |
.rename = transfuse_rename, | |
.link = transfuse_link, | |
.chmod = transfuse_chmod, | |
.chown = transfuse_chown, | |
.truncate = transfuse_truncate, | |
.open = transfuse_open, | |
.read = transfuse_read, | |
.write = transfuse_write, | |
.statfs = transfuse_statfs, | |
//.flush = transfuse_flush, | |
//.release = transfuse_release, | |
//.fsync = transfuse_fsync, | |
.setxattr = transfuse_setxattr, | |
.getxattr = transfuse_getxattr, | |
.listxattr = transfuse_listxattr, | |
.removexattr = transfuse_removexattr, | |
.opendir = transfuse_opendir, | |
.readdir = transfuse_readdir, | |
//.releasedir = transfuse_releasedir, | |
//.fsyncdir = transfuse_fsyncdir, | |
//.init = transfuse_init, | |
//.destroy = transfuse_destroy, | |
.access = transfuse_access, | |
//.create = transfuse_create, // -> mknod() and open(). | |
//.fttruncate = transfuse_fttruncate, // -> truncate(). | |
//.fgetattr = transfuse_fgetattr, // <- create() | |
//.lock = transfuse_lock, // -- not needed. | |
.utimens = transfuse_utimens, | |
//.bmap = transfuse_bmaps, // -- not needed. | |
}; | |
int main(int argc, char *argv[]) | |
{ | |
return fuse_main(argc, argv, &transfuse_oper, NULL); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment