author | Tero Marttila <terom@fixme.fi> |
Sat, 13 Dec 2008 20:32:17 +0200 | |
branch | new-evsql |
changeset 54 | 7dc8ff496da1 |
parent 27 | 461be4cd34a3 |
permissions | -rw-r--r-- |
2 | 1 |
#include <string.h> |
2 |
#include <errno.h> |
|
3 |
#include <stdlib.h> |
|
4 |
||
1 | 5 |
#include <event2/event.h> |
6 |
#include <fuse/fuse_opt.h> |
|
7 |
||
6
d2036d7799fd
new 'simple' module, plus hello_simple
Tero Marttila <terom@fixme.fi>
parents:
5
diff
changeset
|
8 |
#include "lib/log.h" |
2 | 9 |
#include "lib/math.h" |
3 | 10 |
#include "lib/signals.h" |
1 | 11 |
#include "evfuse.h" |
7
3a603d755bcb
split off the dirbuf stuff into its own module
Tero Marttila <terom@fixme.fi>
parents:
6
diff
changeset
|
12 |
#include "dirbuf.h" |
1 | 13 |
|
2 | 14 |
const char *file_name = "hello"; |
15 |
const char *file_data = "Hello World\n"; |
|
16 |
||
17 |
static struct hello { |
|
1 | 18 |
struct event_base *ev_base; |
19 |
||
3 | 20 |
struct signals *signals; |
21 |
||
1 | 22 |
struct evfuse *ev_fuse; |
2 | 23 |
|
1 | 24 |
} ctx; |
25 |
||
26 |
void hello_init (void *userdata, struct fuse_conn_info *conn) { |
|
27 |
INFO("[hello.init] userdata=%p, conn=%p", userdata, conn); |
|
28 |
} |
|
29 |
||
30 |
void hello_destroy (void *userdata) { |
|
31 |
INFO("[hello.destroy] userdata=%p", userdata); |
|
32 |
} |
|
33 |
||
2 | 34 |
void hello_lookup (fuse_req_t req, fuse_ino_t parent, const char *name) { |
35 |
struct fuse_entry_param e; |
|
36 |
||
37 |
INFO("[hello.lookup] (uid=%d, pid=%d) parent=%lu name=%s", fuse_req_ctx(req)->uid, fuse_req_ctx(req)->pid, parent, name); |
|
38 |
||
39 |
// the world is flat |
|
40 |
if (parent != 1 || strcmp(name, file_name)) { |
|
41 |
fuse_reply_err(req, ENOENT); |
|
42 |
||
43 |
return; |
|
44 |
} |
|
45 |
||
46 |
// set up the entry |
|
47 |
memset(&e, 0, sizeof(e)); |
|
48 |
e.ino = 2; |
|
49 |
e.attr_timeout = 1.0; |
|
50 |
e.entry_timeout = 1.0; |
|
51 |
e.attr.st_mode = S_IFREG | 0444; |
|
52 |
e.attr.st_nlink = 1; |
|
53 |
e.attr.st_size = strlen(file_data); |
|
54 |
||
55 |
// reply |
|
56 |
fuse_reply_entry(req, &e); |
|
57 |
} |
|
58 |
||
59 |
void hello_getattr (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { |
|
60 |
struct stat stbuf; |
|
61 |
||
62 |
INFO("[hello.getattr] (uid=%d, pid=%d) ino=%lu, fi=%p", fuse_req_ctx(req)->uid, fuse_req_ctx(req)->pid, ino, fi); |
|
63 |
||
64 |
memset(&stbuf, 0, sizeof(stbuf)); |
|
65 |
||
66 |
// the root dir, or the file? |
|
67 |
if (ino == 1) { |
|
68 |
stbuf.st_mode = S_IFDIR | 0555; |
|
69 |
stbuf.st_nlink = 2; |
|
70 |
||
71 |
} else if (ino == 2) { |
|
72 |
stbuf.st_mode = S_IFREG | 0444; |
|
73 |
stbuf.st_nlink = 1; |
|
74 |
stbuf.st_size = strlen(file_data); |
|
75 |
||
76 |
} else { |
|
77 |
fuse_reply_err(req, ENOENT); |
|
78 |
return; |
|
79 |
} |
|
80 |
||
81 |
// reply |
|
82 |
fuse_reply_attr(req, &stbuf, 1.0); |
|
83 |
} |
|
84 |
||
85 |
||
86 |
void hello_readdir (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) { |
|
87 |
int err = 0; |
|
88 |
struct dirbuf buf; |
|
89 |
||
90 |
INFO("[hello.readdir] ino=%lu, size=%zu, off=%zu, fi=%p", ino, size, off, fi); |
|
91 |
||
92 |
// there exists only one dir |
|
93 |
if (ino != 1) { |
|
94 |
fuse_reply_err(req, ENOTDIR); |
|
95 |
return; |
|
96 |
} |
|
97 |
||
98 |
// fill in the dirbuf |
|
27 | 99 |
if (dirbuf_init(&buf, size, off)) |
2 | 100 |
ERROR("failed to init dirbuf"); |
101 |
||
27 | 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 ); |
|
5 | 105 |
|
106 |
if (err < 0) |
|
107 |
ERROR("failed to add dirents to buf"); |
|
2 | 108 |
|
109 |
// send it |
|
7
3a603d755bcb
split off the dirbuf stuff into its own module
Tero Marttila <terom@fixme.fi>
parents:
6
diff
changeset
|
110 |
if ((err = -dirbuf_done(req, &buf))) |
2 | 111 |
EERROR(-err, "failed to send buf"); |
112 |
||
113 |
// success |
|
114 |
return; |
|
115 |
||
116 |
error: |
|
117 |
if ((err = fuse_reply_err(req, err ? err : EIO))) |
|
118 |
EWARNING(err, "failed to send error reply"); |
|
119 |
} |
|
120 |
||
4 | 121 |
void hello_open (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { |
122 |
int err = 0; |
|
123 |
||
124 |
INFO("[hello.open] ino=%lu, fi=%p, fi->flags=%08X", ino, fi, fi->flags); |
|
125 |
||
126 |
if (ino != 2) { |
|
127 |
// must open our only file, not the dir |
|
128 |
fuse_reply_err(req, ino == 1 ? EISDIR : ENOENT); |
|
129 |
return; |
|
130 |
||
131 |
} else if ((fi->flags & 0x03) != O_RDONLY) { |
|
132 |
// "permission denied" |
|
133 |
fuse_reply_err(req, EACCES); |
|
134 |
return; |
|
135 |
} |
|
136 |
||
137 |
// XXX: update fi stuff? |
|
138 |
||
139 |
// open it! |
|
140 |
if ((err = fuse_reply_open(req, fi))) |
|
141 |
EERROR(err, "fuse_reply_open"); |
|
142 |
||
143 |
// success |
|
144 |
return; |
|
145 |
||
146 |
error: |
|
147 |
if ((err = fuse_reply_err(req, err ? err : EIO))) |
|
148 |
EWARNING(err, "failed to send error reply"); |
|
149 |
} |
|
150 |
||
151 |
void hello_read (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) { |
|
152 |
int err = 0; |
|
153 |
||
154 |
// fi is unused |
|
155 |
(void) fi; |
|
156 |
||
157 |
INFO("[hello.read] ino=%lu, size=%zu, off=%zu, fi=%p", ino, size, off, fi); |
|
158 |
||
159 |
if (ino != 2) { |
|
160 |
// EEK! |
|
161 |
FATAL("wrong inode"); |
|
162 |
} |
|
163 |
||
5 | 164 |
if (off >= strlen(file_data)) { |
165 |
// offset is out-of-file, so return EOF |
|
166 |
err = fuse_reply_buf(req, NULL, 0); |
|
167 |
||
168 |
} else { |
|
169 |
// reply with the requested file data |
|
170 |
err = fuse_reply_buf(req, file_data + off, MIN(strlen(file_data) - off, size)); |
|
171 |
} |
|
4 | 172 |
|
173 |
// reply |
|
5 | 174 |
if (err) |
4 | 175 |
PERROR("fuse_reply_buf"); |
176 |
||
177 |
// success |
|
178 |
return; |
|
179 |
||
180 |
error: |
|
181 |
if ((err = fuse_reply_err(req, err ? err : EIO))) |
|
182 |
EWARNING(err, "failed to send error reply"); |
|
183 |
} |
|
184 |
||
6
d2036d7799fd
new 'simple' module, plus hello_simple
Tero Marttila <terom@fixme.fi>
parents:
5
diff
changeset
|
185 |
void hello_getxattr (fuse_req_t req, fuse_ino_t ino, const char *name, size_t size) { |
d2036d7799fd
new 'simple' module, plus hello_simple
Tero Marttila <terom@fixme.fi>
parents:
5
diff
changeset
|
186 |
INFO("[hello.getxattr] ino=%lu, name=`%s', size=%zu", ino, name, size); |
d2036d7799fd
new 'simple' module, plus hello_simple
Tero Marttila <terom@fixme.fi>
parents:
5
diff
changeset
|
187 |
|
d2036d7799fd
new 'simple' module, plus hello_simple
Tero Marttila <terom@fixme.fi>
parents:
5
diff
changeset
|
188 |
fuse_reply_err(req, ENOSYS); |
d2036d7799fd
new 'simple' module, plus hello_simple
Tero Marttila <terom@fixme.fi>
parents:
5
diff
changeset
|
189 |
} |
d2036d7799fd
new 'simple' module, plus hello_simple
Tero Marttila <terom@fixme.fi>
parents:
5
diff
changeset
|
190 |
|
1 | 191 |
struct fuse_lowlevel_ops hello_llops = { |
192 |
.init = &hello_init, |
|
193 |
.destroy = &hello_destroy, |
|
2 | 194 |
|
195 |
.lookup = &hello_lookup, |
|
196 |
.getattr = &hello_getattr, |
|
197 |
||
4 | 198 |
.open = &hello_open, |
199 |
||
200 |
.read = &hello_read, |
|
201 |
||
2 | 202 |
.readdir = &hello_readdir, |
6
d2036d7799fd
new 'simple' module, plus hello_simple
Tero Marttila <terom@fixme.fi>
parents:
5
diff
changeset
|
203 |
|
d2036d7799fd
new 'simple' module, plus hello_simple
Tero Marttila <terom@fixme.fi>
parents:
5
diff
changeset
|
204 |
.getxattr = hello_getxattr, |
1 | 205 |
}; |
206 |
||
207 |
||
208 |
int main (int argc, char **argv) { |
|
209 |
struct fuse_args fuse_args = FUSE_ARGS_INIT(argc, argv); |
|
3 | 210 |
|
211 |
// zero |
|
212 |
memset(&ctx, 0, sizeof(ctx)); |
|
1 | 213 |
|
214 |
// init libevent |
|
215 |
if ((ctx.ev_base = event_base_new()) == NULL) |
|
3 | 216 |
ERROR("event_base_new"); |
1 | 217 |
|
3 | 218 |
// setup signals |
219 |
if ((ctx.signals = signals_default(ctx.ev_base)) == NULL) |
|
220 |
ERROR("signals_default"); |
|
221 |
||
1 | 222 |
// open fuse |
223 |
if ((ctx.ev_fuse = evfuse_new(ctx.ev_base, &fuse_args, &hello_llops, &ctx)) == NULL) |
|
3 | 224 |
ERROR("evfuse_new"); |
1 | 225 |
|
226 |
// run libevent |
|
227 |
INFO("running libevent loop"); |
|
228 |
||
229 |
if (event_base_dispatch(ctx.ev_base)) |
|
3 | 230 |
PERROR("event_base_dispatch"); |
231 |
||
232 |
// clean shutdown |
|
1 | 233 |
|
3 | 234 |
error : |
1 | 235 |
// cleanup |
3 | 236 |
if (ctx.ev_fuse) |
27 | 237 |
evfuse_free(ctx.ev_fuse); |
3 | 238 |
|
239 |
if (ctx.signals) |
|
240 |
signals_free(ctx.signals); |
|
241 |
||
242 |
if (ctx.ev_base) |
|
243 |
event_base_free(ctx.ev_base); |
|
244 |
||
245 |
fuse_opt_free_args(&fuse_args); |
|
1 | 246 |
} |
247 |