Add a simple FUSE filesystem based on libnfs.
authorRonnie Sahlberg <ronniesahlberg@gmail.com>
Mon, 4 Nov 2013 03:36:57 +0000 (19:36 -0800)
committerRonnie Sahlberg <ronniesahlberg@gmail.com>
Mon, 4 Nov 2013 03:36:57 +0000 (19:36 -0800)
README
examples/fuse_nfs.c [new file with mode: 0644]

diff --git a/README b/README
index 4115911b561300fe03e2bcf00cdc49ac004ace45..330aa5aa7dcaaabd1066f9cf000b44b7cb4f7633 100644 (file)
--- 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://<server>/<export> -m <mountpoint>
+
 
 PLATFORM support
 =================
diff --git a/examples/fuse_nfs.c b/examples/fuse_nfs.c
new file mode 100644 (file)
index 0000000..7e9eba6
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+   Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 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 <http://www.gnu.org/licenses/>.
+*/
+/* A FUSE filesystem based on libnfs. */
+
+#define FUSE_USE_VERSION 26
+#define _FILE_OFFSET_BITS 64
+
+#include <fuse.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+
+#include <nfsc/libnfs.h>
+
+#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",
+               "<export>",
+               "-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;
+}