lowlevel lib: add fuse_reply_iov function...
[fuse.git] / example / hello_ll.c
blob6ab617293ab7a9cbcc75820706febdb72f2b631a
1 /*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
8 gcc -Wall `pkg-config fuse --cflags --libs` hello_ll.c -o hello_ll
9 */
11 #define FUSE_USE_VERSION 26
13 #include <fuse_lowlevel.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <assert.h>
22 static const char *hello_str = "Hello World!\n";
23 static const char *hello_name = "hello";
25 static int hello_stat(fuse_ino_t ino, struct stat *stbuf)
27 stbuf->st_ino = ino;
28 switch (ino) {
29 case 1:
30 stbuf->st_mode = S_IFDIR | 0755;
31 stbuf->st_nlink = 2;
32 break;
34 case 2:
35 stbuf->st_mode = S_IFREG | 0444;
36 stbuf->st_nlink = 1;
37 stbuf->st_size = strlen(hello_str);
38 break;
40 default:
41 return -1;
43 return 0;
46 static void hello_ll_getattr(fuse_req_t req, fuse_ino_t ino,
47 struct fuse_file_info *fi)
49 struct stat stbuf;
51 (void) fi;
53 memset(&stbuf, 0, sizeof(stbuf));
54 if (hello_stat(ino, &stbuf) == -1)
55 fuse_reply_err(req, ENOENT);
56 else
57 fuse_reply_attr(req, &stbuf, 1.0);
60 static void hello_ll_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
62 struct fuse_entry_param e;
64 if (parent != 1 || strcmp(name, hello_name) != 0)
65 fuse_reply_err(req, ENOENT);
66 else {
67 memset(&e, 0, sizeof(e));
68 e.ino = 2;
69 e.attr_timeout = 1.0;
70 e.entry_timeout = 1.0;
71 hello_stat(e.ino, &e.attr);
73 fuse_reply_entry(req, &e);
77 struct dirbuf {
78 char *p;
79 size_t size;
82 static void dirbuf_add(fuse_req_t req, struct dirbuf *b, const char *name,
83 fuse_ino_t ino)
85 struct stat stbuf;
86 size_t oldsize = b->size;
87 b->size += fuse_add_direntry(req, NULL, 0, name, NULL, 0);
88 b->p = (char *) realloc(b->p, b->size);
89 memset(&stbuf, 0, sizeof(stbuf));
90 stbuf.st_ino = ino;
91 fuse_add_direntry(req, b->p + oldsize, b->size - oldsize, name, &stbuf,
92 b->size);
95 #define min(x, y) ((x) < (y) ? (x) : (y))
97 static int reply_buf_limited(fuse_req_t req, const char *buf, size_t bufsize,
98 off_t off, size_t maxsize)
100 if (off < bufsize)
101 return fuse_reply_buf(req, buf + off, min(bufsize - off, maxsize));
102 else
103 return fuse_reply_buf(req, NULL, 0);
106 static void hello_ll_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
107 off_t off, struct fuse_file_info *fi)
109 (void) fi;
111 if (ino != 1)
112 fuse_reply_err(req, ENOTDIR);
113 else {
114 struct dirbuf b;
116 memset(&b, 0, sizeof(b));
117 dirbuf_add(req, &b, ".", 1);
118 dirbuf_add(req, &b, "..", 1);
119 dirbuf_add(req, &b, hello_name, 2);
120 reply_buf_limited(req, b.p, b.size, off, size);
121 free(b.p);
125 static void hello_ll_open(fuse_req_t req, fuse_ino_t ino,
126 struct fuse_file_info *fi)
128 if (ino != 2)
129 fuse_reply_err(req, EISDIR);
130 else if ((fi->flags & 3) != O_RDONLY)
131 fuse_reply_err(req, EACCES);
132 else
133 fuse_reply_open(req, fi);
136 static void hello_ll_read(fuse_req_t req, fuse_ino_t ino, size_t size,
137 off_t off, struct fuse_file_info *fi)
139 (void) fi;
141 assert(ino == 2);
142 reply_buf_limited(req, hello_str, strlen(hello_str), off, size);
145 static struct fuse_lowlevel_ops hello_ll_oper = {
146 .lookup = hello_ll_lookup,
147 .getattr = hello_ll_getattr,
148 .readdir = hello_ll_readdir,
149 .open = hello_ll_open,
150 .read = hello_ll_read,
153 int main(int argc, char *argv[])
155 struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
156 struct fuse_chan *ch;
157 char *mountpoint;
158 int err = -1;
160 if (fuse_parse_cmdline(&args, &mountpoint, NULL, NULL) != -1 &&
161 (ch = fuse_mount(mountpoint, &args)) != NULL) {
162 struct fuse_session *se;
164 se = fuse_lowlevel_new(&args, &hello_ll_oper, sizeof(hello_ll_oper),
165 NULL);
166 if (se != NULL) {
167 if (fuse_set_signal_handlers(se) != -1) {
168 fuse_session_add_chan(se, ch);
169 err = fuse_session_loop(se);
170 fuse_remove_signal_handlers(se);
171 fuse_session_remove_chan(ch);
173 fuse_session_destroy(se);
175 fuse_unmount(mountpoint, ch);
177 fuse_opt_free_args(&args);
179 return err ? 1 : 0;