libfuse

passthrough_ll.c
Go to the documentation of this file.
1 /*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
4
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7 */
8
37 #define _GNU_SOURCE
38 #define FUSE_USE_VERSION 31
39
40 #include <fuse_lowlevel.h>
41 #include <unistd.h>
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <stddef.h>
45 #include <stdbool.h>
46 #include <string.h>
47 #include <limits.h>
48 #include <dirent.h>
49 #include <assert.h>
50 #include <errno.h>
51 #include <err.h>
52 #include <inttypes.h>
53
54 /* We are re-using pointers to our `struct lo_inode` and `struct
55 lo_dirp` elements as inodes. This means that we must be able to
56 store uintptr_t values in a fuse_ino_t variable. The following
57 incantation checks this condition at compile time. */
58 #if defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 6) && !defined __cplusplus
59 _Static_assert(sizeof(fuse_ino_t) >= sizeof(uintptr_t),
60 "fuse_ino_t too small to hold uintptr_t values!");
61 #else
62 struct _uintptr_to_must_hold_fuse_ino_t_dummy_struct \
63 { unsigned _uintptr_to_must_hold_fuse_ino_t:
64 ((sizeof(fuse_ino_t) >= sizeof(uintptr_t)) ? 1 : -1); };
65 #endif
66
67 struct lo_inode {
68 struct lo_inode *next;
69 struct lo_inode *prev;
70 int fd;
71 ino_t ino;
72 dev_t dev;
73 uint64_t nlookup;
74 };
75
76 struct lo_data {
77 int debug;
78 int writeback;
79 struct lo_inode root;
80 };
81
82 static const struct fuse_opt lo_opts[] = {
83 { "writeback",
84 offsetof(struct lo_data, writeback), 1 },
85 { "no_writeback",
86 offsetof(struct lo_data, writeback), 0 },
87 FUSE_OPT_END
88 };
89
90 static struct lo_data *lo_data(fuse_req_t req)
91 {
92 return (struct lo_data *) fuse_req_userdata(req);
93 }
94
95 static struct lo_inode *lo_inode(fuse_req_t req, fuse_ino_t ino)
96 {
97 if (ino == FUSE_ROOT_ID)
98 return &lo_data(req)->root;
99 else
100 return (struct lo_inode *) (uintptr_t) ino;
101 }
102
103 static int lo_fd(fuse_req_t req, fuse_ino_t ino)
104 {
105 return lo_inode(req, ino)->fd;
106 }
107
108 static bool lo_debug(fuse_req_t req)
109 {
110 return lo_data(req)->debug != 0;
111 }
112
113 static void lo_init(void *userdata,
114 struct fuse_conn_info *conn)
115 {
116 struct lo_data *lo = (struct lo_data*) userdata;
117
118 if(conn->capable & FUSE_CAP_EXPORT_SUPPORT)
119 conn->want |= FUSE_CAP_EXPORT_SUPPORT;
120
121 if (lo->writeback &&
122 conn->capable & FUSE_CAP_WRITEBACK_CACHE) {
123 if (lo->debug)
124 fprintf(stderr, "lo_init: activating writeback\n");
125 conn->want |= FUSE_CAP_WRITEBACK_CACHE;
126 }
127 }
128
129 static void lo_getattr(fuse_req_t req, fuse_ino_t ino,
130 struct fuse_file_info *fi)
131 {
132 int res;
133 struct stat buf;
134 (void) fi;
135
136 res = fstatat(lo_fd(req, ino), "", &buf, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
137 if (res == -1)
138 return (void) fuse_reply_err(req, errno);
139
140 fuse_reply_attr(req, &buf, 1.0);
141 }
142
143 static struct lo_inode *lo_find(struct lo_data *lo, struct stat *st)
144 {
145 struct lo_inode *p;
146
147 for (p = lo->root.next; p != &lo->root; p = p->next) {
148 if (p->ino == st->st_ino && p->dev == st->st_dev)
149 return p;
150 }
151 return NULL;
152 }
153
154 static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name,
155 struct fuse_entry_param *e)
156 {
157 int newfd;
158 int res;
159 int saverr;
160 struct lo_inode *inode;
161
162 memset(e, 0, sizeof(*e));
163 e->attr_timeout = 1.0;
164 e->entry_timeout = 1.0;
165
166 newfd = openat(lo_fd(req, parent), name, O_PATH | O_NOFOLLOW);
167 if (newfd == -1)
168 goto out_err;
169
170 res = fstatat(newfd, "", &e->attr, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
171 if (res == -1)
172 goto out_err;
173
174 inode = lo_find(lo_data(req), &e->attr);
175 if (inode) {
176 close(newfd);
177 newfd = -1;
178 } else {
179 struct lo_inode *prev = &lo_data(req)->root;
180 struct lo_inode *next = prev->next;
181 saverr = ENOMEM;
182 inode = calloc(1, sizeof(struct lo_inode));
183 if (!inode)
184 goto out_err;
185
186 inode->fd = newfd;
187 inode->ino = e->attr.st_ino;
188 inode->dev = e->attr.st_dev;
189
190 next->prev = inode;
191 inode->next = next;
192 inode->prev = prev;
193 prev->next = inode;
194 }
195 inode->nlookup++;
196 e->ino = (uintptr_t) inode;
197
198 if (lo_debug(req))
199 fprintf(stderr, " %lli/%s -> %lli\n",
200 (unsigned long long) parent, name, (unsigned long long) e->ino);
201
202 return 0;
203
204 out_err:
205 saverr = errno;
206 if (newfd != -1)
207 close(newfd);
208 return saverr;
209 }
210
211 static void lo_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
212 {
213 struct fuse_entry_param e;
214 int err;
215
216 if (lo_debug(req))
217 fprintf(stderr, "lo_lookup(parent=%" PRIu64 ", name=%s)\n",
218 parent, name);
219
220 err = lo_do_lookup(req, parent, name, &e);
221 if (err)
222 fuse_reply_err(req, err);
223 else
224 fuse_reply_entry(req, &e);
225 }
226
227 static void lo_free(struct lo_inode *inode)
228 {
229 struct lo_inode *prev = inode->prev;
230 struct lo_inode *next = inode->next;
231
232 next->prev = prev;
233 prev->next = next;
234 close(inode->fd);
235 free(inode);
236 }
237
238 static void lo_forget(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup)
239 {
240 struct lo_inode *inode = lo_inode(req, ino);
241
242 if (lo_debug(req)) {
243 fprintf(stderr, " forget %lli %lli -%lli\n",
244 (unsigned long long) ino, (unsigned long long) inode->nlookup,
245 (unsigned long long) nlookup);
246 }
247
248 assert(inode->nlookup >= nlookup);
249 inode->nlookup -= nlookup;
250
251 if (!inode->nlookup)
252 lo_free(inode);
253
254 fuse_reply_none(req);
255 }
256
257 static void lo_readlink(fuse_req_t req, fuse_ino_t ino)
258 {
259 char buf[PATH_MAX + 1];
260 int res;
261
262 res = readlinkat(lo_fd(req, ino), "", buf, sizeof(buf));
263 if (res == -1)
264 return (void) fuse_reply_err(req, errno);
265
266 if (res == sizeof(buf))
267 return (void) fuse_reply_err(req, ENAMETOOLONG);
268
269 buf[res] = '\0';
270
271 fuse_reply_readlink(req, buf);
272 }
273
274 struct lo_dirp {
275 int fd;
276 DIR *dp;
277 struct dirent *entry;
278 off_t offset;
279 };
280
281 static struct lo_dirp *lo_dirp(struct fuse_file_info *fi)
282 {
283 return (struct lo_dirp *) (uintptr_t) fi->fh;
284 }
285
286 static void lo_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
287 {
288 int error = ENOMEM;
289 struct lo_dirp *d = calloc(1, sizeof(struct lo_dirp));
290 if (d == NULL)
291 goto out_err;
292
293 d->fd = openat(lo_fd(req, ino), ".", O_RDONLY);
294 if (d->fd == -1)
295 goto out_errno;
296
297 d->dp = fdopendir(d->fd);
298 if (d->dp == NULL)
299 goto out_errno;
300
301 d->offset = 0;
302 d->entry = NULL;
303
304 fi->fh = (uintptr_t) d;
305 fuse_reply_open(req, fi);
306 return;
307
308 out_errno:
309 error = errno;
310 out_err:
311 if (d) {
312 if (d->fd != -1)
313 close(d->fd);
314 free(d);
315 }
316 fuse_reply_err(req, error);
317 }
318
319 static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
320 off_t offset, struct fuse_file_info *fi, int plus)
321 {
322 struct lo_dirp *d = lo_dirp(fi);
323 char *buf;
324 char *p;
325 size_t rem;
326 int err;
327
328 (void) ino;
329
330 buf = calloc(size, 1);
331 if (!buf)
332 return (void) fuse_reply_err(req, ENOMEM);
333
334 if (offset != d->offset) {
335 seekdir(d->dp, offset);
336 d->entry = NULL;
337 d->offset = offset;
338 }
339 p = buf;
340 rem = size;
341 while (1) {
342 size_t entsize;
343 off_t nextoff;
344
345 if (!d->entry) {
346 errno = 0;
347 d->entry = readdir(d->dp);
348 if (!d->entry) {
349 if (errno && rem == size) {
350 err = errno;
351 goto error;
352 }
353 break;
354 }
355 }
356 nextoff = telldir(d->dp);
357 if (plus) {
358 struct fuse_entry_param e;
359
360 err = lo_do_lookup(req, ino, d->entry->d_name, &e);
361 if (err)
362 goto error;
363
364 entsize = fuse_add_direntry_plus(req, p, rem,
365 d->entry->d_name,
366 &e, nextoff);
367 } else {
368 struct stat st = {
369 .st_ino = d->entry->d_ino,
370 .st_mode = d->entry->d_type << 12,
371 };
372 entsize = fuse_add_direntry(req, p, rem,
373 d->entry->d_name,
374 &st, nextoff);
375 }
376 if (entsize > rem)
377 break;
378
379 p += entsize;
380 rem -= entsize;
381
382 d->entry = NULL;
383 d->offset = nextoff;
384 }
385
386 fuse_reply_buf(req, buf, size - rem);
387 free(buf);
388 return;
389
390 error:
391 free(buf);
392 fuse_reply_err(req, err);
393 }
394
395 static void lo_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
396 off_t offset, struct fuse_file_info *fi)
397 {
398 lo_do_readdir(req, ino, size, offset, fi, 0);
399 }
400
401 static void lo_readdirplus(fuse_req_t req, fuse_ino_t ino, size_t size,
402 off_t offset, struct fuse_file_info *fi)
403 {
404 lo_do_readdir(req, ino, size, offset, fi, 1);
405 }
406
407 static void lo_releasedir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
408 {
409 struct lo_dirp *d = lo_dirp(fi);
410 (void) ino;
411 closedir(d->dp);
412 free(d);
413 fuse_reply_err(req, 0);
414 }
415
416 static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
417 mode_t mode, struct fuse_file_info *fi)
418 {
419 int fd;
420 struct fuse_entry_param e;
421 int err;
422
423 if (lo_debug(req))
424 fprintf(stderr, "lo_create(parent=%" PRIu64 ", name=%s)\n",
425 parent, name);
426
427 fd = openat(lo_fd(req, parent), name,
428 (fi->flags | O_CREAT) & ~O_NOFOLLOW, mode);
429 if (fd == -1)
430 return (void) fuse_reply_err(req, errno);
431
432 fi->fh = fd;
433
434 err = lo_do_lookup(req, parent, name, &e);
435 if (err)
436 fuse_reply_err(req, err);
437 else
438 fuse_reply_create(req, &e, fi);
439 }
440
441 static void lo_open(fuse_req_t req, fuse_ino_t ino,
442 struct fuse_file_info *fi)
443 {
444 int fd;
445 char buf[64];
446
447 if (lo_debug(req))
448 fprintf(stderr, "lo_open(ino=%" PRIu64 ", flags=%d)\n",
449 ino, fi->flags);
450
451 /* With writeback cache, kernel may send read requests even
452 when userspace opened write-only */
453 if (lo_data(req)->writeback &&
454 (fi->flags & O_ACCMODE) == O_WRONLY) {
455 fi->flags &= ~O_ACCMODE;
456 fi->flags |= O_RDWR;
457 }
458
459 /* With writeback cache, O_APPEND is handled by the kernel.
460 This breaks atomicity (since the file may change in the
461 underlying filesystem, so that the kernel's idea of the
462 end of the file isn't accurate anymore). In this example,
463 we just accept that. A more rigorous filesystem may want
464 to return an error here */
465 if (lo_data(req)->writeback && (fi->flags & O_APPEND))
466 fi->flags &= ~O_APPEND;
467
468 sprintf(buf, "/proc/self/fd/%i", lo_fd(req, ino));
469 fd = open(buf, fi->flags & ~O_NOFOLLOW);
470 if (fd == -1)
471 return (void) fuse_reply_err(req, errno);
472
473 fi->fh = fd;
474 fuse_reply_open(req, fi);
475 }
476
477 static void lo_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
478 {
479 (void) ino;
480
481 close(fi->fh);
482 fuse_reply_err(req, 0);
483 }
484
485 static void lo_read(fuse_req_t req, fuse_ino_t ino, size_t size,
486 off_t offset, struct fuse_file_info *fi)
487 {
488 struct fuse_bufvec buf = FUSE_BUFVEC_INIT(size);
489
490 if (lo_debug(req))
491 fprintf(stderr, "lo_read(ino=%" PRIu64 ", size=%zd, "
492 "off=%lu)\n", ino, size, (unsigned long) offset);
493
494 buf.buf[0].flags = FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK;
495 buf.buf[0].fd = fi->fh;
496 buf.buf[0].pos = offset;
497
498 fuse_reply_data(req, &buf, FUSE_BUF_SPLICE_MOVE);
499 }
500
501 static void lo_write_buf(fuse_req_t req, fuse_ino_t ino,
502 struct fuse_bufvec *in_buf, off_t off,
503 struct fuse_file_info *fi)
504 {
505 (void) ino;
506 ssize_t res;
507 struct fuse_bufvec out_buf = FUSE_BUFVEC_INIT(fuse_buf_size(in_buf));
508
509 out_buf.buf[0].flags = FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK;
510 out_buf.buf[0].fd = fi->fh;
511 out_buf.buf[0].pos = off;
512
513 if (lo_debug(req))
514 fprintf(stderr, "lo_write(ino=%" PRIu64 ", size=%zd, off=%lu)\n",
515 ino, out_buf.buf[0].size, (unsigned long) off);
516
517 res = fuse_buf_copy(&out_buf, in_buf, 0);
518 if(res < 0)
519 fuse_reply_err(req, -res);
520 else
521 fuse_reply_write(req, (size_t) res);
522 }
523
524 static struct fuse_lowlevel_ops lo_oper = {
525 .init = lo_init,
526 .lookup = lo_lookup,
527 .forget = lo_forget,
528 .getattr = lo_getattr,
529 .readlink = lo_readlink,
530 .opendir = lo_opendir,
531 .readdir = lo_readdir,
532 .readdirplus = lo_readdirplus,
533 .releasedir = lo_releasedir,
534 .create = lo_create,
535 .open = lo_open,
536 .release = lo_release,
537 .read = lo_read,
538 .write_buf = lo_write_buf
539 };
540
541 int main(int argc, char *argv[])
542 {
543 struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
544 struct fuse_session *se;
545 struct fuse_cmdline_opts opts;
546 struct lo_data lo = { .debug = 0,
547 .writeback = 0 };
548 int ret = -1;
549
550 lo.root.next = lo.root.prev = &lo.root;
551 lo.root.fd = -1;
552
553 if (fuse_parse_cmdline(&args, &opts) != 0)
554 return 1;
555 if (opts.show_help) {
556 printf("usage: %s [options] <mountpoint>\n\n", argv[0]);
557 fuse_cmdline_help();
558 fuse_lowlevel_help();
559 ret = 0;
560 goto err_out1;
561 } else if (opts.show_version) {
562 printf("FUSE library version %s\n", fuse_pkgversion());
563 fuse_lowlevel_version();
564 ret = 0;
565 goto err_out1;
566 }
567
568 if (fuse_opt_parse(&args, &lo, lo_opts, NULL)== -1)
569 return 1;
570
571 lo.debug = opts.debug;
572 lo.root.fd = open("/", O_PATH);
573 lo.root.nlookup = 2;
574 if (lo.root.fd == -1)
575 err(1, "open(\"/\", O_PATH)");
576
577 se = fuse_session_new(&args, &lo_oper, sizeof(lo_oper), &lo);
578 if (se == NULL)
579 goto err_out1;
580
581 if (fuse_set_signal_handlers(se) != 0)
582 goto err_out2;
583
584 if (fuse_session_mount(se, opts.mountpoint) != 0)
585 goto err_out3;
586
587 fuse_daemonize(opts.foreground);
588
589 /* Block until ctrl+c or fusermount -u */
590 if (opts.singlethread)
591 ret = fuse_session_loop(se);
592 else
593 ret = fuse_session_loop_mt(se, opts.clone_fd);
594
595 fuse_session_unmount(se);
596 err_out3:
597 fuse_remove_signal_handlers(se);
598 err_out2:
599 fuse_session_destroy(se);
600 err_out1:
601 free(opts.mountpoint);
602 fuse_opt_free_args(&args);
603
604 while (lo.root.next != &lo.root)
605 lo_free(lo.root.next);
606 if (lo.root.fd >= 0)
607 close(lo.root.fd);
608
609 return ret ? 1 : 0;
610 }
fuse_bufvec::off
size_t off
Definition: fuse_common.h:668
fuse_conn_info::capable
unsigned capable
Definition: fuse_common.h:370
fuse_file_info::fh
uint64_t fh
Definition: fuse_common.h:72
fuse_remove_signal_handlers
void fuse_remove_signal_handlers(struct fuse_session *se)
Definition: fuse_signals.c:80
fuse_conn_info
Definition: fuse_common.h:332
FUSE_OPT_END
#define FUSE_OPT_END
Definition: fuse_opt.h:104
fuse_session_unmount
void fuse_session_unmount(struct fuse_session *se)
Definition: fuse_lowlevel.c:2916
fuse_reply_open
int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *fi)
Definition: fuse_lowlevel.c:450
fuse_pkgversion
const char * fuse_pkgversion(void)
Definition: fuse.c:4923
FUSE_BUF_IS_FD
Definition: fuse_common.h:544
FUSE_ARGS_INIT
#define FUSE_ARGS_INIT(argc, argv)
Definition: fuse_opt.h:123
fuse_reply_write
int fuse_reply_write(fuse_req_t req, size_t count)
Definition: fuse_lowlevel.c:459
fuse_entry_param::attr
struct stat attr
Definition: fuse_lowlevel.h:91
fuse_reply_buf
int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
Definition: fuse_lowlevel.c:469
FUSE_BUF_FD_SEEK
Definition: fuse_common.h:553
fuse_entry_param
Definition: fuse_lowlevel.h:59
fuse_daemonize
int fuse_daemonize(int foreground)
Definition: helper.c:220
fuse_entry_param::ino
fuse_ino_t ino
Definition: fuse_lowlevel.h:67
fuse_reply_entry
int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
Definition: fuse_lowlevel.c:398
fuse_session_loop
int fuse_session_loop(struct fuse_session *se)
Definition: fuse_loop.c:19
fuse_buf::pos
off_t pos
Definition: fuse_common.h:643
fuse_file_info
Definition: fuse_common.h:37
fuse_lowlevel_help
void fuse_lowlevel_help(void)
Definition: fuse_lowlevel.c:2587
FUSE_CAP_WRITEBACK_CACHE
#define FUSE_CAP_WRITEBACK_CACHE
Definition: fuse_common.h:255
fuse_file_info::flags
int flags
Definition: fuse_common.h:39
fuse_bufvec
Definition: fuse_common.h:654
fuse_reply_readlink
int fuse_reply_readlink(fuse_req_t req, const char *link)
Definition: fuse_lowlevel.c:445
fuse_lowlevel_version
void fuse_lowlevel_version(void)
Definition: fuse_lowlevel.c:2580
fuse_reply_err
int fuse_reply_err(fuse_req_t req, int err)
Definition: fuse_lowlevel.c:311
fuse_buf_size
size_t fuse_buf_size(const struct fuse_bufvec *bufv)
Definition: buffer.c:22
fuse_req_userdata
void * fuse_req_userdata(fuse_req_t req)
Definition: fuse_lowlevel.c:2315
fuse_buf::flags
enum fuse_buf_flags flags
Definition: fuse_common.h:622
fuse_req_t
struct fuse_req * fuse_req_t
Definition: fuse_lowlevel.h:49
fuse_reply_attr
int fuse_reply_attr(fuse_req_t req, const struct stat *attr, double attr_timeout)
Definition: fuse_lowlevel.c:430
fuse_parse_cmdline
int fuse_parse_cmdline(struct fuse_args *args, struct fuse_cmdline_opts *opts)
Definition: helper.c:197
fuse_session_new
struct fuse_session * fuse_session_new(struct fuse_args *args, const struct fuse_lowlevel_ops *op, size_t op_size, void *userdata)
Definition: fuse_lowlevel.c:2785
fuse_opt_parse
int fuse_opt_parse(struct fuse_args *args, void *data, const struct fuse_opt opts[], fuse_opt_proc_t proc)
Definition: fuse_opt.c:397
fuse_ino_t
uint64_t fuse_ino_t
Definition: fuse_lowlevel.h:46
fuse_add_direntry
size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize, const char *name, const struct stat *stbuf, off_t off)
Definition: fuse_lowlevel.c:266
fuse_session_destroy
void fuse_session_destroy(struct fuse_session *se)
Definition: fuse_lowlevel.c:2597
fuse_lowlevel_ops
Definition: fuse_lowlevel.h:175
FUSE_BUF_SPLICE_MOVE
Definition: fuse_common.h:595
fuse_session_mount
int fuse_session_mount(struct fuse_session *se, const char *mountpoint)
Definition: fuse_lowlevel.c:2879
fuse_opt
Definition: fuse_opt.h:77
fuse_conn_info::want
unsigned want
Definition: fuse_common.h:378
fuse_bufvec::buf
struct fuse_buf buf[1]
Definition: fuse_common.h:673
fuse_args
Definition: fuse_opt.h:109
fuse_set_signal_handlers
int fuse_set_signal_handlers(struct fuse_session *se)
Definition: fuse_signals.c:63
FUSE_CAP_EXPORT_SUPPORT
#define FUSE_CAP_EXPORT_SUPPORT
Definition: fuse_common.h:144
fuse_buf::size
size_t size
Definition: fuse_common.h:617
fuse_entry_param::entry_timeout
double entry_timeout
Definition: fuse_lowlevel.h:103
fuse_buf::fd
int fd
Definition: fuse_common.h:636
fuse_reply_none
void fuse_reply_none(fuse_req_t req)
Definition: fuse_lowlevel.c:316
fuse_entry_param::attr_timeout
double attr_timeout
Definition: fuse_lowlevel.h:97
fuse_reply_data
int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv, enum fuse_buf_copy_flags flags)
Definition: fuse_lowlevel.c:819
fuse_cmdline_help
void fuse_cmdline_help(void)
Definition: helper.c:128
fuse_add_direntry_plus
size_t fuse_add_direntry_plus(fuse_req_t req, char *buf, size_t bufsize, const char *name, const struct fuse_entry_param *e, off_t off)
Definition: fuse_lowlevel.c:356
fuse_reply_create
int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e, const struct fuse_file_info *fi)
Definition: fuse_lowlevel.c:414
fuse_lowlevel_ops::init
void(* init)(void *userdata, struct fuse_conn_info *conn)
Definition: fuse_lowlevel.h:192
FUSE_ROOT_ID
#define FUSE_ROOT_ID
Definition: fuse_lowlevel.h:43
fuse_opt_free_args
void fuse_opt_free_args(struct fuse_args *args)
Definition: fuse_opt.c:33
fuse_buf_copy
ssize_t fuse_buf_copy(struct fuse_bufvec *dst, struct fuse_bufvec *src, enum fuse_buf_copy_flags flags)
Definition: buffer.c:281