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)))
34 struct nfs_context
*nfs
= NULL
;
36 static int fuse_nfs_getattr(const char *path
, struct stat
*stbuf
)
40 memset(stbuf
, 0, sizeof(struct stat
));
41 ret
= nfs_stat(nfs
, path
, stbuf
);
46 static int fuse_nfs_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
47 off_t offset
, struct fuse_file_info
*fi
)
49 struct nfsdir
*nfsdir
;
50 struct nfsdirent
*nfsdirent
;
54 ret
= nfs_opendir(nfs
, path
, &nfsdir
);
58 while ((nfsdirent
= nfs_readdir(nfs
, nfsdir
)) != NULL
) {
59 filler(buf
, nfsdirent
->name
, NULL
, 0);
65 static int fuse_nfs_open(const char *path
, struct fuse_file_info
*fi
)
71 ret
= nfs_open(nfs
, path
, fi
->flags
, &nfsfh
);
76 fi
->fh
= (uint64_t)nfsfh
;
81 static int fuse_nfs_release(const char *path
, struct fuse_file_info
*fi
)
83 struct nfsfh
*nfsfh
= (struct nfsfh
*)fi
->fh
;
85 nfs_close(nfs
, nfsfh
);
89 static int fuse_nfs_read(const char *path
, char *buf
, size_t size
,
90 off_t offset
, struct fuse_file_info
*fi
)
93 struct nfsfh
*nfsfh
= (struct nfsfh
*)fi
->fh
;
95 ret
= nfs_pread(nfs
, nfsfh
, offset
, size
, buf
);
100 static int fuse_nfs_write(const char *path
, const char *buf
, size_t size
,
101 off_t offset
, struct fuse_file_info
*fi
)
104 struct nfsfh
*nfsfh
= (struct nfsfh
*)fi
->fh
;
106 ret
= nfs_pwrite(nfs
, nfsfh
, offset
, size
, discard_const(buf
));
111 static int fuse_nfs_create(const char *path
, mode_t mode
, struct fuse_file_info
*fi
)
116 ret
= nfs_creat(nfs
, path
, mode
, &nfsfh
);
121 fi
->fh
= (uint64_t)nfsfh
;
126 static int fuse_nfs_utime(const char *path
, struct utimbuf
*times
)
130 ret
= nfs_utime(nfs
, path
, times
);
138 static int fuse_nfs_unlink(const char *path
)
142 ret
= nfs_unlink(nfs
, path
);
150 static int fuse_nfs_rmdir(const char *path
)
154 ret
= nfs_rmdir(nfs
, path
);
162 static int fuse_nfs_mkdir(const char *path
, mode_t mode
)
166 ret
= nfs_mkdir(nfs
, path
);
170 ret
= nfs_chmod(nfs
, path
, mode
);
178 static struct fuse_operations nfs_oper
= {
179 .create
= fuse_nfs_create
,
180 .getattr
= fuse_nfs_getattr
,
181 .mkdir
= fuse_nfs_mkdir
,
182 .open
= fuse_nfs_open
,
183 .read
= fuse_nfs_read
,
184 .readdir
= fuse_nfs_readdir
,
185 .release
= fuse_nfs_release
,
186 .rmdir
= fuse_nfs_rmdir
,
187 .unlink
= fuse_nfs_unlink
,
188 .utime
= fuse_nfs_utime
,
189 .write
= fuse_nfs_write
,
192 void print_usage(char *name
)
194 printf("Usage: %s [-?|--help] [-n|--nfs-share=nfs-url] mountpoint\n",
199 int main(int argc
, char *argv
[])
202 static struct option long_opts
[] = {
203 { "help", no_argument
, 0, '?' },
204 { "nfs-share", required_argument
, 0, 'n' },
205 { "mountpoint", required_argument
, 0, 'm' },
212 char *server
= NULL
, *export
= NULL
, *strp
;
213 int fuse_nfs_argc
= 5;
214 char *fuse_nfs_argv
[16] = {
218 "-odefault_permissions",
233 while ((c
= getopt_long(argc
, argv
, "?hm:n:", long_opts
,
238 print_usage(argv
[0]);
241 mnt
= strdup(optarg
);
244 url
= strdup(optarg
);
250 fprintf(stderr
, "-n was not specified.\n");
255 fprintf(stderr
, "-m was not specified.\n");
261 if (strncmp(url
, "nfs://", 6)) {
262 fprintf(stderr
, "Invalid URL specified.\n");
266 server
= strdup(url
+ 6);
267 if (server
== NULL
) {
268 fprintf(stderr
, "Failed to strdup server string\n");
272 if (server
[0] == '/' || server
[0] == '\0') {
273 fprintf(stderr
, "Invalid server string.\n");
277 strp
= strchr(server
, '/');
279 fprintf(stderr
, "Invalid URL specified.\n");
283 export
= strdup(strp
);
284 if (export
== NULL
) {
285 fprintf(stderr
, "Failed to strdup server string\n");
289 if (export
[0] != '/') {
290 fprintf(stderr
, "Invalid export.\n");
296 nfs
= nfs_init_context();
298 printf("failed to init context\n");
302 ret
= nfs_mount(nfs
, server
, export
);
304 printf("Failed to mount nfs share : %s\n", nfs_get_error(nfs
));
309 fuse_nfs_argv
[1] = mnt
;
310 return fuse_main(fuse_nfs_argc
, fuse_nfs_argv
, &nfs_oper
, NULL
);
314 nfs_destroy_context(nfs
);