5 #include <event2/event.h>
6 #include <fuse/fuse_opt.h>
10 #include "lib/signals.h"
14 const char *file_name = "hello";
15 const char *file_data = "Hello World\n";
18 struct event_base *ev_base;
20 struct signals *signals;
22 struct evfuse *ev_fuse;
26 void hello_init (void *userdata, struct fuse_conn_info *conn) {
27 INFO("[hello.init] userdata=%p, conn=%p", userdata, conn);
30 void hello_destroy (void *userdata) {
31 INFO("[hello.destroy] userdata=%p", userdata);
34 void hello_lookup (fuse_req_t req, fuse_ino_t parent, const char *name) {
35 struct fuse_entry_param e;
37 INFO("[hello.lookup] (uid=%d, pid=%d) parent=%lu name=%s", fuse_req_ctx(req)->uid, fuse_req_ctx(req)->pid, parent, name);
40 if (parent != 1 || strcmp(name, file_name)) {
41 fuse_reply_err(req, ENOENT);
47 memset(&e, 0, sizeof(e));
50 e.entry_timeout = 1.0;
51 e.attr.st_mode = S_IFREG | 0444;
53 e.attr.st_size = strlen(file_data);
56 fuse_reply_entry(req, &e);
59 void hello_getattr (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) {
62 INFO("[hello.getattr] (uid=%d, pid=%d) ino=%lu, fi=%p", fuse_req_ctx(req)->uid, fuse_req_ctx(req)->pid, ino, fi);
64 memset(&stbuf, 0, sizeof(stbuf));
66 // the root dir, or the file?
68 stbuf.st_mode = S_IFDIR | 0555;
71 } else if (ino == 2) {
72 stbuf.st_mode = S_IFREG | 0444;
74 stbuf.st_size = strlen(file_data);
77 fuse_reply_err(req, ENOENT);
82 fuse_reply_attr(req, &stbuf, 1.0);
86 void hello_readdir (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) {
90 INFO("[hello.readdir] ino=%lu, size=%zu, off=%zu, fi=%p", ino, size, off, fi);
92 // there exists only one dir
94 fuse_reply_err(req, ENOTDIR);
99 if (dirbuf_init(&buf, size, off))
100 ERROR("failed to init dirbuf");
102 err = dirbuf_add(req, &buf, 0, 1, ".", 1, S_IFDIR )
103 || dirbuf_add(req, &buf, 1, 2, "..", 1, S_IFDIR )
104 || dirbuf_add(req, &buf, 2, 3, file_name, 2, S_IFREG );
107 ERROR("failed to add dirents to buf");
110 if ((err = -dirbuf_done(req, &buf)))
111 EERROR(-err, "failed to send buf");
117 if ((err = fuse_reply_err(req, err ? err : EIO)))
118 EWARNING(err, "failed to send error reply");
121 void hello_open (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) {
124 INFO("[hello.open] ino=%lu, fi=%p, fi->flags=%08X", ino, fi, fi->flags);
127 // must open our only file, not the dir
128 fuse_reply_err(req, ino == 1 ? EISDIR : ENOENT);
131 } else if ((fi->flags & 0x03) != O_RDONLY) {
132 // "permission denied"
133 fuse_reply_err(req, EACCES);
137 // XXX: update fi stuff?
140 if ((err = fuse_reply_open(req, fi)))
141 EERROR(err, "fuse_reply_open");
147 if ((err = fuse_reply_err(req, err ? err : EIO)))
148 EWARNING(err, "failed to send error reply");
151 void hello_read (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) {
157 INFO("[hello.read] ino=%lu, size=%zu, off=%zu, fi=%p", ino, size, off, fi);
161 FATAL("wrong inode");
164 if (off >= strlen(file_data)) {
165 // offset is out-of-file, so return EOF
166 err = fuse_reply_buf(req, NULL, 0);
169 // reply with the requested file data
170 err = fuse_reply_buf(req, file_data + off, MIN(strlen(file_data) - off, size));
175 PERROR("fuse_reply_buf");
181 if ((err = fuse_reply_err(req, err ? err : EIO)))
182 EWARNING(err, "failed to send error reply");
185 void hello_getxattr (fuse_req_t req, fuse_ino_t ino, const char *name, size_t size) {
186 INFO("[hello.getxattr] ino=%lu, name=`%s', size=%zu", ino, name, size);
188 fuse_reply_err(req, ENOSYS);
191 struct fuse_lowlevel_ops hello_llops = {
193 .destroy = &hello_destroy,
195 .lookup = &hello_lookup,
196 .getattr = &hello_getattr,
202 .readdir = &hello_readdir,
204 .getxattr = hello_getxattr,
208 int main (int argc, char **argv) {
209 struct fuse_args fuse_args = FUSE_ARGS_INIT(argc, argv);
212 memset(&ctx, 0, sizeof(ctx));
215 if ((ctx.ev_base = event_base_new()) == NULL)
216 ERROR("event_base_new");
219 if ((ctx.signals = signals_default(ctx.ev_base)) == NULL)
220 ERROR("signals_default");
223 if ((ctx.ev_fuse = evfuse_new(ctx.ev_base, &fuse_args, &hello_llops, &ctx)) == NULL)
227 INFO("running libevent loop");
229 if (event_base_dispatch(ctx.ev_base))
230 PERROR("event_base_dispatch");
237 evfuse_free(ctx.ev_fuse);
240 signals_free(ctx.signals);
243 event_base_free(ctx.ev_base);
245 fuse_opt_free_args(&fuse_args);