From c6bd90a235076a19f2f42eb44d4f83cd16a4090d Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Sun, 3 Nov 2013 19:36:57 -0800 Subject: [PATCH] Add a simple FUSE filesystem based on libnfs. --- README | 8 ++ examples/fuse_nfs.c | 325 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 333 insertions(+) create mode 100644 examples/fuse_nfs.c diff --git a/README b/README index 4115911..330aa5a 100644 --- a/README +++ b/README @@ -47,6 +47,14 @@ This is highly non-portable so IF this works on your linux system, count yourself lucky. +FUSE +==== +A simple FUSE filesystem built on libnfs can be found in +examples/fuse_nfs.c + +Compile using : gcc fuse_nfs.c -o fuse_nfs -lfuse -lnfs +Mount using : sudo ./fuse_nfs -n nfs:/// -m + PLATFORM support ================= diff --git a/examples/fuse_nfs.c b/examples/fuse_nfs.c new file mode 100644 index 0000000..7e9eba6 --- /dev/null +++ b/examples/fuse_nfs.c @@ -0,0 +1,325 @@ +/* + Copyright (C) by Ronnie Sahlberg 2013 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ +/* A FUSE filesystem based on libnfs. */ + +#define FUSE_USE_VERSION 26 +#define _FILE_OFFSET_BITS 64 + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define discard_const(ptr) ((void *)((intptr_t)(ptr))) + +FILE *fh=NULL; + +struct nfs_context *nfs = NULL; + +static int fuse_nfs_getattr(const char *path, struct stat *stbuf) +{ + int ret = 0; + + memset(stbuf, 0, sizeof(struct stat)); + ret = nfs_stat(nfs, path, stbuf); + + return ret; +} + +static int fuse_nfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, + off_t offset, struct fuse_file_info *fi) +{ + struct nfsdir *nfsdir; + struct nfsdirent *nfsdirent; + + int ret = 0; + + ret = nfs_opendir(nfs, path, &nfsdir); + if (ret < 0) { + return ret; + } + while ((nfsdirent = nfs_readdir(nfs, nfsdir)) != NULL) { + filler(buf, nfsdirent->name, NULL, 0); + } + + return ret; +} + +static int fuse_nfs_open(const char *path, struct fuse_file_info *fi) +{ + int ret = 0; + struct nfsfh *nfsfh; + + fi->fh = 0; + ret = nfs_open(nfs, path, fi->flags, &nfsfh); + if (ret < 0) { + return ret; + } + + fi->fh = (uint64_t)nfsfh; + + return ret; +} + +static int fuse_nfs_release(const char *path, struct fuse_file_info *fi) +{ + struct nfsfh *nfsfh = (struct nfsfh *)fi->fh; + + nfs_close(nfs, nfsfh); + return 0; +} + +static int fuse_nfs_read(const char *path, char *buf, size_t size, + off_t offset, struct fuse_file_info *fi) +{ + int ret = 0; + struct nfsfh *nfsfh = (struct nfsfh *)fi->fh; + + ret = nfs_pread(nfs, nfsfh, offset, size, buf); + + return ret; +} + +static int fuse_nfs_write(const char *path, const char *buf, size_t size, + off_t offset, struct fuse_file_info *fi) +{ + int ret = 0; + struct nfsfh *nfsfh = (struct nfsfh *)fi->fh; + + ret = nfs_pwrite(nfs, nfsfh, offset, size, discard_const(buf)); + + return ret; +} + +static int fuse_nfs_create(const char *path, mode_t mode, struct fuse_file_info *fi) +{ + int ret = 0; + struct nfsfh *nfsfh; + + ret = nfs_creat(nfs, path, mode, &nfsfh); + if (ret < 0) { + return ret; + } + + fi->fh = (uint64_t)nfsfh; + +//nfs_chown + + return ret; +} + +static int fuse_nfs_utime(const char *path, struct utimbuf *times) +{ + int ret = 0; + + ret = nfs_utime(nfs, path, times); + if (ret < 0) { + return ret; + } + + return ret; +} + +static int fuse_nfs_unlink(const char *path) +{ + int ret = 0; + + ret = nfs_unlink(nfs, path); + if (ret < 0) { + return ret; + } + + return ret; +} + +static int fuse_nfs_rmdir(const char *path) +{ + int ret = 0; + + ret = nfs_rmdir(nfs, path); + if (ret < 0) { + return ret; + } + + return ret; +} + +static int fuse_nfs_mkdir(const char *path, mode_t mode) +{ + int ret = 0; + + ret = nfs_mkdir(nfs, path); + if (ret < 0) { + return ret; + } + ret = nfs_chmod(nfs, path, mode); + if (ret < 0) { + return ret; + } + + return ret; +} + +static struct fuse_operations nfs_oper = { + .create = fuse_nfs_create, + .getattr = fuse_nfs_getattr, + .mkdir = fuse_nfs_mkdir, + .open = fuse_nfs_open, + .read = fuse_nfs_read, + .readdir = fuse_nfs_readdir, + .release = fuse_nfs_release, + .rmdir = fuse_nfs_rmdir, + .unlink = fuse_nfs_unlink, + .utime = fuse_nfs_utime, + .write = fuse_nfs_write, +}; + +void print_usage(char *name) +{ + printf("Usage: %s [-?|--help] [-n|--nfs-share=nfs-url] mountpoint\n", + name); + exit(0); +} + +int main(int argc, char *argv[]) +{ + int ret = 0; + static struct option long_opts[] = { + { "help", no_argument, 0, '?' }, + { "nfs-share", required_argument, 0, 'n' }, + { "mountpoint", required_argument, 0, 'm' }, + { NULL, 0, 0, 0 } + }; + int c; + int opt_idx = 0; + char *url = NULL; + char *mnt = NULL; + char *server = NULL, *export = NULL, *strp; + int fuse_nfs_argc = 6; + char *fuse_nfs_argv[16] = { + "fuse-nfs", + "", + "-odebug", + "-oallow_other", + "-odefault_permissions", + "-omax_write=32768", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + }; + + while ((c = getopt_long(argc, argv, "?hm:n:", long_opts, + &opt_idx)) > 0) { + switch (c) { + case 'h': + case '?': + print_usage(argv[0]); + return 0; + case 'm': + mnt = strdup(optarg); + break; + case 'n': + url = strdup(optarg); + break; + } + } + + if (url == NULL) { + fprintf(stderr, "-n was not specified.\n"); + ret = 10; + goto finished; + } + if (mnt == NULL) { + fprintf(stderr, "-m was not specified.\n"); + ret = 10; + goto finished; + } + + + if (strncmp(url, "nfs://", 6)) { + fprintf(stderr, "Invalid URL specified.\n"); + ret = 10; + goto finished; + } + server = strdup(url + 6); + if (server == NULL) { + fprintf(stderr, "Failed to strdup server string\n"); + ret = 10; + goto finished; + } + if (server[0] == '/' || server[0] == '\0') { + fprintf(stderr, "Invalid server string.\n"); + ret = 10; + goto finished; + } + strp = strchr(server, '/'); + if (strp == NULL) { + fprintf(stderr, "Invalid URL specified.\n"); + ret = 10; + goto finished; + } + export = strdup(strp); + if (export == NULL) { + fprintf(stderr, "Failed to strdup server string\n"); + ret = 10; + goto finished; + } + if (export[0] != '/') { + fprintf(stderr, "Invalid export.\n"); + ret = 10; + goto finished; + } + *strp = 0; + + nfs = nfs_init_context(); + if (nfs == NULL) { + printf("failed to init context\n"); + goto finished; + } + + ret = nfs_mount(nfs, server, export); + if (ret != 0) { + printf("Failed to mount nfs share : %s\n", nfs_get_error(nfs)); + goto finished; + } + + + fuse_nfs_argv[1] = mnt; + return fuse_main(fuse_nfs_argc, fuse_nfs_argv, &nfs_oper, NULL); + +finished: + if (nfs != NULL) { + nfs_destroy_context(nfs); + } + free(server); + free(export); + free(url); + free(mnt); + return ret; +} -- 2.34.1