Skip to content

Instantly share code, notes, and snippets.

@cat-in-136
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cat-in-136/cb78f3c93fdada6b3e3b to your computer and use it in GitHub Desktop.
Save cat-in-136/cb78f3c93fdada6b3e3b to your computer and use it in GitHub Desktop.
Transparent Filesystem, for study FUSE
/*
* 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