blob: cd919ed4cc8c820a55f031840829fdbb6a6e86d3 [file] [log] [blame]
Miklos Szeredi85c74fc2001-10-28 19:44:14 +00001/*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001 Miklos Szeredi (mszeredi@inf.bme.hu)
4
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7*/
8
9#include "fuse_i.h"
10#include <linux/fuse.h>
11
12#include <string.h>
13#include <unistd.h>
14#include <errno.h>
Miklos Szeredi19dff1b2001-10-30 15:06:52 +000015#include <assert.h>
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000016
17
18static guint name_hash(const struct node *node)
19{
20 return g_str_hash(node->name) ^ node->parent;
21}
22
23static gint name_compare(const struct node *node1, const struct node *node2)
24{
25 return
26 node1->parent == node2->parent &&
27 strcmp(node1->name, node2->name) == 0;
28}
29
Miklos Szeredi5e183482001-10-31 14:52:35 +000030static struct node *new_node(fino_t parent, const char *name, int mode)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000031{
32 struct node *node = g_new0(struct node, 1);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +000033 node->name = g_strdup(name);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000034 node->parent = parent;
Miklos Szeredi5e183482001-10-31 14:52:35 +000035 node->mode = mode;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000036 return node;
37}
38
39static int free_node(struct node *node)
40{
41 g_free(node->name);
42 g_free(node);
43 return 1;
44}
45
46static inline struct node *get_node(fino_t ino)
47{
Miklos Szeredib483c932001-10-29 14:57:57 +000048 return (struct node *) ((ino << 3) + 0x8000000);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000049}
50
51static inline fino_t get_ino(struct node *node)
52{
Miklos Szeredib483c932001-10-29 14:57:57 +000053 return (((fino_t) node) - 0x8000000) >> 3;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000054}
55
Miklos Szeredi19dff1b2001-10-30 15:06:52 +000056static struct node *lookup_node(struct fuse *f, fino_t parent,
57 const char *name)
58{
59 struct node tmp;
60
61 tmp.name = (char *) name;
62 tmp.parent = parent;
63
64 return g_hash_table_lookup(f->nametab, &tmp);
65}
66
Miklos Szeredi5e183482001-10-31 14:52:35 +000067static void unhash_node(struct fuse *f, struct node *node)
68{
69 g_hash_table_remove(f->nametab, node);
70 g_free(node->name);
71 node->parent = 0;
72 node->name = NULL;
73}
74
75static fino_t find_node(struct fuse *f, fino_t parent, char *name, int mode)
76{
77 struct node *node;
78 mode &= S_IFMT;
79
80 node = lookup_node(f, parent, name);
81 if(node != NULL) {
82 if(node->mode == mode)
83 return get_ino(node);
84
85 unhash_node(f, node);
86 }
87
88 node = new_node(parent, name, mode);
89 g_hash_table_insert(f->nametab, node, node);
90 return get_ino(node);
91}
92
93static fino_t find_node_dir(struct fuse *f, fino_t parent, char *name)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000094{
95 struct node *node;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000096
Miklos Szeredi19dff1b2001-10-30 15:06:52 +000097 node = lookup_node(f, parent, name);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000098 if(node != NULL)
99 return get_ino(node);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000100 else
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000101 return (fino_t) -1;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000102}
103
104static char *get_path(fino_t ino)
105{
106 GString *s;
107 char *ss;
108
109 s = g_string_new("");
110 if(ino == FUSE_ROOT_INO)
111 g_string_prepend_c(s, '/');
112 else {
113 struct node *node;
114 for(; ino != FUSE_ROOT_INO; ino = node->parent) {
115 node = get_node(ino);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000116 if(node->name == NULL) {
117 g_string_free(s, TRUE);
118 return NULL;
119 }
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000120 g_string_prepend(s, node->name);
121 g_string_prepend_c(s, '/');
122 }
123 }
124
125 ss = s->str;
126 g_string_free(s, FALSE);
127
128 return ss;
129}
130
Miklos Szeredib483c932001-10-29 14:57:57 +0000131static char *get_path_name(fino_t ino, const char *name)
132{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000133 char *path;
134 char *path2;
135
136 path = get_path(ino);
137 if(path == NULL)
138 return NULL;
139
140 path2 = g_strconcat(path, "/", name, NULL);
Miklos Szeredib483c932001-10-29 14:57:57 +0000141 g_free(path);
142 return path2;
143}
144
Miklos Szeredi5e183482001-10-31 14:52:35 +0000145static void destroy_node(struct fuse *f, fino_t ino)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000146{
147 struct node *node = get_node(ino);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000148 unhash_node(f, node);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000149 free_node(node);
150}
151
Miklos Szeredi5e183482001-10-31 14:52:35 +0000152static void remove_node(struct fuse *f, fino_t dir, const char *name)
153{
154 struct node *node = lookup_node(f, dir, name);
155 assert(node != NULL);
156 unhash_node(f, node);
157}
158
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000159static void rename_node(struct fuse *f, fino_t olddir, const char *oldname,
160 fino_t newdir, const char *newname)
161{
162 struct node *node = lookup_node(f, olddir, oldname);
163 struct node *newnode = lookup_node(f, newdir, newname);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000164 assert(node != NULL);
165
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000166 if(newnode != NULL)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000167 unhash_node(f, newnode);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000168
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000169 g_hash_table_remove(f->nametab, node);
170 g_free(node->name);
171 node->name = g_strdup(newname);
172 node->parent = newdir;
173 g_hash_table_insert(f->nametab, node, node);
174}
175
176
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000177static void convert_stat(struct stat *stbuf, struct fuse_attr *attr)
178{
179 attr->mode = stbuf->st_mode;
180 attr->nlink = stbuf->st_nlink;
181 attr->uid = stbuf->st_uid;
182 attr->gid = stbuf->st_gid;
183 attr->rdev = stbuf->st_rdev;
184 attr->size = stbuf->st_size;
185 attr->blksize = stbuf->st_blksize;
186 attr->blocks = stbuf->st_blocks;
187 attr->atime = stbuf->st_atime;
188 attr->mtime = stbuf->st_mtime;
189 attr->ctime = stbuf->st_ctime;
190}
191
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000192static int fill_dir(struct fuse_dh *dh, char *name, int type)
193{
194 struct fuse_dirent dirent;
195 size_t reclen;
196 size_t res;
197
Miklos Szeredi5e183482001-10-31 14:52:35 +0000198 dirent.ino = find_node_dir(dh->fuse, dh->dir, name);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000199 dirent.namelen = strlen(name);
200 strncpy(dirent.name, name, sizeof(dirent.name));
201 dirent.type = type;
202 reclen = FUSE_DIRENT_SIZE(&dirent);
203 res = fwrite(&dirent, reclen, 1, dh->fp);
204 if(res == 0) {
205 perror("writing directory file");
206 return -EIO;
207 }
208 return 0;
209}
210
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000211static void send_reply(struct fuse *f, struct fuse_in_header *in, int error,
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000212 void *arg, size_t argsize)
213{
214 int res;
215 char *outbuf;
216 size_t outsize;
217 struct fuse_out_header *out;
218
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000219 if(error > 0) {
220 fprintf(stderr, "positive error code: %i\n", error);
221 error = -ERANGE;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000222 }
223
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000224 if(error)
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000225 argsize = 0;
226
227 outsize = sizeof(struct fuse_out_header) + argsize;
228 outbuf = (char *) g_malloc(outsize);
229 out = (struct fuse_out_header *) outbuf;
230 out->unique = in->unique;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000231 out->error = error;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000232 if(argsize != 0)
233 memcpy(outbuf + sizeof(struct fuse_out_header), arg, argsize);
234
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000235 printf(" unique: %i, error: %i (%s), outsize: %i\n", out->unique,
236 out->error, strerror(-out->error), outsize);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000237
238 res = write(f->fd, outbuf, outsize);
239 if(res == -1)
240 perror("writing fuse device");
241
242 g_free(outbuf);
243}
244
245static void do_lookup(struct fuse *f, struct fuse_in_header *in, char *name)
246{
247 int res;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000248 char *path;
249 struct stat buf;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000250 struct fuse_lookup_out arg;
251
Miklos Szeredi5e183482001-10-31 14:52:35 +0000252 res = -ENOENT;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000253 path = get_path_name(in->ino, name);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000254 if(path != NULL) {
255 res = -ENOSYS;
256 if(f->op.getattr)
257 res = f->op.getattr(path, &buf);
258 g_free(path);
259 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000260 if(res == 0) {
261 convert_stat(&buf, &arg.attr);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000262 arg.ino = find_node(f, in->ino, name, arg.attr.mode);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000263 }
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000264 send_reply(f, in, res, &arg, sizeof(arg));
265}
266
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000267static void do_forget(struct fuse *f, unsigned long *inos, size_t num)
268{
269 size_t i;
270
271 for(i = 0; i < num; i++)
Miklos Szeredi5e183482001-10-31 14:52:35 +0000272 destroy_node(f, inos[i]);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000273}
274
275static void do_getattr(struct fuse *f, struct fuse_in_header *in)
276{
277 int res;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000278 char *path;
279 struct stat buf;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000280 struct fuse_getattr_out arg;
281
Miklos Szeredi5e183482001-10-31 14:52:35 +0000282 res = -ENOENT;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000283 path = get_path(in->ino);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000284 if(path != NULL) {
285 res = -ENOSYS;
286 if(f->op.getattr)
287 res = f->op.getattr(path, &buf);
288 g_free(path);
289 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000290 if(res == 0)
291 convert_stat(&buf, &arg.attr);
292
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000293 send_reply(f, in, res, &arg, sizeof(arg));
294}
295
Miklos Szeredi5e183482001-10-31 14:52:35 +0000296static void do_setattr(struct fuse *f, struct fuse_in_header *in,
297 struct fuse_setattr_in *arg)
298{
299 int res;
300 char *path;
301 int valid = arg->valid;
302 struct fuse_attr *attr = &arg->attr;
303
304 res = -ENOENT;
305 path = get_path(in->ino);
306 if(path != NULL) {
307 res = 0;
308 if(!res && (valid & FATTR_MODE)) {
309 res = -ENOSYS;
310 if(f->op.chmod)
311 res = f->op.chmod(path, attr->mode);
312 }
313 if(!res && (valid & (FATTR_UID | FATTR_GID))) {
314 uid_t uid = (valid & FATTR_UID) ? attr->uid : (uid_t) -1;
315 gid_t gid = (valid & FATTR_GID) ? attr->gid : (gid_t) -1;
316
317 res = -ENOSYS;
318 if(f->op.chown)
319 res = f->op.chown(path, uid, gid);
320 }
321 if(!res && (valid & FATTR_SIZE)) {
322 res = -ENOSYS;
323 if(f->op.truncate)
324 res = f->op.truncate(path, attr->size);
325 }
326 if(!res && (valid & FATTR_UTIME)) {
327 struct utimbuf buf;
328 buf.actime = attr->atime;
329 buf.modtime = attr->mtime;
330 res = -ENOSYS;
331 if(f->op.utime)
332 res = f->op.utime(path, &buf);
333 }
334 g_free(path);
335 }
336 send_reply(f, in, res, NULL, 0);
337}
338
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000339static void do_readlink(struct fuse *f, struct fuse_in_header *in)
340{
341 int res;
342 char link[PATH_MAX + 1];
Miklos Szeredib483c932001-10-29 14:57:57 +0000343 char *path;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000344
Miklos Szeredi5e183482001-10-31 14:52:35 +0000345 res = -ENOENT;
346 path = get_path(in->ino);
347 if(path != NULL) {
348 res = -ENOSYS;
349 if(f->op.readlink)
350 res = f->op.readlink(path, link, sizeof(link));
351 g_free(path);
352 }
353 send_reply(f, in, res, link, !res ? strlen(link) : 0);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000354}
355
356static void do_getdir(struct fuse *f, struct fuse_in_header *in)
357{
358 int res;
359 struct fuse_getdir_out arg;
Miklos Szeredib483c932001-10-29 14:57:57 +0000360 struct fuse_dh dh;
361 char *path;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000362
Miklos Szeredib483c932001-10-29 14:57:57 +0000363 dh.fuse = f;
364 dh.fp = tmpfile();
365 dh.dir = in->ino;
366
Miklos Szeredi5e183482001-10-31 14:52:35 +0000367 res = -ENOENT;
Miklos Szeredib483c932001-10-29 14:57:57 +0000368 path = get_path(in->ino);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000369 if(path != NULL) {
370 res = -ENOSYS;
371 if(f->op.getdir)
372 res = f->op.getdir(path, &dh, (dirfiller_t) fill_dir);
373 g_free(path);
374 }
Miklos Szeredib483c932001-10-29 14:57:57 +0000375 fflush(dh.fp);
376 arg.fd = fileno(dh.fp);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000377 send_reply(f, in, res, &arg, sizeof(arg));
Miklos Szeredib483c932001-10-29 14:57:57 +0000378 fclose(dh.fp);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000379}
380
Miklos Szeredib483c932001-10-29 14:57:57 +0000381static void do_mknod(struct fuse *f, struct fuse_in_header *in,
382 struct fuse_mknod_in *inarg)
383{
384 int res;
385 char *path;
386 struct fuse_mknod_out outarg;
387 struct stat buf;
388
Miklos Szeredi5e183482001-10-31 14:52:35 +0000389 res = -ENOENT;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000390 path = get_path_name(in->ino, inarg->name);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000391 if(path != NULL) {
392 res = -ENOSYS;
393 if(f->op.mknod && f->op.getattr) {
394 res = f->op.mknod(path, inarg->mode, inarg->rdev);
395 if(res == 0)
396 res = f->op.getattr(path, &buf);
397 }
398 g_free(path);
Miklos Szeredib483c932001-10-29 14:57:57 +0000399 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000400 if(res == 0) {
Miklos Szeredib483c932001-10-29 14:57:57 +0000401 convert_stat(&buf, &outarg.attr);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000402 outarg.ino = find_node(f, in->ino, inarg->name, outarg.attr.mode);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000403 }
Miklos Szeredib483c932001-10-29 14:57:57 +0000404
405 send_reply(f, in, res, &outarg, sizeof(outarg));
406}
407
408static void do_mkdir(struct fuse *f, struct fuse_in_header *in,
409 struct fuse_mkdir_in *inarg)
410{
411 int res;
412 char *path;
413
Miklos Szeredi5e183482001-10-31 14:52:35 +0000414 res = -ENOENT;
Miklos Szeredib483c932001-10-29 14:57:57 +0000415 path = get_path_name(in->ino, inarg->name);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000416 if(path != NULL) {
417 res = -ENOSYS;
418 if(f->op.mkdir)
419 res = f->op.mkdir(path, inarg->mode);
420 g_free(path);
421 }
Miklos Szeredib483c932001-10-29 14:57:57 +0000422 send_reply(f, in, res, NULL, 0);
423}
424
425static void do_remove(struct fuse *f, struct fuse_in_header *in, char *name)
426{
427 int res;
428 char *path;
429
Miklos Szeredi5e183482001-10-31 14:52:35 +0000430 res = -ENOENT;
Miklos Szeredib483c932001-10-29 14:57:57 +0000431 path = get_path_name(in->ino, name);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000432 if(path != NULL) {
433 res = -ENOSYS;
434 if(in->opcode == FUSE_UNLINK) {
435 if(f->op.unlink)
436 res = f->op.unlink(path);
437 }
438 else {
439 if(f->op.rmdir)
440 res = f->op.rmdir(path);
441 }
442 g_free(path);
Miklos Szeredib483c932001-10-29 14:57:57 +0000443 }
Miklos Szeredi5e183482001-10-31 14:52:35 +0000444 if(res == 0)
445 remove_node(f, in->ino, name);
Miklos Szeredib483c932001-10-29 14:57:57 +0000446 send_reply(f, in, res, NULL, 0);
447}
448
449static void do_symlink(struct fuse *f, struct fuse_in_header *in, char *name,
450 char *link)
451{
452 int res;
453 char *path;
454
Miklos Szeredi5e183482001-10-31 14:52:35 +0000455 res = -ENOENT;
Miklos Szeredib483c932001-10-29 14:57:57 +0000456 path = get_path_name(in->ino, name);
Miklos Szeredi5e183482001-10-31 14:52:35 +0000457 if(path != NULL) {
458 res = -ENOSYS;
459 if(f->op.symlink)
460 res = f->op.symlink(link, path);
461 g_free(path);
462 }
Miklos Szeredib483c932001-10-29 14:57:57 +0000463 send_reply(f, in, res, NULL, 0);
464}
465
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000466static void do_rename(struct fuse *f, struct fuse_in_header *in,
467 struct fuse_rename_in *inarg)
468{
469 int res;
470 fino_t olddir = in->ino;
471 fino_t newdir = inarg->newdir;
472 char *oldname = inarg->names;
473 char *newname = inarg->names + strlen(oldname) + 1;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000474 char *oldpath;
475 char *newpath;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000476
Miklos Szeredi5e183482001-10-31 14:52:35 +0000477 res = -ENOENT;
478 oldpath = get_path_name(olddir, oldname);
479 if(oldpath != NULL) {
480 newpath = get_path_name(newdir, newname);
481 if(newpath != NULL) {
482 res = -ENOSYS;
483 if(f->op.rename)
484 res = f->op.rename(oldpath, newpath);
485 if(res == 0)
486 rename_node(f, olddir, oldname, newdir, newname);
487 g_free(newpath);
488 }
489 g_free(oldpath);
490 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000491 send_reply(f, in, res, NULL, 0);
492}
493
494static void do_link(struct fuse *f, struct fuse_in_header *in,
Miklos Szeredi5e183482001-10-31 14:52:35 +0000495 struct fuse_link_in *arg)
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000496{
497 int res;
Miklos Szeredi5e183482001-10-31 14:52:35 +0000498 char *oldpath;
499 char *newpath;
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000500
Miklos Szeredi5e183482001-10-31 14:52:35 +0000501 res = -ENOENT;
502 oldpath = get_path(in->ino);
503 if(oldpath != NULL) {
504 newpath = get_path_name(arg->newdir, arg->name);
505 if(newpath != NULL) {
506 res = -ENOSYS;
507 if(f->op.link)
508 res = f->op.link(oldpath, newpath);
509 g_free(newpath);
510 }
511 g_free(oldpath);
512 }
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000513 send_reply(f, in, res, NULL, 0);
514}
515
Miklos Szeredi5e183482001-10-31 14:52:35 +0000516static void do_open(struct fuse *f, struct fuse_in_header *in,
517 struct fuse_open_in *arg)
518{
519 int res;
520 char *path;
521
522 res = -ENOENT;
523 path = get_path(in->ino);
524 if(path != NULL) {
525 res = -ENOSYS;
526 if(f->op.open)
527 res = f->op.open(path, arg->flags);
528 g_free(path);
529 }
530 send_reply(f, in, res, NULL, 0);
531}
532
533static void do_read(struct fuse *f, struct fuse_in_header *in,
534 struct fuse_read_in *arg)
535{
536 int res;
537 char *path;
538 char *buf = g_malloc(arg->size);
539 size_t size;
540
541 path = get_path(in->ino);
542 if(path != NULL) {
543 res = -ENOSYS;
544 if(f->op.pread)
545 res = f->op.pread(path, buf, arg->size, arg->offset);
546 g_free(path);
547 }
548
549 size = 0;
550 if(res > 0) {
551 size = res;
552 res = 0;
553 }
554
555 send_reply(f, in, res, buf, size);
556 g_free(buf);
557}
Miklos Szeredib483c932001-10-29 14:57:57 +0000558
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000559void fuse_loop(struct fuse *f)
560{
561 int res;
562 char inbuf[FUSE_MAX_IN];
563 struct fuse_in_header *in = (struct fuse_in_header *) inbuf;
564 void *inarg = inbuf + sizeof(struct fuse_in_header);
565 size_t insize;
566 size_t argsize;
567
568 while(1) {
569 res = read(f->fd, inbuf, sizeof(inbuf));
570 if(res == -1) {
571 perror("reading fuse device");
572 continue;
573 }
574 insize = res;
575
576 if(insize < sizeof(struct fuse_in_header)) {
577 fprintf(stderr, "short read on fuse device\n");
578 continue;
579 }
580 printf("unique: %i, opcode: %i, ino: %li, insize: %i (%i)\n",
581 in->unique, in->opcode, in->ino, insize,
582 g_hash_table_size(f->nametab));
583
584 argsize = insize - sizeof(struct fuse_in_header);
585
586 switch(in->opcode) {
587 case FUSE_LOOKUP:
588 do_lookup(f, in, (char *) inarg);
589 break;
590
591 case FUSE_FORGET:
592 do_forget(f, (unsigned long *) inarg,
593 argsize / sizeof(unsigned long));
594 break;
595
596 case FUSE_GETATTR:
597 do_getattr(f, in);
598 break;
599
Miklos Szeredi5e183482001-10-31 14:52:35 +0000600 case FUSE_SETATTR:
601 do_setattr(f, in, (struct fuse_setattr_in *) inarg);
602 break;
603
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000604 case FUSE_READLINK:
605 do_readlink(f, in);
606 break;
607
608 case FUSE_GETDIR:
609 do_getdir(f, in);
610 break;
611
612 case FUSE_MKNOD:
613 do_mknod(f, in, (struct fuse_mknod_in *) inarg);
614 break;
Miklos Szeredib483c932001-10-29 14:57:57 +0000615
616 case FUSE_MKDIR:
617 do_mkdir(f, in, (struct fuse_mkdir_in *) inarg);
618 break;
619
620 case FUSE_UNLINK:
621 case FUSE_RMDIR:
622 do_remove(f, in, (char *) inarg);
623 break;
624
625 case FUSE_SYMLINK:
626 do_symlink(f, in, (char *) inarg,
627 ((char *) inarg) + strlen((char *) inarg) + 1);
628 break;
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000629
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000630 case FUSE_RENAME:
631 do_rename(f, in, (struct fuse_rename_in *) inarg);
632 break;
633
634 case FUSE_LINK:
635 do_link(f, in, (struct fuse_link_in *) inarg);
636 break;
637
Miklos Szeredi5e183482001-10-31 14:52:35 +0000638 case FUSE_OPEN:
639 do_open(f, in, (struct fuse_open_in *) inarg);
640 break;
641
642 case FUSE_READ:
643 do_read(f, in, (struct fuse_read_in *) inarg);
644 break;
645
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000646 default:
647 fprintf(stderr, "Operation %i not implemented\n", in->opcode);
648 /* No need to send reply to async requests */
649 if(in->unique != 0)
650 send_reply(f, in, -ENOSYS, NULL, 0);
651 }
652 }
653}
654
655struct fuse *fuse_new()
656{
657 struct fuse *f = g_new0(struct fuse, 1);
658
659 f->fd = -1;
660 f->dir = NULL;
661 f->nametab = g_hash_table_new((GHashFunc) name_hash,
662 (GCompareFunc) name_compare);
663
664 return f;
665}
666
Miklos Szeredi85c74fc2001-10-28 19:44:14 +0000667void fuse_set_operations(struct fuse *f, const struct fuse_operations *op)
668{
669 f->op = *op;
670}
671
672void fuse_destroy(struct fuse *f)
673{
674 fuse_unmount(f);
675 g_hash_table_foreach_remove(f->nametab, (GHRFunc) free_node, NULL);
676 g_hash_table_destroy(f->nametab);
677 g_free(f);
678}