2 Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 2013
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, see <http://www.gnu.org/licenses/>.
17 /* A FUSE filesystem based on libnfs. */
19 #define FUSE_USE_VERSION 26
20 #define _FILE_OFFSET_BITS 64
30 #include <nfsc/libnfs.h>
32 #define discard_const(ptr) ((void *)((intptr_t)(ptr)))
36 struct nfs_context
*nfs
= NULL
;
38 static int fuse_nfs_getattr(const char *path
, struct stat
*stbuf
)
42 memset(stbuf
, 0, sizeof(struct stat
));
43 ret
= nfs_stat(nfs
, path
, stbuf
);
48 static int fuse_nfs_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
49 off_t offset
, struct fuse_file_info
*fi
)
51 struct nfsdir
*nfsdir
;
52 struct nfsdirent
*nfsdirent
;
56 ret
= nfs_opendir(nfs
, path
, &nfsdir
);
60 while ((nfsdirent
= nfs_readdir(nfs
, nfsdir
)) != NULL
) {
61 filler(buf
, nfsdirent
->name
, NULL
, 0);
67 static int fuse_nfs_open(const char *path
, struct fuse_file_info
*fi
)
73 ret
= nfs_open(nfs
, path
, fi
->flags
, &nfsfh
);
78 fi
->fh
= (uint64_t)nfsfh
;
83 static int fuse_nfs_release(const char *path
, struct fuse_file_info
*fi
)
85 struct nfsfh
*nfsfh
= (struct nfsfh
*)fi
->fh
;
87 nfs_close(nfs
, nfsfh
);
91 static int fuse_nfs_read(const char *path
, char *buf
, size_t size
,
92 off_t offset
, struct fuse_file_info
*fi
)
95 struct nfsfh
*nfsfh
= (struct nfsfh
*)fi
->fh
;
97 ret
= nfs_pread(nfs
, nfsfh
, offset
, size
, buf
);
102 static int fuse_nfs_write(const char *path
, const char *buf
, size_t size
,
103 off_t offset
, struct fuse_file_info
*fi
)
106 struct nfsfh
*nfsfh
= (struct nfsfh
*)fi
->fh
;
108 ret
= nfs_pwrite(nfs
, nfsfh
, offset
, size
, discard_const(buf
));
113 static int fuse_nfs_create(const char *path
, mode_t mode
, struct fuse_file_info
*fi
)
118 ret
= nfs_creat(nfs
, path
, mode
, &nfsfh
);
123 fi
->fh
= (uint64_t)nfsfh
;
130 static int fuse_nfs_utime(const char *path
, struct utimbuf
*times
)
134 ret
= nfs_utime(nfs
, path
, times
);
142 static int fuse_nfs_unlink(const char *path
)
146 ret
= nfs_unlink(nfs
, path
);
154 static int fuse_nfs_rmdir(const char *path
)
158 ret
= nfs_rmdir(nfs
, path
);
166 static int fuse_nfs_mkdir(const char *path
, mode_t mode
)
170 ret
= nfs_mkdir(nfs
, path
);
174 ret
= nfs_chmod(nfs
, path
, mode
);
182 static struct fuse_operations nfs_oper
= {
183 .create
= fuse_nfs_create
,
184 .getattr
= fuse_nfs_getattr
,
185 .mkdir
= fuse_nfs_mkdir
,
186 .open
= fuse_nfs_open
,
187 .read
= fuse_nfs_read
,
188 .readdir
= fuse_nfs_readdir
,
189 .release
= fuse_nfs_release
,
190 .rmdir
= fuse_nfs_rmdir
,
191 .unlink
= fuse_nfs_unlink
,
192 .utime
= fuse_nfs_utime
,
193 .write
= fuse_nfs_write
,
196 void print_usage(char *name
)
198 printf("Usage: %s [-?|--help] [-n|--nfs-share=nfs-url] mountpoint\n",
203 int main(int argc
, char *argv
[])
206 static struct option long_opts
[] = {
207 { "help", no_argument
, 0, '?' },
208 { "nfs-share", required_argument
, 0, 'n' },
209 { "mountpoint", required_argument
, 0, 'm' },
216 char *server
= NULL
, *export
= NULL
, *strp
;
217 int fuse_nfs_argc
= 6;
218 char *fuse_nfs_argv
[16] = {
223 "-odefault_permissions",
237 while ((c
= getopt_long(argc
, argv
, "?hm:n:", long_opts
,
242 print_usage(argv
[0]);
245 mnt
= strdup(optarg
);
248 url
= strdup(optarg
);
254 fprintf(stderr
, "-n was not specified.\n");
259 fprintf(stderr
, "-m was not specified.\n");
265 if (strncmp(url
, "nfs://", 6)) {
266 fprintf(stderr
, "Invalid URL specified.\n");
270 server
= strdup(url
+ 6);
271 if (server
== NULL
) {
272 fprintf(stderr
, "Failed to strdup server string\n");
276 if (server
[0] == '/' || server
[0] == '\0') {
277 fprintf(stderr
, "Invalid server string.\n");
281 strp
= strchr(server
, '/');
283 fprintf(stderr
, "Invalid URL specified.\n");
287 export
= strdup(strp
);
288 if (export
== NULL
) {
289 fprintf(stderr
, "Failed to strdup server string\n");
293 if (export
[0] != '/') {
294 fprintf(stderr
, "Invalid export.\n");
300 nfs
= nfs_init_context();
302 printf("failed to init context\n");
306 ret
= nfs_mount(nfs
, server
, export
);
308 printf("Failed to mount nfs share : %s\n", nfs_get_error(nfs
));
313 fuse_nfs_argv
[1] = mnt
;
314 return fuse_main(fuse_nfs_argc
, fuse_nfs_argv
, &nfs_oper
, NULL
);
318 nfs_destroy_context(nfs
);