blob: 893f723c3a871e636dbe6bdfa1cee09727b3ee48 [file] [log] [blame]
Miklos Szeredi12744942005-07-11 12:32:31 +00001/*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
4
5 This program can be distributed under the terms of the GNU LGPL.
6 See the file COPYING.LIB
7*/
8
Miklos Szeredibd10a7b2005-07-15 09:59:59 +00009#include <config.h>
Miklos Szeredia1482422005-08-14 23:00:27 +000010#include "fuse_lowlevel.h"
Miklos Szeredi12744942005-07-11 12:32:31 +000011#include "fuse_kernel.h"
Miklos Szeredi12744942005-07-11 12:32:31 +000012
13#include <stdio.h>
14#include <string.h>
15#include <stdlib.h>
16#include <unistd.h>
17#include <limits.h>
18#include <errno.h>
Miklos Szeredi12744942005-07-11 12:32:31 +000019#include <stdint.h>
Miklos Szeredi12744942005-07-11 12:32:31 +000020
Miklos Szeredi2482fdb2005-07-12 13:23:53 +000021#define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg)))
Miklos Szeredi12744942005-07-11 12:32:31 +000022
Miklos Szeredia1482422005-08-14 23:00:27 +000023struct fuse_ll {
24 unsigned int debug : 1;
25 unsigned int allow_root : 1;
26 struct fuse_lowlevel_ops op;
27 int got_init;
28 void *userdata;
29 int major;
30 int minor;
31 uid_t owner;
Miklos Szeredi12744942005-07-11 12:32:31 +000032};
33
Miklos Szeredi76c17522005-07-13 14:08:19 +000034struct fuse_req {
35 struct fuse_ll *f;
36 uint64_t unique;
Miklos Szeredibd10a7b2005-07-15 09:59:59 +000037 struct fuse_ctx ctx;
Miklos Szeredia1482422005-08-14 23:00:27 +000038 struct fuse_chan *ch;
Miklos Szeredi76c17522005-07-13 14:08:19 +000039};
40
Miklos Szeredi12744942005-07-11 12:32:31 +000041static const char *opname(enum fuse_opcode opcode)
42{
43 switch (opcode) {
44 case FUSE_LOOKUP: return "LOOKUP";
45 case FUSE_FORGET: return "FORGET";
46 case FUSE_GETATTR: return "GETATTR";
47 case FUSE_SETATTR: return "SETATTR";
48 case FUSE_READLINK: return "READLINK";
49 case FUSE_SYMLINK: return "SYMLINK";
50 case FUSE_MKNOD: return "MKNOD";
51 case FUSE_MKDIR: return "MKDIR";
52 case FUSE_UNLINK: return "UNLINK";
53 case FUSE_RMDIR: return "RMDIR";
54 case FUSE_RENAME: return "RENAME";
55 case FUSE_LINK: return "LINK";
56 case FUSE_OPEN: return "OPEN";
57 case FUSE_READ: return "READ";
58 case FUSE_WRITE: return "WRITE";
59 case FUSE_STATFS: return "STATFS";
60 case FUSE_FLUSH: return "FLUSH";
61 case FUSE_RELEASE: return "RELEASE";
62 case FUSE_FSYNC: return "FSYNC";
63 case FUSE_SETXATTR: return "SETXATTR";
64 case FUSE_GETXATTR: return "GETXATTR";
65 case FUSE_LISTXATTR: return "LISTXATTR";
66 case FUSE_REMOVEXATTR: return "REMOVEXATTR";
67 case FUSE_INIT: return "INIT";
68 case FUSE_OPENDIR: return "OPENDIR";
69 case FUSE_READDIR: return "READDIR";
70 case FUSE_RELEASEDIR: return "RELEASEDIR";
71 case FUSE_FSYNCDIR: return "FSYNCDIR";
Miklos Szeredie3b83092005-07-22 17:24:30 +000072 case FUSE_GETLK: return "GETLK";
73 case FUSE_SETLK: return "SETLK";
74 case FUSE_SETLKW: return "SETLKW";
Miklos Szeredi7b28eae2005-08-01 12:48:30 +000075 case FUSE_ACCESS: return "ACCESS";
Miklos Szeredib0c52c52005-08-23 15:39:43 +000076 case FUSE_CREATE: return "CREATE";
Miklos Szeredi12744942005-07-11 12:32:31 +000077 default: return "???";
78 }
79}
80
Miklos Szeredi76c17522005-07-13 14:08:19 +000081static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr)
Miklos Szeredi12744942005-07-11 12:32:31 +000082{
Miklos Szeredi2482fdb2005-07-12 13:23:53 +000083 attr->ino = stbuf->st_ino;
Miklos Szeredi12744942005-07-11 12:32:31 +000084 attr->mode = stbuf->st_mode;
Miklos Szeredi12744942005-07-11 12:32:31 +000085 attr->nlink = stbuf->st_nlink;
Miklos Szeredi2482fdb2005-07-12 13:23:53 +000086 attr->uid = stbuf->st_uid;
87 attr->gid = stbuf->st_gid;
Miklos Szeredi12744942005-07-11 12:32:31 +000088 attr->rdev = stbuf->st_rdev;
89 attr->size = stbuf->st_size;
90 attr->blocks = stbuf->st_blocks;
91 attr->atime = stbuf->st_atime;
92 attr->mtime = stbuf->st_mtime;
93 attr->ctime = stbuf->st_ctime;
94#ifdef HAVE_STRUCT_STAT_ST_ATIM
95 attr->atimensec = stbuf->st_atim.tv_nsec;
96 attr->mtimensec = stbuf->st_mtim.tv_nsec;
97 attr->ctimensec = stbuf->st_ctim.tv_nsec;
98#endif
99}
100
Miklos Szeredi76c17522005-07-13 14:08:19 +0000101static void convert_attr(const struct fuse_attr *attr, struct stat *stbuf)
102{
103 stbuf->st_mode = attr->mode;
104 stbuf->st_uid = attr->uid;
105 stbuf->st_gid = attr->gid;
106 stbuf->st_size = attr->size;
107 stbuf->st_atime = attr->atime;
108 stbuf->st_mtime = attr->mtime;
109 stbuf->st_ctime = attr->ctime;
110#ifdef HAVE_STRUCT_STAT_ST_ATIM
111 stbuf->st_atim.tv_nsec = attr->atimensec;
112 stbuf->st_mtim.tv_nsec = attr->mtimensec;
113 stbuf->st_ctim.tv_nsec = attr->ctimensec;
114#endif
115}
116
Miklos Szeredie3b83092005-07-22 17:24:30 +0000117static void convert_file_lock(const struct fuse_file_lock *ffl,
118 struct fuse_lock_param *lk)
119{
120 lk->type = ffl->type;
121 lk->start = ffl->start;
122 lk->end = ffl->end;
123 lk->owner = ffl->owner;
124 lk->pid = ffl->pid;
125}
126
127static void convert_lock_param(const struct fuse_lock_param *lk,
128 struct fuse_file_lock *ffl)
129{
130 ffl->type = lk->type;
131 ffl->start = lk->start;
132 ffl->end = lk->end;
133 ffl->owner = lk->owner;
134 ffl->pid = lk->pid;
135}
136
Miklos Szeredi12744942005-07-11 12:32:31 +0000137static size_t iov_length(const struct iovec *iov, size_t count)
138{
139 size_t seg;
140 size_t ret = 0;
141
142 for (seg = 0; seg < count; seg++)
143 ret += iov[seg].iov_len;
144 return ret;
145}
146
Miklos Szeredia1482422005-08-14 23:00:27 +0000147static void free_req(fuse_req_t req)
Miklos Szeredi12744942005-07-11 12:32:31 +0000148{
Miklos Szeredia1482422005-08-14 23:00:27 +0000149 free(req);
Miklos Szeredi12744942005-07-11 12:32:31 +0000150}
151
Miklos Szeredia1482422005-08-14 23:00:27 +0000152static int send_reply(fuse_req_t req, int error, const void *arg,
153 size_t argsize)
Miklos Szeredi12744942005-07-11 12:32:31 +0000154{
155 struct fuse_out_header out;
156 struct iovec iov[2];
157 size_t count;
Miklos Szeredia1482422005-08-14 23:00:27 +0000158 int res;
Miklos Szeredi12744942005-07-11 12:32:31 +0000159
160 if (error <= -1000 || error > 0) {
161 fprintf(stderr, "fuse: bad error value: %i\n", error);
162 error = -ERANGE;
163 }
164
Miklos Szeredia1482422005-08-14 23:00:27 +0000165 out.unique = req->unique;
Miklos Szeredi12744942005-07-11 12:32:31 +0000166 out.error = error;
167 count = 1;
168 iov[0].iov_base = &out;
169 iov[0].iov_len = sizeof(struct fuse_out_header);
170 if (argsize && !error) {
171 count++;
Miklos Szeredi76c17522005-07-13 14:08:19 +0000172 iov[1].iov_base = (void *) arg;
Miklos Szeredi12744942005-07-11 12:32:31 +0000173 iov[1].iov_len = argsize;
174 }
Miklos Szeredia1482422005-08-14 23:00:27 +0000175 out.len = iov_length(iov, count);
176
177 if (req->f->debug) {
178 printf(" unique: %llu, error: %i (%s), outsize: %i\n",
179 out.unique, out.error, strerror(-out.error), out.len);
180 fflush(stdout);
181 }
182 res = fuse_chan_send(req->ch, iov, count);
183 free_req(req);
184
185 return res;
Miklos Szeredi12744942005-07-11 12:32:31 +0000186}
187
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000188size_t fuse_dirent_size(size_t namelen)
Miklos Szeredi12744942005-07-11 12:32:31 +0000189{
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000190 return FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + namelen);
Miklos Szeredi12744942005-07-11 12:32:31 +0000191}
192
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000193char *fuse_add_dirent(char *buf, const char *name, const struct stat *stbuf,
Miklos Szeredi76c17522005-07-13 14:08:19 +0000194 off_t off)
Miklos Szeredi12744942005-07-11 12:32:31 +0000195{
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000196 unsigned namelen = strlen(name);
197 unsigned entlen = FUSE_NAME_OFFSET + namelen;
198 unsigned entsize = fuse_dirent_size(namelen);
199 unsigned padlen = entsize - entlen;
200 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
Miklos Szeredi12744942005-07-11 12:32:31 +0000201
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000202 dirent->ino = stbuf->st_ino;
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000203 dirent->off = off;
204 dirent->namelen = namelen;
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000205 dirent->type = (stbuf->st_mode & 0170000) >> 12;
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000206 strncpy(dirent->name, name, namelen);
207 if (padlen)
208 memset(buf + entlen, 0, padlen);
Miklos Szeredi12744942005-07-11 12:32:31 +0000209
Miklos Szeredi76c17522005-07-13 14:08:19 +0000210 return buf + entsize;
Miklos Szeredi12744942005-07-11 12:32:31 +0000211}
212
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000213static void convert_statfs(const struct statfs *stbuf,
Miklos Szeredi76c17522005-07-13 14:08:19 +0000214 struct fuse_kstatfs *kstatfs)
Miklos Szeredi12744942005-07-11 12:32:31 +0000215{
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000216 kstatfs->bsize = stbuf->f_bsize;
217 kstatfs->blocks = stbuf->f_blocks;
218 kstatfs->bfree = stbuf->f_bfree;
219 kstatfs->bavail = stbuf->f_bavail;
220 kstatfs->files = stbuf->f_files;
221 kstatfs->ffree = stbuf->f_ffree;
222 kstatfs->namelen = stbuf->f_namelen;
Miklos Szeredi12744942005-07-11 12:32:31 +0000223}
224
Miklos Szeredia1482422005-08-14 23:00:27 +0000225static int send_reply_ok(fuse_req_t req, const void *arg, size_t argsize)
Miklos Szeredi76c17522005-07-13 14:08:19 +0000226{
Miklos Szeredia1482422005-08-14 23:00:27 +0000227 return send_reply(req, 0, arg, argsize);
Miklos Szeredi76c17522005-07-13 14:08:19 +0000228}
229
230int fuse_reply_err(fuse_req_t req, int err)
231{
Miklos Szeredia1482422005-08-14 23:00:27 +0000232 return send_reply(req, -err, NULL, 0);
Miklos Szeredi76c17522005-07-13 14:08:19 +0000233}
234
235int fuse_reply_none(fuse_req_t req)
236{
237 free_req(req);
238 return 0;
239}
240
241static unsigned long calc_timeout_sec(double t)
242{
243 if (t > (double) ULONG_MAX)
244 return ULONG_MAX;
245 else if (t < 0.0)
246 return 0;
247 else
248 return (unsigned long) t;
249}
250
251static unsigned int calc_timeout_nsec(double t)
252{
253 double f = t - (double) calc_timeout_sec(t);
254 if (f < 0.0)
255 return 0;
256 else if (f >= 0.999999999)
257 return 999999999;
258 else
259 return (unsigned int) (f * 1.0e9);
260}
261
Miklos Szeredib0c52c52005-08-23 15:39:43 +0000262static void fill_entry(struct fuse_entry_out *arg,
263 const struct fuse_entry_param *e)
264{
265 arg->nodeid = e->ino;
266 arg->generation = e->generation;
267 arg->entry_valid = calc_timeout_sec(e->entry_timeout);
268 arg->entry_valid_nsec = calc_timeout_nsec(e->entry_timeout);
269 arg->attr_valid = calc_timeout_sec(e->attr_timeout);
270 arg->attr_valid_nsec = calc_timeout_nsec(e->attr_timeout);
271 convert_stat(&e->attr, &arg->attr);
272}
273
274static void fill_open(struct fuse_open_out *arg,
275 const struct fuse_file_info *f)
276{
277 arg->fh = f->fh;
278 if (f->direct_io)
279 arg->open_flags |= FOPEN_DIRECT_IO;
280 if (f->keep_cache)
281 arg->open_flags |= FOPEN_KEEP_CACHE;
282}
283
Miklos Szeredi76c17522005-07-13 14:08:19 +0000284int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
285{
286 struct fuse_entry_out arg;
287
288 memset(&arg, 0, sizeof(arg));
Miklos Szeredib0c52c52005-08-23 15:39:43 +0000289 fill_entry(&arg, e);
290 return send_reply_ok(req, &arg, sizeof(arg));
291}
Miklos Szeredi76c17522005-07-13 14:08:19 +0000292
Miklos Szeredib0c52c52005-08-23 15:39:43 +0000293int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e,
294 const struct fuse_file_info *f)
295{
296 struct {
297 struct fuse_entry_out e;
298 struct fuse_open_out o;
299 } arg;
300
301 memset(&arg, 0, sizeof(arg));
302 fill_entry(&arg.e, e);
303 fill_open(&arg.o, f);
Miklos Szeredia1482422005-08-14 23:00:27 +0000304 return send_reply_ok(req, &arg, sizeof(arg));
Miklos Szeredi76c17522005-07-13 14:08:19 +0000305}
306
307int fuse_reply_attr(fuse_req_t req, const struct stat *attr,
308 double attr_timeout)
309{
310 struct fuse_attr_out arg;
311
312 memset(&arg, 0, sizeof(arg));
313 arg.attr_valid = calc_timeout_sec(attr_timeout);
314 arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout);
315 convert_stat(attr, &arg.attr);
316
Miklos Szeredia1482422005-08-14 23:00:27 +0000317 return send_reply_ok(req, &arg, sizeof(arg));
Miklos Szeredi76c17522005-07-13 14:08:19 +0000318}
319
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000320int fuse_reply_readlink(fuse_req_t req, const char *linkname)
Miklos Szeredi76c17522005-07-13 14:08:19 +0000321{
Miklos Szeredia1482422005-08-14 23:00:27 +0000322 return send_reply_ok(req, linkname, strlen(linkname));
Miklos Szeredi76c17522005-07-13 14:08:19 +0000323}
324
325int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *f)
326{
327 struct fuse_open_out arg;
328
329 memset(&arg, 0, sizeof(arg));
Miklos Szeredib0c52c52005-08-23 15:39:43 +0000330 fill_open(&arg, f);
Miklos Szeredia1482422005-08-14 23:00:27 +0000331 return send_reply_ok(req, &arg, sizeof(arg));
Miklos Szeredi76c17522005-07-13 14:08:19 +0000332}
333
334int fuse_reply_write(fuse_req_t req, size_t count)
335{
336 struct fuse_write_out arg;
337
338 memset(&arg, 0, sizeof(arg));
339 arg.size = count;
Miklos Szeredi9b813af2005-07-21 07:59:37 +0000340
Miklos Szeredia1482422005-08-14 23:00:27 +0000341 return send_reply_ok(req, &arg, sizeof(arg));
Miklos Szeredi76c17522005-07-13 14:08:19 +0000342}
343
344int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
345{
Miklos Szeredia1482422005-08-14 23:00:27 +0000346 return send_reply_ok(req, buf, size);
Miklos Szeredi76c17522005-07-13 14:08:19 +0000347}
348
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000349int fuse_reply_statfs(fuse_req_t req, const struct statfs *stbuf)
Miklos Szeredi76c17522005-07-13 14:08:19 +0000350{
351 struct fuse_statfs_out arg;
352
353 memset(&arg, 0, sizeof(arg));
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000354 convert_statfs(stbuf, &arg.st);
Miklos Szeredi9b813af2005-07-21 07:59:37 +0000355
Miklos Szeredia1482422005-08-14 23:00:27 +0000356 return send_reply_ok(req, &arg, sizeof(arg));
Miklos Szeredi76c17522005-07-13 14:08:19 +0000357}
358
359int fuse_reply_xattr(fuse_req_t req, size_t count)
360{
361 struct fuse_getxattr_out arg;
362
363 memset(&arg, 0, sizeof(arg));
364 arg.size = count;
Miklos Szeredi9b813af2005-07-21 07:59:37 +0000365
Miklos Szeredia1482422005-08-14 23:00:27 +0000366 return send_reply_ok(req, &arg, sizeof(arg));
Miklos Szeredi76c17522005-07-13 14:08:19 +0000367}
368
Miklos Szeredie3b83092005-07-22 17:24:30 +0000369int fuse_reply_getlk(fuse_req_t req, const struct fuse_lock_param *lk)
370{
371 struct fuse_lk_in_out arg;
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000372
Miklos Szeredie3b83092005-07-22 17:24:30 +0000373 memset(&arg, 0, sizeof(arg));
374 convert_lock_param(lk, &arg.lk);
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000375
Miklos Szeredia1482422005-08-14 23:00:27 +0000376 return send_reply_ok(req, &arg, sizeof(arg));
Miklos Szeredie3b83092005-07-22 17:24:30 +0000377}
378
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000379static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, char *name)
Miklos Szeredi12744942005-07-11 12:32:31 +0000380{
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000381 if (req->f->op.lookup)
382 req->f->op.lookup(req, nodeid, name);
Miklos Szeredi12744942005-07-11 12:32:31 +0000383 else
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000384 fuse_reply_err(req, ENOSYS);
Miklos Szeredi12744942005-07-11 12:32:31 +0000385}
386
Miklos Szeredi76c17522005-07-13 14:08:19 +0000387static void do_forget(fuse_req_t req, fuse_ino_t nodeid,
388 struct fuse_forget_in *arg)
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000389{
390 if (req->f->op.forget)
Miklos Szeredi76c17522005-07-13 14:08:19 +0000391 req->f->op.forget(req, nodeid, arg->nlookup);
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000392}
393
394static void do_getattr(fuse_req_t req, fuse_ino_t nodeid)
395{
396 if (req->f->op.getattr)
397 req->f->op.getattr(req, nodeid);
398 else
399 fuse_reply_err(req, ENOSYS);
400}
401
402static void do_setattr(fuse_req_t req, fuse_ino_t nodeid,
403 struct fuse_setattr_in *arg)
404{
Miklos Szeredi76c17522005-07-13 14:08:19 +0000405 if (req->f->op.setattr) {
406 struct stat stbuf;
Miklos Szeredie3b83092005-07-22 17:24:30 +0000407 memset(&stbuf, 0, sizeof(stbuf));
Miklos Szeredi76c17522005-07-13 14:08:19 +0000408 convert_attr(&arg->attr, &stbuf);
409 req->f->op.setattr(req, nodeid, &stbuf, arg->valid);
410 } else
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000411 fuse_reply_err(req, ENOSYS);
412}
413
Miklos Szeredi7b28eae2005-08-01 12:48:30 +0000414static void do_access(fuse_req_t req, fuse_ino_t nodeid,
415 struct fuse_access_in *arg)
416{
417 if (req->f->op.access)
418 req->f->op.access(req, nodeid, arg->mask);
419 else
420 fuse_reply_err(req, ENOSYS);
421}
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000422static void do_readlink(fuse_req_t req, fuse_ino_t nodeid)
423{
424 if (req->f->op.readlink)
425 req->f->op.readlink(req, nodeid);
426 else
427 fuse_reply_err(req, ENOSYS);
428}
429
430static void do_mknod(fuse_req_t req, fuse_ino_t nodeid,
431 struct fuse_mknod_in *arg)
432{
433 if (req->f->op.mknod)
434 req->f->op.mknod(req, nodeid, PARAM(arg), arg->mode, arg->rdev);
435 else
436 fuse_reply_err(req, ENOSYS);
437}
438
439static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid,
440 struct fuse_mkdir_in *arg)
441{
442 if (req->f->op.mkdir)
443 req->f->op.mkdir(req, nodeid, PARAM(arg), arg->mode);
444 else
445 fuse_reply_err(req, ENOSYS);
446}
447
448static void do_unlink(fuse_req_t req, fuse_ino_t nodeid, char *name)
449{
450 if (req->f->op.unlink)
451 req->f->op.unlink(req, nodeid, name);
452 else
453 fuse_reply_err(req, ENOSYS);
454}
455
456static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid, char *name)
457{
458 if (req->f->op.rmdir)
459 req->f->op.rmdir(req, nodeid, name);
460 else
461 fuse_reply_err(req, ENOSYS);
462}
463
464static void do_symlink(fuse_req_t req, fuse_ino_t nodeid, char *name,
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000465 char *linkname)
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000466{
467 if (req->f->op.symlink)
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000468 req->f->op.symlink(req, linkname, nodeid, name);
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000469 else
470 fuse_reply_err(req, ENOSYS);
471}
472
473static void do_rename(fuse_req_t req, fuse_ino_t nodeid,
474 struct fuse_rename_in *arg)
475{
476 char *oldname = PARAM(arg);
477 char *newname = oldname + strlen(oldname) + 1;
478
479 if (req->f->op.rename)
480 req->f->op.rename(req, nodeid, oldname, arg->newdir, newname);
481 else
482 fuse_reply_err(req, ENOSYS);
483}
484
485static void do_link(fuse_req_t req, fuse_ino_t nodeid,
486 struct fuse_link_in *arg)
487{
488 if (req->f->op.link)
489 req->f->op.link(req, arg->oldnodeid, nodeid, PARAM(arg));
490 else
491 fuse_reply_err(req, ENOSYS);
492}
493
Miklos Szeredib0c52c52005-08-23 15:39:43 +0000494static void do_create(fuse_req_t req, fuse_ino_t nodeid,
495 struct fuse_open_in *arg)
496{
497 if (req->f->op.create) {
498 struct fuse_file_info fi;
499
500 memset(&fi, 0, sizeof(fi));
501 fi.flags = arg->flags;
502
503 req->f->op.create(req, nodeid, PARAM(arg), arg->mode, &fi);
504 } else
505 fuse_reply_err(req, ENOSYS);
506}
507
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000508static void do_open(fuse_req_t req, fuse_ino_t nodeid,
509 struct fuse_open_in *arg)
510{
511 struct fuse_file_info fi;
Miklos Szeredi9b813af2005-07-21 07:59:37 +0000512
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000513 memset(&fi, 0, sizeof(fi));
514 fi.flags = arg->flags;
515
516 if (req->f->op.open)
517 req->f->op.open(req, nodeid, &fi);
518 else
Miklos Szeredi76c17522005-07-13 14:08:19 +0000519 fuse_reply_open(req, &fi);
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000520}
521
522static void do_read(fuse_req_t req, fuse_ino_t nodeid,
523 struct fuse_read_in *arg)
524{
Miklos Szeredi76c17522005-07-13 14:08:19 +0000525 if (req->f->op.read) {
526 struct fuse_file_info fi;
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000527
Miklos Szeredi76c17522005-07-13 14:08:19 +0000528 memset(&fi, 0, sizeof(fi));
529 fi.fh = arg->fh;
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000530 req->f->op.read(req, nodeid, arg->size, arg->offset, &fi);
Miklos Szeredi76c17522005-07-13 14:08:19 +0000531 } else
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000532 fuse_reply_err(req, ENOSYS);
533}
534
535static void do_write(fuse_req_t req, fuse_ino_t nodeid,
536 struct fuse_write_in *arg)
537{
538 struct fuse_file_info fi;
539
540 memset(&fi, 0, sizeof(fi));
541 fi.fh = arg->fh;
542 fi.writepage = arg->write_flags & 1;
543
544 if (req->f->op.write)
Miklos Szeredi76c17522005-07-13 14:08:19 +0000545 req->f->op.write(req, nodeid, PARAM(arg), arg->size,
546 arg->offset, &fi);
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000547 else
548 fuse_reply_err(req, ENOSYS);
549}
550
551static void do_flush(fuse_req_t req, fuse_ino_t nodeid,
552 struct fuse_flush_in *arg)
553{
554 struct fuse_file_info fi;
555
556 memset(&fi, 0, sizeof(fi));
557 fi.fh = arg->fh;
558
559 if (req->f->op.flush)
560 req->f->op.flush(req, nodeid, &fi);
561 else
562 fuse_reply_err(req, ENOSYS);
563}
564
565static void do_release(fuse_req_t req, fuse_ino_t nodeid,
566 struct fuse_release_in *arg)
567{
568 struct fuse_file_info fi;
569
570 memset(&fi, 0, sizeof(fi));
571 fi.flags = arg->flags;
572 fi.fh = arg->fh;
573
574 if (req->f->op.release)
575 req->f->op.release(req, nodeid, &fi);
576 else
Miklos Szeredi76c17522005-07-13 14:08:19 +0000577 fuse_reply_err(req, 0);
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000578}
579
580static void do_fsync(fuse_req_t req, fuse_ino_t nodeid,
Miklos Szeredi12744942005-07-11 12:32:31 +0000581 struct fuse_fsync_in *inarg)
582{
Miklos Szeredi12744942005-07-11 12:32:31 +0000583 struct fuse_file_info fi;
584
585 memset(&fi, 0, sizeof(fi));
586 fi.fh = inarg->fh;
587
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000588 if (req->f->op.fsync)
589 req->f->op.fsync(req, nodeid, inarg->fsync_flags & 1, &fi);
590 else
591 fuse_reply_err(req, ENOSYS);
592}
593
594static void do_opendir(fuse_req_t req, fuse_ino_t nodeid,
595 struct fuse_open_in *arg)
596{
597 struct fuse_file_info fi;
598
599 memset(&fi, 0, sizeof(fi));
600 fi.flags = arg->flags;
601
602 if (req->f->op.opendir)
603 req->f->op.opendir(req, nodeid, &fi);
604 else
Miklos Szeredi76c17522005-07-13 14:08:19 +0000605 fuse_reply_open(req, &fi);
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000606}
607
608static void do_readdir(fuse_req_t req, fuse_ino_t nodeid,
609 struct fuse_read_in *arg)
610{
611 struct fuse_file_info fi;
612
613 memset(&fi, 0, sizeof(fi));
614 fi.fh = arg->fh;
615
616 if (req->f->op.readdir)
617 req->f->op.readdir(req, nodeid, arg->size, arg->offset, &fi);
618 else
619 fuse_reply_err(req, ENOSYS);
620}
621
622static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid,
623 struct fuse_release_in *arg)
624{
625 struct fuse_file_info fi;
626
627 memset(&fi, 0, sizeof(fi));
628 fi.flags = arg->flags;
629 fi.fh = arg->fh;
630
631 if (req->f->op.releasedir)
632 req->f->op.releasedir(req, nodeid, &fi);
633 else
Miklos Szeredi76c17522005-07-13 14:08:19 +0000634 fuse_reply_err(req, 0);
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000635}
636
637static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid,
638 struct fuse_fsync_in *inarg)
639{
640 struct fuse_file_info fi;
641
642 memset(&fi, 0, sizeof(fi));
643 fi.fh = inarg->fh;
644
645 if (req->f->op.fsyncdir)
646 req->f->op.fsyncdir(req, nodeid, inarg->fsync_flags & 1, &fi);
647 else
648 fuse_reply_err(req, ENOSYS);
649}
650
Miklos Szeredibd10a7b2005-07-15 09:59:59 +0000651static void do_statfs(fuse_req_t req)
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000652{
653 if (req->f->op.statfs)
Miklos Szeredibd10a7b2005-07-15 09:59:59 +0000654 req->f->op.statfs(req);
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000655 else
656 fuse_reply_err(req, ENOSYS);
Miklos Szeredi12744942005-07-11 12:32:31 +0000657}
658
Miklos Szeredi4331a272005-07-12 14:51:04 +0000659static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid,
Miklos Szeredi12744942005-07-11 12:32:31 +0000660 struct fuse_setxattr_in *arg)
661{
Miklos Szeredi12744942005-07-11 12:32:31 +0000662 char *name = PARAM(arg);
Miklos Szeredi1b188022005-07-28 11:07:29 +0000663 char *value = name + strlen(name) + 1;
Miklos Szeredi12744942005-07-11 12:32:31 +0000664
Miklos Szeredi4331a272005-07-12 14:51:04 +0000665 if (req->f->op.setxattr)
Miklos Szeredi76c17522005-07-13 14:08:19 +0000666 req->f->op.setxattr(req, nodeid, name, value, arg->size,
667 arg->flags);
Miklos Szeredi4331a272005-07-12 14:51:04 +0000668 else
669 fuse_reply_err(req, ENOSYS);
Miklos Szeredi12744942005-07-11 12:32:31 +0000670}
671
Miklos Szeredi4331a272005-07-12 14:51:04 +0000672static void do_getxattr(fuse_req_t req, fuse_ino_t nodeid,
Miklos Szeredi12744942005-07-11 12:32:31 +0000673 struct fuse_getxattr_in *arg)
674{
Miklos Szeredi4331a272005-07-12 14:51:04 +0000675 if (req->f->op.getxattr)
676 req->f->op.getxattr(req, nodeid, PARAM(arg), arg->size);
Miklos Szeredi12744942005-07-11 12:32:31 +0000677 else
Miklos Szeredi4331a272005-07-12 14:51:04 +0000678 fuse_reply_err(req, ENOSYS);
Miklos Szeredi12744942005-07-11 12:32:31 +0000679}
680
Miklos Szeredi4331a272005-07-12 14:51:04 +0000681static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid,
Miklos Szeredi12744942005-07-11 12:32:31 +0000682 struct fuse_getxattr_in *arg)
683{
Miklos Szeredi4331a272005-07-12 14:51:04 +0000684 if (req->f->op.listxattr)
685 req->f->op.listxattr(req, nodeid, arg->size);
Miklos Szeredi12744942005-07-11 12:32:31 +0000686 else
Miklos Szeredi4331a272005-07-12 14:51:04 +0000687 fuse_reply_err(req, ENOSYS);
Miklos Szeredi12744942005-07-11 12:32:31 +0000688}
689
Miklos Szeredi4331a272005-07-12 14:51:04 +0000690static void do_removexattr(fuse_req_t req, fuse_ino_t nodeid, char *name)
Miklos Szeredi12744942005-07-11 12:32:31 +0000691{
Miklos Szeredi4331a272005-07-12 14:51:04 +0000692 if (req->f->op.removexattr)
693 req->f->op.removexattr(req, nodeid, name);
694 else
695 fuse_reply_err(req, ENOSYS);
Miklos Szeredi12744942005-07-11 12:32:31 +0000696}
697
Miklos Szeredie3b83092005-07-22 17:24:30 +0000698static void do_getlk(fuse_req_t req, fuse_ino_t nodeid,
699 struct fuse_lk_in_out *arg)
700{
701 if (req->f->op.getlk) {
702 struct fuse_lock_param lk;
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000703
Miklos Szeredie3b83092005-07-22 17:24:30 +0000704 memset(&lk, 0, sizeof(lk));
705 convert_file_lock(&arg->lk, &lk);
706 req->f->op.getlk(req, nodeid, &lk);
707 } else
708 fuse_reply_err(req, ENOSYS);
709}
710
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000711static void do_setlk(fuse_req_t req, fuse_ino_t nodeid, int issleep,
Miklos Szeredie3b83092005-07-22 17:24:30 +0000712 struct fuse_lk_in_out *arg)
713{
714 if (req->f->op.setlk) {
715 struct fuse_lock_param lk;
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000716
Miklos Szeredie3b83092005-07-22 17:24:30 +0000717 memset(&lk, 0, sizeof(lk));
718 convert_file_lock(&arg->lk, &lk);
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000719 req->f->op.setlk(req, nodeid, issleep, &lk);
Miklos Szeredie3b83092005-07-22 17:24:30 +0000720 } else
721 fuse_reply_err(req, ENOSYS);
722}
723
Miklos Szeredia1482422005-08-14 23:00:27 +0000724static void do_init(fuse_req_t req, struct fuse_init_in_out *arg)
Miklos Szeredi12744942005-07-11 12:32:31 +0000725{
726 struct fuse_init_in_out outarg;
Miklos Szeredia1482422005-08-14 23:00:27 +0000727 struct fuse_ll *f = req->f;
Miklos Szeredi12744942005-07-11 12:32:31 +0000728
Miklos Szeredi76c17522005-07-13 14:08:19 +0000729 if (f->debug) {
Miklos Szeredi12744942005-07-11 12:32:31 +0000730 printf("INIT: %u.%u\n", arg->major, arg->minor);
731 fflush(stdout);
732 }
733 f->got_init = 1;
734 if (f->op.init)
Miklos Szeredia1482422005-08-14 23:00:27 +0000735 f->op.init(f->userdata);
Miklos Szeredi12744942005-07-11 12:32:31 +0000736
Miklos Szeredi76c17522005-07-13 14:08:19 +0000737 f->major = FUSE_KERNEL_VERSION;
738 f->minor = FUSE_KERNEL_MINOR_VERSION;
739
Miklos Szeredi12744942005-07-11 12:32:31 +0000740 memset(&outarg, 0, sizeof(outarg));
741 outarg.major = f->major;
742 outarg.minor = f->minor;
743
Miklos Szeredi76c17522005-07-13 14:08:19 +0000744 if (f->debug) {
Miklos Szeredi12744942005-07-11 12:32:31 +0000745 printf(" INIT: %u.%u\n", outarg.major, outarg.minor);
746 fflush(stdout);
747 }
748
Miklos Szeredia1482422005-08-14 23:00:27 +0000749 send_reply_ok(req, &outarg, sizeof(outarg));
Miklos Szeredi12744942005-07-11 12:32:31 +0000750}
751
Miklos Szeredibd10a7b2005-07-15 09:59:59 +0000752void *fuse_req_userdata(fuse_req_t req)
753{
754 return req->f->userdata;
755}
756
757const struct fuse_ctx *fuse_req_ctx(fuse_req_t req)
758{
759 return &req->ctx;
760}
761
Miklos Szeredia1482422005-08-14 23:00:27 +0000762static void fuse_ll_process(void *data, const char *buf, size_t len,
763 struct fuse_chan *ch)
Miklos Szeredi12744942005-07-11 12:32:31 +0000764{
Miklos Szeredia1482422005-08-14 23:00:27 +0000765 struct fuse_ll *f = (struct fuse_ll *) data;
766 struct fuse_in_header *in = (struct fuse_in_header *) buf;
767 const void *inarg = buf + sizeof(struct fuse_in_header);
Miklos Szeredi76c17522005-07-13 14:08:19 +0000768 struct fuse_req *req;
Miklos Szeredi12744942005-07-11 12:32:31 +0000769
Miklos Szeredi76c17522005-07-13 14:08:19 +0000770 if (f->debug) {
Miklos Szeredi12744942005-07-11 12:32:31 +0000771 printf("unique: %llu, opcode: %s (%i), nodeid: %lu, insize: %i\n",
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000772 in->unique, opname((enum fuse_opcode) in->opcode), in->opcode,
Miklos Szeredia1482422005-08-14 23:00:27 +0000773 (unsigned long) in->nodeid, len);
Miklos Szeredi12744942005-07-11 12:32:31 +0000774 fflush(stdout);
775 }
776
Miklos Szeredi76c17522005-07-13 14:08:19 +0000777 req = (struct fuse_req *) malloc(sizeof(struct fuse_req));
778 if (req == NULL) {
779 fprintf(stderr, "fuse: failed to allocate request\n");
Miklos Szeredia1482422005-08-14 23:00:27 +0000780 return;
Miklos Szeredi76c17522005-07-13 14:08:19 +0000781 }
Miklos Szeredi9b813af2005-07-21 07:59:37 +0000782
Miklos Szeredi76c17522005-07-13 14:08:19 +0000783 req->f = f;
784 req->unique = in->unique;
Miklos Szeredibd10a7b2005-07-15 09:59:59 +0000785 req->ctx.uid = in->uid;
786 req->ctx.gid = in->gid;
787 req->ctx.pid = in->pid;
Miklos Szeredia1482422005-08-14 23:00:27 +0000788 req->ch = ch;
Miklos Szeredi12744942005-07-11 12:32:31 +0000789
Miklos Szeredia1482422005-08-14 23:00:27 +0000790 if (!f->got_init && in->opcode != FUSE_INIT)
791 fuse_reply_err(req, EPROTO);
792 else if (f->allow_root && in->uid != f->owner && in->uid != 0 &&
793 in->opcode != FUSE_INIT && in->opcode != FUSE_READ &&
794 in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC &&
795 in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR &&
796 in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR) {
797 fuse_reply_err(req, EACCES);
798 } else switch (in->opcode) {
799 case FUSE_INIT:
800 do_init(req, (struct fuse_init_in_out *) inarg);
801 break;
802
Miklos Szeredi12744942005-07-11 12:32:31 +0000803 case FUSE_LOOKUP:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000804 do_lookup(req, in->nodeid, (char *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000805 break;
806
Miklos Szeredi76c17522005-07-13 14:08:19 +0000807 case FUSE_FORGET:
808 do_forget(req, in->nodeid, (struct fuse_forget_in *) inarg);
Miklos Szeredi2482fdb2005-07-12 13:23:53 +0000809 break;
Miklos Szeredi76c17522005-07-13 14:08:19 +0000810
Miklos Szeredi12744942005-07-11 12:32:31 +0000811 case FUSE_GETATTR:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000812 do_getattr(req, in->nodeid);
Miklos Szeredi12744942005-07-11 12:32:31 +0000813 break;
814
815 case FUSE_SETATTR:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000816 do_setattr(req, in->nodeid, (struct fuse_setattr_in *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000817 break;
818
819 case FUSE_READLINK:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000820 do_readlink(req, in->nodeid);
Miklos Szeredi12744942005-07-11 12:32:31 +0000821 break;
822
823 case FUSE_MKNOD:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000824 do_mknod(req, in->nodeid, (struct fuse_mknod_in *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000825 break;
826
827 case FUSE_MKDIR:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000828 do_mkdir(req, in->nodeid, (struct fuse_mkdir_in *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000829 break;
830
831 case FUSE_UNLINK:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000832 do_unlink(req, in->nodeid, (char *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000833 break;
834
835 case FUSE_RMDIR:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000836 do_rmdir(req, in->nodeid, (char *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000837 break;
838
839 case FUSE_SYMLINK:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000840 do_symlink(req, in->nodeid, (char *) inarg,
Miklos Szeredi12744942005-07-11 12:32:31 +0000841 ((char *) inarg) + strlen((char *) inarg) + 1);
842 break;
843
844 case FUSE_RENAME:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000845 do_rename(req, in->nodeid, (struct fuse_rename_in *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000846 break;
847
848 case FUSE_LINK:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000849 do_link(req, in->nodeid, (struct fuse_link_in *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000850 break;
851
852 case FUSE_OPEN:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000853 do_open(req, in->nodeid, (struct fuse_open_in *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000854 break;
855
856 case FUSE_FLUSH:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000857 do_flush(req, in->nodeid, (struct fuse_flush_in *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000858 break;
859
860 case FUSE_RELEASE:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000861 do_release(req, in->nodeid, (struct fuse_release_in *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000862 break;
863
864 case FUSE_READ:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000865 do_read(req, in->nodeid, (struct fuse_read_in *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000866 break;
867
868 case FUSE_WRITE:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000869 do_write(req, in->nodeid, (struct fuse_write_in *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000870 break;
871
872 case FUSE_STATFS:
Miklos Szeredibd10a7b2005-07-15 09:59:59 +0000873 do_statfs(req);
Miklos Szeredi12744942005-07-11 12:32:31 +0000874 break;
875
876 case FUSE_FSYNC:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000877 do_fsync(req, in->nodeid, (struct fuse_fsync_in *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000878 break;
879
880 case FUSE_SETXATTR:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000881 do_setxattr(req, in->nodeid, (struct fuse_setxattr_in *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000882 break;
883
884 case FUSE_GETXATTR:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000885 do_getxattr(req, in->nodeid, (struct fuse_getxattr_in *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000886 break;
887
888 case FUSE_LISTXATTR:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000889 do_listxattr(req, in->nodeid, (struct fuse_getxattr_in *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000890 break;
891
892 case FUSE_REMOVEXATTR:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000893 do_removexattr(req, in->nodeid, (char *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000894 break;
895
896 case FUSE_OPENDIR:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000897 do_opendir(req, in->nodeid, (struct fuse_open_in *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000898 break;
899
900 case FUSE_READDIR:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000901 do_readdir(req, in->nodeid, (struct fuse_read_in *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000902 break;
903
904 case FUSE_RELEASEDIR:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000905 do_releasedir(req, in->nodeid, (struct fuse_release_in *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000906 break;
907
908 case FUSE_FSYNCDIR:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000909 do_fsyncdir(req, in->nodeid, (struct fuse_fsync_in *) inarg);
Miklos Szeredi12744942005-07-11 12:32:31 +0000910 break;
911
Miklos Szeredie3b83092005-07-22 17:24:30 +0000912 case FUSE_GETLK:
913 do_getlk(req, in->nodeid, (struct fuse_lk_in_out *) inarg);
914 break;
915
916 case FUSE_SETLK:
917 do_setlk(req, in->nodeid, 0, (struct fuse_lk_in_out *) inarg);
918 break;
919
920 case FUSE_SETLKW:
921 do_setlk(req, in->nodeid, 1, (struct fuse_lk_in_out *) inarg);
922 break;
Miklos Szeredif6e0ec62005-08-03 09:11:06 +0000923
Miklos Szeredi7b28eae2005-08-01 12:48:30 +0000924 case FUSE_ACCESS:
925 do_access(req, in->nodeid, (struct fuse_access_in *) inarg);
926 break;
Miklos Szeredie3b83092005-07-22 17:24:30 +0000927
Miklos Szeredib0c52c52005-08-23 15:39:43 +0000928 case FUSE_CREATE:
929 do_create(req, in->nodeid, (struct fuse_open_in *) inarg);
930 break;
931
Miklos Szeredi12744942005-07-11 12:32:31 +0000932 default:
Miklos Szeredi76c17522005-07-13 14:08:19 +0000933 fuse_reply_err(req, ENOSYS);
Miklos Szeredi12744942005-07-11 12:32:31 +0000934 }
Miklos Szeredi12744942005-07-11 12:32:31 +0000935}
936
Miklos Szeredia1482422005-08-14 23:00:27 +0000937int fuse_lowlevel_is_lib_option(const char *opt)
Miklos Szeredi12744942005-07-11 12:32:31 +0000938{
939 if (strcmp(opt, "debug") == 0 ||
Miklos Szeredi76c17522005-07-13 14:08:19 +0000940 strcmp(opt, "allow_root") == 0)
Miklos Szeredi12744942005-07-11 12:32:31 +0000941 return 1;
942 else
943 return 0;
944}
945
Miklos Szeredi76c17522005-07-13 14:08:19 +0000946static int parse_ll_opts(struct fuse_ll *f, const char *opts)
Miklos Szeredi12744942005-07-11 12:32:31 +0000947{
948 if (opts) {
949 char *xopts = strdup(opts);
950 char *s = xopts;
951 char *opt;
952
953 if (xopts == NULL) {
954 fprintf(stderr, "fuse: memory allocation failed\n");
955 return -1;
956 }
957
958 while((opt = strsep(&s, ","))) {
959 if (strcmp(opt, "debug") == 0)
Miklos Szeredi76c17522005-07-13 14:08:19 +0000960 f->debug = 1;
Miklos Szeredi12744942005-07-11 12:32:31 +0000961 else if (strcmp(opt, "allow_root") == 0)
Miklos Szeredi76c17522005-07-13 14:08:19 +0000962 f->allow_root = 1;
Miklos Szeredi12744942005-07-11 12:32:31 +0000963 else
964 fprintf(stderr, "fuse: warning: unknown option `%s'\n", opt);
965 }
966 free(xopts);
967 }
968 return 0;
969}
970
Miklos Szeredia1482422005-08-14 23:00:27 +0000971static void fuse_ll_destroy(void *data)
972{
973 struct fuse_ll *f = (struct fuse_ll *) data;
974
975 if (f->op.destroy)
976 f->op.destroy(f->userdata);
977
978 free(f);
979}
980
981
982struct fuse_session *fuse_lowlevel_new(const char *opts,
983 const struct fuse_lowlevel_ops *op,
984 size_t op_size, void *userdata)
Miklos Szeredi12744942005-07-11 12:32:31 +0000985{
986 struct fuse_ll *f;
Miklos Szeredia1482422005-08-14 23:00:27 +0000987 struct fuse_session *se;
988 struct fuse_session_ops sop = {
989 .process = fuse_ll_process,
990 .destroy = fuse_ll_destroy,
991 };
Miklos Szeredi12744942005-07-11 12:32:31 +0000992
Miklos Szeredia1482422005-08-14 23:00:27 +0000993 if (sizeof(struct fuse_lowlevel_ops) < op_size) {
Miklos Szeredi12744942005-07-11 12:32:31 +0000994 fprintf(stderr, "fuse: warning: library too old, some operations may not not work\n");
Miklos Szeredia1482422005-08-14 23:00:27 +0000995 op_size = sizeof(struct fuse_lowlevel_ops);
Miklos Szeredi12744942005-07-11 12:32:31 +0000996 }
997
998 f = (struct fuse_ll *) calloc(1, sizeof(struct fuse_ll));
999 if (f == NULL) {
1000 fprintf(stderr, "fuse: failed to allocate fuse object\n");
1001 goto out;
1002 }
1003
Miklos Szeredi76c17522005-07-13 14:08:19 +00001004 if (parse_ll_opts(f, opts) == -1)
Miklos Szeredi12744942005-07-11 12:32:31 +00001005 goto out_free;
1006
Miklos Szeredi12744942005-07-11 12:32:31 +00001007 memcpy(&f->op, op, op_size);
Miklos Szeredi12744942005-07-11 12:32:31 +00001008 f->owner = getuid();
Miklos Szeredibd10a7b2005-07-15 09:59:59 +00001009 f->userdata = userdata;
Miklos Szeredi12744942005-07-11 12:32:31 +00001010
Miklos Szeredia1482422005-08-14 23:00:27 +00001011 se = fuse_session_new(&sop, f);
1012 if (!se)
1013 goto out_free;
1014
1015 return se;
Miklos Szeredi12744942005-07-11 12:32:31 +00001016
1017 out_free:
1018 free(f);
1019 out:
1020 return NULL;
1021}
1022