43
fuse_interrupt_func_t func;
47
struct fuse_req *next;
48
struct fuse_req *prev;
43
fuse_interrupt_func_t func;
47
struct fuse_req *next;
48
struct fuse_req *prev;
54
struct fuse_lowlevel_ops op;
58
struct fuse_conn_info conn;
60
struct fuse_req interrupts;
54
struct fuse_lowlevel_ops op;
58
struct fuse_conn_info conn;
60
struct fuse_req interrupts;
65
65
static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr)
67
attr->ino = stbuf->st_ino;
68
attr->mode = stbuf->st_mode;
69
attr->nlink = stbuf->st_nlink;
70
attr->uid = stbuf->st_uid;
71
attr->gid = stbuf->st_gid;
72
attr->rdev = stbuf->st_rdev;
73
attr->size = stbuf->st_size;
74
attr->blocks = stbuf->st_blocks;
75
attr->atime = stbuf->st_atime;
76
attr->mtime = stbuf->st_mtime;
77
attr->ctime = stbuf->st_ctime;
78
attr->atimensec = ST_ATIM_NSEC(stbuf);
79
attr->mtimensec = ST_MTIM_NSEC(stbuf);
80
attr->ctimensec = ST_CTIM_NSEC(stbuf);
67
attr->ino = stbuf->st_ino;
68
attr->mode = stbuf->st_mode;
69
attr->nlink = stbuf->st_nlink;
70
attr->uid = stbuf->st_uid;
71
attr->gid = stbuf->st_gid;
72
attr->rdev = stbuf->st_rdev;
73
attr->size = stbuf->st_size;
74
attr->blocks = stbuf->st_blocks;
75
attr->atime = stbuf->st_atime;
76
attr->mtime = stbuf->st_mtime;
77
attr->ctime = stbuf->st_ctime;
78
attr->atimensec = ST_ATIM_NSEC(stbuf);
79
attr->mtimensec = ST_MTIM_NSEC(stbuf);
80
attr->ctimensec = ST_CTIM_NSEC(stbuf);
83
83
static void convert_attr(const struct fuse_setattr_in *attr, struct stat *stbuf)
85
stbuf->st_mode = attr->mode;
86
stbuf->st_uid = attr->uid;
87
stbuf->st_gid = attr->gid;
88
stbuf->st_size = attr->size;
89
stbuf->st_atime = attr->atime;
90
stbuf->st_mtime = attr->mtime;
91
ST_ATIM_NSEC_SET(stbuf, attr->atimensec);
92
ST_MTIM_NSEC_SET(stbuf, attr->mtimensec);
85
stbuf->st_mode = attr->mode;
86
stbuf->st_uid = attr->uid;
87
stbuf->st_gid = attr->gid;
88
stbuf->st_size = attr->size;
89
stbuf->st_atime = attr->atime;
90
stbuf->st_mtime = attr->mtime;
91
ST_ATIM_NSEC_SET(stbuf, attr->atimensec);
92
ST_MTIM_NSEC_SET(stbuf, attr->mtimensec);
95
static size_t iov_length(const struct iovec *iov, size_t count)
95
static size_t iov_length(const struct iovec *iov, size_t count)
100
for (seg = 0; seg < count; seg++)
101
ret += iov[seg].iov_len;
100
for (seg = 0; seg < count; seg++)
101
ret += iov[seg].iov_len;
105
105
static void list_init_req(struct fuse_req *req)
111
111
static void list_del_req(struct fuse_req *req)
113
struct fuse_req *prev = req->prev;
114
struct fuse_req *next = req->next;
113
struct fuse_req *prev = req->prev;
114
struct fuse_req *next = req->next;
119
119
static void list_add_req(struct fuse_req *req, struct fuse_req *next)
121
struct fuse_req *prev = next->prev;
121
struct fuse_req *prev = next->prev;
128
128
static void destroy_req(fuse_req_t req)
130
pthread_mutex_destroy(&req->lock);
130
pthread_mutex_destroy(&req->lock);
134
134
static void free_req(fuse_req_t req)
137
struct fuse_ll *f = req->f;
139
pthread_mutex_lock(&req->lock);
140
req->u.ni.func = NULL;
141
req->u.ni.data = NULL;
142
pthread_mutex_unlock(&req->lock);
144
pthread_mutex_lock(&f->lock);
147
pthread_mutex_unlock(&f->lock);
137
struct fuse_ll *f = req->f;
139
pthread_mutex_lock(&req->lock);
140
req->u.ni.func = NULL;
141
req->u.ni.data = NULL;
142
pthread_mutex_unlock(&req->lock);
144
pthread_mutex_lock(&f->lock);
147
pthread_mutex_unlock(&f->lock);
152
152
static int send_reply_iov(fuse_req_t req, int error, struct iovec *iov,
155
struct fuse_out_header out;
158
if (error <= -1000 || error > 0) {
159
fprintf(stderr, "fuse: bad error value: %i\n", error);
163
out.unique = req->unique;
165
iov[0].iov_base = &out;
166
iov[0].iov_len = sizeof(struct fuse_out_header);
167
out.len = iov_length(iov, count);
170
fprintf(stderr, " unique: %llu, error: %i (%s), outsize: %i\n",
171
(unsigned long long) out.unique, out.error,
172
strerror(-out.error), out.len);
173
res = fuse_chan_send(req->ch, iov, count);
155
struct fuse_out_header out;
158
if (error <= -1000 || error > 0) {
159
fprintf(stderr, "fuse: bad error value: %i\n", error);
163
out.unique = req->unique;
165
iov[0].iov_base = &out;
166
iov[0].iov_len = sizeof(struct fuse_out_header);
167
out.len = iov_length(iov, count);
171
" unique: %llu, error: %i (%s), outsize: %i\n",
172
(unsigned long long) out.unique, out.error,
173
strerror(-out.error), out.len);
174
res = fuse_chan_send(req->ch, iov, count);
179
180
static int send_reply(fuse_req_t req, int error, const void *arg,
185
iov[1].iov_base = (void *) arg;
186
iov[1].iov_len = argsize;
189
return send_reply_iov(req, error, iov, count);
186
iov[1].iov_base = (void *) arg;
187
iov[1].iov_len = argsize;
190
return send_reply_iov(req, error, iov, count);
192
193
int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count)
195
struct iovec *padded_iov;
197
padded_iov = malloc((count + 1) * sizeof(struct iovec));
198
if (padded_iov == NULL)
199
return fuse_reply_err(req, -ENOMEM);
201
memcpy(padded_iov + 1, iov, count * sizeof(struct iovec));
204
res = send_reply_iov(req, 0, padded_iov, count);
196
struct iovec *padded_iov;
198
padded_iov = malloc((count + 1) * sizeof(struct iovec));
199
if (padded_iov == NULL)
200
return fuse_reply_err(req, -ENOMEM);
202
memcpy(padded_iov + 1, iov, count * sizeof(struct iovec));
205
res = send_reply_iov(req, 0, padded_iov, count);
210
211
size_t fuse_dirent_size(size_t namelen)
212
return FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + namelen);
213
return FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + namelen);
215
216
char *fuse_add_dirent(char *buf, const char *name, const struct stat *stbuf,
218
unsigned namelen = strlen(name);
219
unsigned entlen = FUSE_NAME_OFFSET + namelen;
220
unsigned entsize = fuse_dirent_size(namelen);
221
unsigned padlen = entsize - entlen;
222
struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
224
dirent->ino = stbuf->st_ino;
226
dirent->namelen = namelen;
227
dirent->type = (stbuf->st_mode & 0170000) >> 12;
228
strncpy(dirent->name, name, namelen);
230
memset(buf + entlen, 0, padlen);
232
return buf + entsize;
219
unsigned namelen = strlen(name);
220
unsigned entlen = FUSE_NAME_OFFSET + namelen;
221
unsigned entsize = fuse_dirent_size(namelen);
222
unsigned padlen = entsize - entlen;
223
struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
225
dirent->ino = stbuf->st_ino;
227
dirent->namelen = namelen;
228
dirent->type = (stbuf->st_mode & 0170000) >> 12;
229
strncpy(dirent->name, name, namelen);
231
memset(buf + entlen, 0, padlen);
233
return buf + entsize;
235
236
size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize,
236
const char *name, const struct stat *stbuf, off_t off)
237
const char *name, const struct stat *stbuf, off_t off)
241
entsize = fuse_dirent_size(strlen(name));
242
if (entsize <= bufsize && buf)
243
fuse_add_dirent(buf, name, stbuf, off);
242
entsize = fuse_dirent_size(strlen(name));
243
if (entsize <= bufsize && buf)
244
fuse_add_dirent(buf, name, stbuf, off);
247
248
static void convert_statfs(const struct statvfs *stbuf,
248
struct fuse_kstatfs *kstatfs)
249
struct fuse_kstatfs *kstatfs)
250
kstatfs->bsize = stbuf->f_bsize;
251
kstatfs->frsize = stbuf->f_frsize;
252
kstatfs->blocks = stbuf->f_blocks;
253
kstatfs->bfree = stbuf->f_bfree;
254
kstatfs->bavail = stbuf->f_bavail;
255
kstatfs->files = stbuf->f_files;
256
kstatfs->ffree = stbuf->f_ffree;
257
kstatfs->namelen = stbuf->f_namemax;
251
kstatfs->bsize = stbuf->f_bsize;
252
kstatfs->frsize = stbuf->f_frsize;
253
kstatfs->blocks = stbuf->f_blocks;
254
kstatfs->bfree = stbuf->f_bfree;
255
kstatfs->bavail = stbuf->f_bavail;
256
kstatfs->files = stbuf->f_files;
257
kstatfs->ffree = stbuf->f_ffree;
258
kstatfs->namelen = stbuf->f_namemax;
260
261
static int send_reply_ok(fuse_req_t req, const void *arg, size_t argsize)
262
return send_reply(req, 0, arg, argsize);
263
return send_reply(req, 0, arg, argsize);
265
266
int fuse_reply_err(fuse_req_t req, int err)
267
return send_reply(req, -err, NULL, 0);
268
return send_reply(req, -err, NULL, 0);
270
271
void fuse_reply_none(fuse_req_t req)
272
fuse_chan_send(req->ch, NULL, 0);
273
fuse_chan_send(req->ch, NULL, 0);
276
277
static unsigned long calc_timeout_sec(double t)
278
if (t > (double) ULONG_MAX)
283
return (unsigned long) t;
279
if (t > (double) ULONG_MAX)
284
return (unsigned long) t;
286
287
static unsigned int calc_timeout_nsec(double t)
288
double f = t - (double) calc_timeout_sec(t);
291
else if (f >= 0.999999999)
294
return (unsigned int) (f * 1.0e9);
289
double f = t - (double) calc_timeout_sec(t);
292
else if (f >= 0.999999999)
295
return (unsigned int) (f * 1.0e9);
297
298
static void fill_entry(struct fuse_entry_out *arg,
298
const struct fuse_entry_param *e)
299
const struct fuse_entry_param *e)
300
arg->nodeid = e->ino;
301
arg->generation = e->generation;
302
arg->entry_valid = calc_timeout_sec(e->entry_timeout);
303
arg->entry_valid_nsec = calc_timeout_nsec(e->entry_timeout);
304
arg->attr_valid = calc_timeout_sec(e->attr_timeout);
305
arg->attr_valid_nsec = calc_timeout_nsec(e->attr_timeout);
306
convert_stat(&e->attr, &arg->attr);
301
arg->nodeid = e->ino;
302
arg->generation = e->generation;
303
arg->entry_valid = calc_timeout_sec(e->entry_timeout);
304
arg->entry_valid_nsec = calc_timeout_nsec(e->entry_timeout);
305
arg->attr_valid = calc_timeout_sec(e->attr_timeout);
306
arg->attr_valid_nsec = calc_timeout_nsec(e->attr_timeout);
307
convert_stat(&e->attr, &arg->attr);
309
310
static void fill_open(struct fuse_open_out *arg,
310
const struct fuse_file_info *f)
311
const struct fuse_file_info *f)
314
arg->open_flags |= FOPEN_DIRECT_IO;
316
arg->open_flags |= FOPEN_KEEP_CACHE;
315
arg->open_flags |= FOPEN_DIRECT_IO;
317
arg->open_flags |= FOPEN_KEEP_CACHE;
319
320
int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
321
struct fuse_entry_out arg;
323
/* before ABI 7.4 e->ino == 0 was invalid, only ENOENT meant
325
if (!e->ino && req->f->conn.proto_minor < 4)
326
return fuse_reply_err(req, ENOENT);
328
memset(&arg, 0, sizeof(arg));
330
return send_reply_ok(req, &arg, sizeof(arg));
322
struct fuse_entry_out arg;
324
/* before ABI 7.4 e->ino == 0 was invalid, only ENOENT meant
326
if (!e->ino && req->f->conn.proto_minor < 4)
327
return fuse_reply_err(req, ENOENT);
329
memset(&arg, 0, sizeof(arg));
331
return send_reply_ok(req, &arg, sizeof(arg));
333
334
int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e,
334
const struct fuse_file_info *f)
335
const struct fuse_file_info *f)
337
struct fuse_entry_out e;
338
struct fuse_open_out o;
338
struct fuse_entry_out e;
339
struct fuse_open_out o;
341
memset(&arg, 0, sizeof(arg));
342
fill_entry(&arg.e, e);
343
fill_open(&arg.o, f);
344
return send_reply_ok(req, &arg, sizeof(arg));
342
memset(&arg, 0, sizeof(arg));
343
fill_entry(&arg.e, e);
344
fill_open(&arg.o, f);
345
return send_reply_ok(req, &arg, sizeof(arg));
347
348
int fuse_reply_attr(fuse_req_t req, const struct stat *attr,
350
struct fuse_attr_out arg;
352
memset(&arg, 0, sizeof(arg));
353
arg.attr_valid = calc_timeout_sec(attr_timeout);
354
arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout);
355
convert_stat(attr, &arg.attr);
357
return send_reply_ok(req, &arg, sizeof(arg));
351
struct fuse_attr_out arg;
353
memset(&arg, 0, sizeof(arg));
354
arg.attr_valid = calc_timeout_sec(attr_timeout);
355
arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout);
356
convert_stat(attr, &arg.attr);
358
return send_reply_ok(req, &arg, sizeof(arg));
360
361
int fuse_reply_readlink(fuse_req_t req, const char *linkname)
362
return send_reply_ok(req, linkname, strlen(linkname));
363
return send_reply_ok(req, linkname, strlen(linkname));
365
366
int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *f)
367
struct fuse_open_out arg;
368
struct fuse_open_out arg;
369
memset(&arg, 0, sizeof(arg));
371
return send_reply_ok(req, &arg, sizeof(arg));
370
memset(&arg, 0, sizeof(arg));
372
return send_reply_ok(req, &arg, sizeof(arg));
374
375
int fuse_reply_write(fuse_req_t req, size_t count)
376
struct fuse_write_out arg;
378
memset(&arg, 0, sizeof(arg));
381
return send_reply_ok(req, &arg, sizeof(arg));
377
struct fuse_write_out arg;
379
memset(&arg, 0, sizeof(arg));
382
return send_reply_ok(req, &arg, sizeof(arg));
384
385
int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
386
return send_reply_ok(req, buf, size);
387
return send_reply_ok(req, buf, size);
389
390
int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf)
391
struct fuse_statfs_out arg;
392
size_t size = req->f->conn.proto_minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(arg);
394
memset(&arg, 0, sizeof(arg));
395
convert_statfs(stbuf, &arg.st);
397
return send_reply_ok(req, &arg, size);
392
struct fuse_statfs_out arg;
393
size_t size = req->f->conn.proto_minor < 4 ?
394
FUSE_COMPAT_STATFS_SIZE : sizeof(arg);
396
memset(&arg, 0, sizeof(arg));
397
convert_statfs(stbuf, &arg.st);
399
return send_reply_ok(req, &arg, size);
400
402
int fuse_reply_xattr(fuse_req_t req, size_t count)
402
struct fuse_getxattr_out arg;
404
memset(&arg, 0, sizeof(arg));
407
return send_reply_ok(req, &arg, sizeof(arg));
404
struct fuse_getxattr_out arg;
406
memset(&arg, 0, sizeof(arg));
409
return send_reply_ok(req, &arg, sizeof(arg));
410
412
int fuse_reply_lock(fuse_req_t req, struct flock *lock)
412
struct fuse_lk_out arg;
414
struct fuse_lk_out arg;
414
memset(&arg, 0, sizeof(arg));
415
arg.lk.type = lock->l_type;
416
if (lock->l_type != F_UNLCK) {
417
arg.lk.start = lock->l_start;
418
if (lock->l_len == 0)
419
arg.lk.end = OFFSET_MAX;
421
arg.lk.end = lock->l_start + lock->l_len - 1;
423
arg.lk.pid = lock->l_pid;
424
return send_reply_ok(req, &arg, sizeof(arg));
416
memset(&arg, 0, sizeof(arg));
417
arg.lk.type = lock->l_type;
418
if (lock->l_type != F_UNLCK) {
419
arg.lk.start = lock->l_start;
420
if (lock->l_len == 0)
421
arg.lk.end = OFFSET_MAX;
423
arg.lk.end = lock->l_start + lock->l_len - 1;
425
arg.lk.pid = lock->l_pid;
426
return send_reply_ok(req, &arg, sizeof(arg));
427
429
int fuse_reply_bmap(fuse_req_t req, uint64_t idx)
429
struct fuse_bmap_out arg;
431
memset(&arg, 0, sizeof(arg));
434
return send_reply_ok(req, &arg, sizeof(arg));
431
struct fuse_bmap_out arg;
433
memset(&arg, 0, sizeof(arg));
436
return send_reply_ok(req, &arg, sizeof(arg));
437
439
static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
439
char *name = (char *) inarg;
441
char *name = (char *) inarg;
441
if (req->f->op.lookup)
442
req->f->op.lookup(req, nodeid, name);
444
fuse_reply_err(req, ENOSYS);
443
if (req->f->op.lookup)
444
req->f->op.lookup(req, nodeid, name);
446
fuse_reply_err(req, ENOSYS);
447
449
static void do_forget(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
449
struct fuse_forget_in *arg = (struct fuse_forget_in *) inarg;
451
struct fuse_forget_in *arg = (struct fuse_forget_in *) inarg;
451
if (req->f->op.forget)
452
req->f->op.forget(req, nodeid, arg->nlookup);
454
fuse_reply_none(req);
453
if (req->f->op.forget)
454
req->f->op.forget(req, nodeid, arg->nlookup);
456
fuse_reply_none(req);
457
459
static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
461
if (req->f->op.getattr)
462
req->f->op.getattr(req, nodeid, NULL);
464
fuse_reply_err(req, ENOSYS);
463
if (req->f->op.getattr)
464
req->f->op.getattr(req, nodeid, NULL);
466
fuse_reply_err(req, ENOSYS);
467
469
static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
469
struct fuse_setattr_in *arg = (struct fuse_setattr_in *) inarg;
471
struct fuse_setattr_in *arg = (struct fuse_setattr_in *) inarg;
471
if (req->f->op.setattr) {
472
struct fuse_file_info *fi = NULL;
473
struct fuse_file_info fi_store;
475
memset(&stbuf, 0, sizeof(stbuf));
476
convert_attr(arg, &stbuf);
477
if (arg->valid & FATTR_FH) {
478
arg->valid &= ~FATTR_FH;
479
memset(&fi_store, 0, sizeof(fi_store));
484
req->f->op.setattr(req, nodeid, &stbuf, arg->valid, fi);
486
fuse_reply_err(req, ENOSYS);
473
if (req->f->op.setattr) {
474
struct fuse_file_info *fi = NULL;
475
struct fuse_file_info fi_store;
477
memset(&stbuf, 0, sizeof(stbuf));
478
convert_attr(arg, &stbuf);
479
if (arg->valid & FATTR_FH) {
480
arg->valid &= ~FATTR_FH;
481
memset(&fi_store, 0, sizeof(fi_store));
486
req->f->op.setattr(req, nodeid, &stbuf, arg->valid, fi);
488
fuse_reply_err(req, ENOSYS);
489
491
static void do_access(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
491
struct fuse_access_in *arg = (struct fuse_access_in *) inarg;
493
struct fuse_access_in *arg = (struct fuse_access_in *) inarg;
493
if (req->f->op.access)
494
req->f->op.access(req, nodeid, arg->mask);
496
fuse_reply_err(req, ENOSYS);
495
if (req->f->op.access)
496
req->f->op.access(req, nodeid, arg->mask);
498
fuse_reply_err(req, ENOSYS);
499
501
static void do_readlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
503
if (req->f->op.readlink)
504
req->f->op.readlink(req, nodeid);
506
fuse_reply_err(req, ENOSYS);
505
if (req->f->op.readlink)
506
req->f->op.readlink(req, nodeid);
508
fuse_reply_err(req, ENOSYS);
509
511
static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
511
struct fuse_mknod_in *arg = (struct fuse_mknod_in *) inarg;
513
struct fuse_mknod_in *arg = (struct fuse_mknod_in *) inarg;
513
if (req->f->op.mknod)
514
req->f->op.mknod(req, nodeid, PARAM(arg), arg->mode, arg->rdev);
516
fuse_reply_err(req, ENOSYS);
515
if (req->f->op.mknod)
516
req->f->op.mknod(req, nodeid, PARAM(arg), arg->mode, arg->rdev);
518
fuse_reply_err(req, ENOSYS);
519
521
static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
521
struct fuse_mkdir_in *arg = (struct fuse_mkdir_in *) inarg;
523
struct fuse_mkdir_in *arg = (struct fuse_mkdir_in *) inarg;
523
if (req->f->op.mkdir)
524
req->f->op.mkdir(req, nodeid, PARAM(arg), arg->mode);
526
fuse_reply_err(req, ENOSYS);
525
if (req->f->op.mkdir)
526
req->f->op.mkdir(req, nodeid, PARAM(arg), arg->mode);
528
fuse_reply_err(req, ENOSYS);
529
531
static void do_unlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
531
char *name = (char *) inarg;
533
char *name = (char *) inarg;
533
if (req->f->op.unlink)
534
req->f->op.unlink(req, nodeid, name);
536
fuse_reply_err(req, ENOSYS);
535
if (req->f->op.unlink)
536
req->f->op.unlink(req, nodeid, name);
538
fuse_reply_err(req, ENOSYS);
539
541
static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
541
char *name = (char *) inarg;
543
char *name = (char *) inarg;
543
if (req->f->op.rmdir)
544
req->f->op.rmdir(req, nodeid, name);
546
fuse_reply_err(req, ENOSYS);
545
if (req->f->op.rmdir)
546
req->f->op.rmdir(req, nodeid, name);
548
fuse_reply_err(req, ENOSYS);
549
551
static void do_symlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
551
char *name = (char *) inarg;
552
char *linkname = ((char *) inarg) + strlen((char *) inarg) + 1;
553
char *name = (char *) inarg;
554
char *linkname = ((char *) inarg) + strlen((char *) inarg) + 1;
554
if (req->f->op.symlink)
555
req->f->op.symlink(req, linkname, nodeid, name);
557
fuse_reply_err(req, ENOSYS);
556
if (req->f->op.symlink)
557
req->f->op.symlink(req, linkname, nodeid, name);
559
fuse_reply_err(req, ENOSYS);
560
562
static void do_rename(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
562
struct fuse_rename_in *arg = (struct fuse_rename_in *) inarg;
563
char *oldname = PARAM(arg);
564
char *newname = oldname + strlen(oldname) + 1;
564
struct fuse_rename_in *arg = (struct fuse_rename_in *) inarg;
565
char *oldname = PARAM(arg);
566
char *newname = oldname + strlen(oldname) + 1;
566
if (req->f->op.rename)
567
req->f->op.rename(req, nodeid, oldname, arg->newdir, newname);
569
fuse_reply_err(req, ENOSYS);
568
if (req->f->op.rename)
569
req->f->op.rename(req, nodeid, oldname, arg->newdir, newname);
571
fuse_reply_err(req, ENOSYS);
572
574
static void do_link(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
574
struct fuse_link_in *arg = (struct fuse_link_in *) inarg;
576
struct fuse_link_in *arg = (struct fuse_link_in *) inarg;
577
req->f->op.link(req, arg->oldnodeid, nodeid, PARAM(arg));
579
fuse_reply_err(req, ENOSYS);
579
req->f->op.link(req, arg->oldnodeid, nodeid, PARAM(arg));
581
fuse_reply_err(req, ENOSYS);
582
584
static void do_create(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
584
struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
586
if (req->f->op.create) {
587
struct fuse_file_info fi;
589
memset(&fi, 0, sizeof(fi));
590
fi.flags = arg->flags;
592
req->f->op.create(req, nodeid, PARAM(arg), arg->mode, &fi);
594
fuse_reply_err(req, ENOSYS);
586
struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
588
if (req->f->op.create) {
589
struct fuse_file_info fi;
591
memset(&fi, 0, sizeof(fi));
592
fi.flags = arg->flags;
594
req->f->op.create(req, nodeid, PARAM(arg), arg->mode, &fi);
596
fuse_reply_err(req, ENOSYS);
597
599
static void do_open(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
599
struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
600
struct fuse_file_info fi;
602
memset(&fi, 0, sizeof(fi));
603
fi.flags = arg->flags;
606
req->f->op.open(req, nodeid, &fi);
608
fuse_reply_open(req, &fi);
601
struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
602
struct fuse_file_info fi;
604
memset(&fi, 0, sizeof(fi));
605
fi.flags = arg->flags;
608
req->f->op.open(req, nodeid, &fi);
610
fuse_reply_open(req, &fi);
611
613
static void do_read(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
613
struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
615
if (req->f->op.read) {
616
struct fuse_file_info fi;
618
memset(&fi, 0, sizeof(fi));
621
req->f->op.read(req, nodeid, arg->size, arg->offset, &fi);
623
fuse_reply_err(req, ENOSYS);
615
struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
617
if (req->f->op.read) {
618
struct fuse_file_info fi;
620
memset(&fi, 0, sizeof(fi));
623
req->f->op.read(req, nodeid, arg->size, arg->offset, &fi);
625
fuse_reply_err(req, ENOSYS);
626
628
static void do_write(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
628
struct fuse_write_in *arg = (struct fuse_write_in *) inarg;
629
struct fuse_file_info fi;
631
memset(&fi, 0, sizeof(fi));
634
fi.writepage = arg->write_flags & 1;
636
if (req->f->op.write)
637
req->f->op.write(req, nodeid, PARAM(arg), arg->size, arg->offset, &fi);
639
fuse_reply_err(req, ENOSYS);
630
struct fuse_write_in *arg = (struct fuse_write_in *) inarg;
631
struct fuse_file_info fi;
633
memset(&fi, 0, sizeof(fi));
636
fi.writepage = arg->write_flags & 1;
638
if (req->f->op.write)
639
req->f->op.write(req, nodeid, PARAM(arg), arg->size,
642
fuse_reply_err(req, ENOSYS);
642
645
static void do_flush(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
644
struct fuse_flush_in *arg = (struct fuse_flush_in *) inarg;
645
struct fuse_file_info fi;
647
memset(&fi, 0, sizeof(fi));
651
if (req->f->conn.proto_minor >= 7)
652
fi.lock_owner = arg->lock_owner;
654
if (req->f->op.flush)
655
req->f->op.flush(req, nodeid, &fi);
657
fuse_reply_err(req, ENOSYS);
647
struct fuse_flush_in *arg = (struct fuse_flush_in *) inarg;
648
struct fuse_file_info fi;
650
memset(&fi, 0, sizeof(fi));
654
if (req->f->conn.proto_minor >= 7)
655
fi.lock_owner = arg->lock_owner;
657
if (req->f->op.flush)
658
req->f->op.flush(req, nodeid, &fi);
660
fuse_reply_err(req, ENOSYS);
660
663
static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
662
struct fuse_release_in *arg = (struct fuse_release_in *) inarg;
663
struct fuse_file_info fi;
665
memset(&fi, 0, sizeof(fi));
666
fi.flags = arg->flags;
669
if (req->f->conn.proto_minor >= 8) {
670
fi.flush = (arg->release_flags & FUSE_RELEASE_FLUSH) ? 1 : 0;
671
fi.lock_owner = arg->lock_owner;
674
if (req->f->op.release)
675
req->f->op.release(req, nodeid, &fi);
677
fuse_reply_err(req, 0);
665
struct fuse_release_in *arg = (struct fuse_release_in *) inarg;
666
struct fuse_file_info fi;
668
memset(&fi, 0, sizeof(fi));
669
fi.flags = arg->flags;
672
if (req->f->conn.proto_minor >= 8) {
673
fi.flush = (arg->release_flags & FUSE_RELEASE_FLUSH) ? 1 : 0;
674
fi.lock_owner = arg->lock_owner;
677
if (req->f->op.release)
678
req->f->op.release(req, nodeid, &fi);
680
fuse_reply_err(req, 0);
680
683
static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
682
struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg;
683
struct fuse_file_info fi;
685
memset(&fi, 0, sizeof(fi));
689
if (req->f->op.fsync)
690
req->f->op.fsync(req, nodeid, arg->fsync_flags & 1, &fi);
692
fuse_reply_err(req, ENOSYS);
685
struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg;
686
struct fuse_file_info fi;
688
memset(&fi, 0, sizeof(fi));
692
if (req->f->op.fsync)
693
req->f->op.fsync(req, nodeid, arg->fsync_flags & 1, &fi);
695
fuse_reply_err(req, ENOSYS);
695
698
static void do_opendir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
697
struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
698
struct fuse_file_info fi;
700
memset(&fi, 0, sizeof(fi));
701
fi.flags = arg->flags;
703
if (req->f->op.opendir)
704
req->f->op.opendir(req, nodeid, &fi);
706
fuse_reply_open(req, &fi);
700
struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
701
struct fuse_file_info fi;
703
memset(&fi, 0, sizeof(fi));
704
fi.flags = arg->flags;
706
if (req->f->op.opendir)
707
req->f->op.opendir(req, nodeid, &fi);
709
fuse_reply_open(req, &fi);
709
712
static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
711
struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
712
struct fuse_file_info fi;
714
memset(&fi, 0, sizeof(fi));
718
if (req->f->op.readdir)
719
req->f->op.readdir(req, nodeid, arg->size, arg->offset, &fi);
721
fuse_reply_err(req, ENOSYS);
714
struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
715
struct fuse_file_info fi;
717
memset(&fi, 0, sizeof(fi));
721
if (req->f->op.readdir)
722
req->f->op.readdir(req, nodeid, arg->size, arg->offset, &fi);
724
fuse_reply_err(req, ENOSYS);
724
727
static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
726
struct fuse_release_in *arg = (struct fuse_release_in *) inarg;
727
struct fuse_file_info fi;
729
memset(&fi, 0, sizeof(fi));
730
fi.flags = arg->flags;
734
if (req->f->op.releasedir)
735
req->f->op.releasedir(req, nodeid, &fi);
737
fuse_reply_err(req, 0);
729
struct fuse_release_in *arg = (struct fuse_release_in *) inarg;
730
struct fuse_file_info fi;
732
memset(&fi, 0, sizeof(fi));
733
fi.flags = arg->flags;
737
if (req->f->op.releasedir)
738
req->f->op.releasedir(req, nodeid, &fi);
740
fuse_reply_err(req, 0);
740
743
static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
742
struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg;
743
struct fuse_file_info fi;
745
memset(&fi, 0, sizeof(fi));
749
if (req->f->op.fsyncdir)
750
req->f->op.fsyncdir(req, nodeid, arg->fsync_flags & 1, &fi);
752
fuse_reply_err(req, ENOSYS);
745
struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg;
746
struct fuse_file_info fi;
748
memset(&fi, 0, sizeof(fi));
752
if (req->f->op.fsyncdir)
753
req->f->op.fsyncdir(req, nodeid, arg->fsync_flags & 1, &fi);
755
fuse_reply_err(req, ENOSYS);
755
758
static void do_statfs(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
760
if (req->f->op.statfs)
761
req->f->op.statfs(req, nodeid);
763
struct statvfs buf = {
767
fuse_reply_statfs(req, &buf);
763
if (req->f->op.statfs)
764
req->f->op.statfs(req, nodeid);
766
struct statvfs buf = {
770
fuse_reply_statfs(req, &buf);
771
774
static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
773
struct fuse_setxattr_in *arg = (struct fuse_setxattr_in *) inarg;
774
char *name = PARAM(arg);
775
char *value = name + strlen(name) + 1;
776
struct fuse_setxattr_in *arg = (struct fuse_setxattr_in *) inarg;
777
char *name = PARAM(arg);
778
char *value = name + strlen(name) + 1;
777
if (req->f->op.setxattr)
778
req->f->op.setxattr(req, nodeid, name, value, arg->size, arg->flags);
780
fuse_reply_err(req, ENOSYS);
780
if (req->f->op.setxattr)
781
req->f->op.setxattr(req, nodeid, name, value, arg->size,
784
fuse_reply_err(req, ENOSYS);
783
787
static void do_getxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
785
struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg;
789
struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg;
787
if (req->f->op.getxattr)
788
req->f->op.getxattr(req, nodeid, PARAM(arg), arg->size);
790
fuse_reply_err(req, ENOSYS);
791
if (req->f->op.getxattr)
792
req->f->op.getxattr(req, nodeid, PARAM(arg), arg->size);
794
fuse_reply_err(req, ENOSYS);
793
797
static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
795
struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg;
799
struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg;
797
if (req->f->op.listxattr)
798
req->f->op.listxattr(req, nodeid, arg->size);
800
fuse_reply_err(req, ENOSYS);
801
if (req->f->op.listxattr)
802
req->f->op.listxattr(req, nodeid, arg->size);
804
fuse_reply_err(req, ENOSYS);
803
807
static void do_removexattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
805
char *name = (char *) inarg;
809
char *name = (char *) inarg;
807
if (req->f->op.removexattr)
808
req->f->op.removexattr(req, nodeid, name);
810
fuse_reply_err(req, ENOSYS);
811
if (req->f->op.removexattr)
812
req->f->op.removexattr(req, nodeid, name);
814
fuse_reply_err(req, ENOSYS);
813
817
static void convert_fuse_file_lock(struct fuse_file_lock *fl,
816
memset(flock, 0, sizeof(struct flock));
817
flock->l_type = fl->type;
818
flock->l_whence = SEEK_SET;
819
flock->l_start = fl->start;
820
if (fl->end == OFFSET_MAX)
823
flock->l_len = fl->end - fl->start + 1;
824
flock->l_pid = fl->pid;
820
memset(flock, 0, sizeof(struct flock));
821
flock->l_type = fl->type;
822
flock->l_whence = SEEK_SET;
823
flock->l_start = fl->start;
824
if (fl->end == OFFSET_MAX)
827
flock->l_len = fl->end - fl->start + 1;
828
flock->l_pid = fl->pid;
827
831
static void do_getlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
829
struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg;
830
struct fuse_file_info fi;
833
memset(&fi, 0, sizeof(fi));
835
fi.lock_owner = arg->owner;
837
convert_fuse_file_lock(&arg->lk, &flock);
838
if (req->f->op.getlk)
839
req->f->op.getlk(req, nodeid, &fi, &flock);
841
fuse_reply_err(req, ENOSYS);
833
struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg;
834
struct fuse_file_info fi;
837
memset(&fi, 0, sizeof(fi));
839
fi.lock_owner = arg->owner;
841
convert_fuse_file_lock(&arg->lk, &flock);
842
if (req->f->op.getlk)
843
req->f->op.getlk(req, nodeid, &fi, &flock);
845
fuse_reply_err(req, ENOSYS);
844
848
static void do_setlk_common(fuse_req_t req, fuse_ino_t nodeid,
845
const void *inarg, int sleep)
849
const void *inarg, int sleep)
847
struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg;
848
struct fuse_file_info fi;
851
memset(&fi, 0, sizeof(fi));
853
fi.lock_owner = arg->owner;
855
convert_fuse_file_lock(&arg->lk, &flock);
856
if (req->f->op.setlk)
857
req->f->op.setlk(req, nodeid, &fi, &flock, sleep);
859
fuse_reply_err(req, ENOSYS);
851
struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg;
852
struct fuse_file_info fi;
855
memset(&fi, 0, sizeof(fi));
857
fi.lock_owner = arg->owner;
859
convert_fuse_file_lock(&arg->lk, &flock);
860
if (req->f->op.setlk)
861
req->f->op.setlk(req, nodeid, &fi, &flock, sleep);
863
fuse_reply_err(req, ENOSYS);
862
866
static void do_setlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
864
do_setlk_common(req, nodeid, inarg, 0);
868
do_setlk_common(req, nodeid, inarg, 0);
867
871
static void do_setlkw(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
869
do_setlk_common(req, nodeid, inarg, 1);
873
do_setlk_common(req, nodeid, inarg, 1);
872
876
static int find_interrupted(struct fuse_ll *f, struct fuse_req *req)
874
struct fuse_req *curr;
876
for (curr = f->list.next; curr != &f->list; curr = curr->next) {
877
if (curr->unique == req->u.i.unique) {
879
pthread_mutex_unlock(&f->lock);
881
/* Ugh, ugly locking */
882
pthread_mutex_lock(&curr->lock);
883
pthread_mutex_lock(&f->lock);
884
curr->interrupted = 1;
885
pthread_mutex_unlock(&f->lock);
887
curr->u.ni.func(curr, curr->u.ni.data);
888
pthread_mutex_unlock(&curr->lock);
890
pthread_mutex_lock(&f->lock);
898
for (curr = f->interrupts.next; curr != &f->interrupts;
900
if (curr->u.i.unique == req->u.i.unique)
878
struct fuse_req *curr;
880
for (curr = f->list.next; curr != &f->list; curr = curr->next) {
881
if (curr->unique == req->u.i.unique) {
883
pthread_mutex_unlock(&f->lock);
885
/* Ugh, ugly locking */
886
pthread_mutex_lock(&curr->lock);
887
pthread_mutex_lock(&f->lock);
888
curr->interrupted = 1;
889
pthread_mutex_unlock(&f->lock);
891
curr->u.ni.func(curr, curr->u.ni.data);
892
pthread_mutex_unlock(&curr->lock);
894
pthread_mutex_lock(&f->lock);
902
for (curr = f->interrupts.next; curr != &f->interrupts;
904
if (curr->u.i.unique == req->u.i.unique)
906
910
static void do_interrupt(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
908
struct fuse_interrupt_in *arg = (struct fuse_interrupt_in *) inarg;
909
struct fuse_ll *f = req->f;
913
fprintf(stderr, "INTERRUPT: %llu\n", (unsigned long long) arg->unique);
915
req->u.i.unique = arg->unique;
917
pthread_mutex_lock(&f->lock);
918
if (find_interrupted(f, req))
921
list_add_req(req, &f->interrupts);
922
pthread_mutex_unlock(&f->lock);
912
struct fuse_interrupt_in *arg = (struct fuse_interrupt_in *) inarg;
913
struct fuse_ll *f = req->f;
917
fprintf(stderr, "INTERRUPT: %llu\n",
918
(unsigned long long) arg->unique);
920
req->u.i.unique = arg->unique;
922
pthread_mutex_lock(&f->lock);
923
if (find_interrupted(f, req))
926
list_add_req(req, &f->interrupts);
927
pthread_mutex_unlock(&f->lock);
925
930
static struct fuse_req *check_interrupt(struct fuse_ll *f, struct fuse_req *req)
927
struct fuse_req *curr;
932
struct fuse_req *curr;
929
for (curr = f->interrupts.next; curr != &f->interrupts; curr = curr->next) {
930
if (curr->u.i.unique == req->unique) {
931
req->interrupted = 1;
937
curr = f->interrupts.next;
938
if (curr != &f->interrupts) {
934
for (curr = f->interrupts.next; curr != &f->interrupts;
936
if (curr->u.i.unique == req->unique) {
937
req->interrupted = 1;
943
curr = f->interrupts.next;
944
if (curr != &f->interrupts) {
946
952
static void do_bmap(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
948
struct fuse_bmap_in *arg = (struct fuse_bmap_in *) inarg;
954
struct fuse_bmap_in *arg = (struct fuse_bmap_in *) inarg;
951
req->f->op.bmap(req, nodeid, arg->blocksize, arg->block);
953
fuse_reply_err(req, ENOSYS);
957
req->f->op.bmap(req, nodeid, arg->blocksize, arg->block);
959
fuse_reply_err(req, ENOSYS);
956
962
static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
958
struct fuse_init_in *arg = (struct fuse_init_in *) inarg;
959
struct fuse_init_out outarg;
960
struct fuse_ll *f = req->f;
961
size_t bufsize = fuse_chan_bufsize(req->ch);
965
fprintf(stderr, "INIT: %u.%u\n", arg->major, arg->minor);
966
if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
967
fprintf(stderr, "flags=0x%08x\n", arg->flags);
968
fprintf(stderr, "max_readahead=0x%08x\n", arg->max_readahead);
971
f->conn.proto_major = arg->major;
972
f->conn.proto_minor = arg->minor;
974
if (arg->major < 7) {
975
fprintf(stderr, "fuse: unsupported protocol version: %u.%u\n",
976
arg->major, arg->minor);
977
fuse_reply_err(req, EPROTO);
981
if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
982
if (f->conn.async_read)
983
f->conn.async_read = arg->flags & FUSE_ASYNC_READ;
984
if (arg->max_readahead < f->conn.max_readahead)
985
f->conn.max_readahead = arg->max_readahead;
987
f->conn.async_read = 0;
988
f->conn.max_readahead = 0;
991
if (bufsize < FUSE_MIN_READ_BUFFER) {
992
fprintf(stderr, "fuse: warning: buffer size too small: %zu\n",
994
bufsize = FUSE_MIN_READ_BUFFER;
998
if (bufsize < f->conn.max_write)
999
f->conn.max_write = bufsize;
1003
f->op.init(f->userdata, &f->conn);
1005
memset(&outarg, 0, sizeof(outarg));
1006
outarg.major = FUSE_KERNEL_VERSION;
1007
outarg.minor = FUSE_KERNEL_MINOR_VERSION;
1008
if (f->conn.async_read)
1009
outarg.flags |= FUSE_ASYNC_READ;
1010
if (f->op.getlk && f->op.setlk)
1011
outarg.flags |= FUSE_POSIX_LOCKS;
1012
outarg.max_readahead = f->conn.max_readahead;
1013
outarg.max_write = f->conn.max_write;
1016
fprintf(stderr, " INIT: %u.%u\n", outarg.major, outarg.minor);
1017
fprintf(stderr, " flags=0x%08x\n", outarg.flags);
1018
fprintf(stderr, " max_readahead=0x%08x\n", outarg.max_readahead);
1019
fprintf(stderr, " max_write=0x%08x\n", outarg.max_write);
1022
send_reply_ok(req, &outarg, arg->minor < 5 ? 8 : sizeof(outarg));
964
struct fuse_init_in *arg = (struct fuse_init_in *) inarg;
965
struct fuse_init_out outarg;
966
struct fuse_ll *f = req->f;
967
size_t bufsize = fuse_chan_bufsize(req->ch);
971
fprintf(stderr, "INIT: %u.%u\n", arg->major, arg->minor);
972
if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
973
fprintf(stderr, "flags=0x%08x\n", arg->flags);
974
fprintf(stderr, "max_readahead=0x%08x\n",
978
f->conn.proto_major = arg->major;
979
f->conn.proto_minor = arg->minor;
981
if (arg->major < 7) {
982
fprintf(stderr, "fuse: unsupported protocol version: %u.%u\n",
983
arg->major, arg->minor);
984
fuse_reply_err(req, EPROTO);
988
if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
989
if (f->conn.async_read)
990
f->conn.async_read = arg->flags & FUSE_ASYNC_READ;
991
if (arg->max_readahead < f->conn.max_readahead)
992
f->conn.max_readahead = arg->max_readahead;
994
f->conn.async_read = 0;
995
f->conn.max_readahead = 0;
998
if (bufsize < FUSE_MIN_READ_BUFFER) {
999
fprintf(stderr, "fuse: warning: buffer size too small: %zu\n",
1001
bufsize = FUSE_MIN_READ_BUFFER;
1005
if (bufsize < f->conn.max_write)
1006
f->conn.max_write = bufsize;
1010
f->op.init(f->userdata, &f->conn);
1012
memset(&outarg, 0, sizeof(outarg));
1013
outarg.major = FUSE_KERNEL_VERSION;
1014
outarg.minor = FUSE_KERNEL_MINOR_VERSION;
1015
if (f->conn.async_read)
1016
outarg.flags |= FUSE_ASYNC_READ;
1017
if (f->op.getlk && f->op.setlk)
1018
outarg.flags |= FUSE_POSIX_LOCKS;
1019
outarg.max_readahead = f->conn.max_readahead;
1020
outarg.max_write = f->conn.max_write;
1023
fprintf(stderr, " INIT: %u.%u\n", outarg.major, outarg.minor);
1024
fprintf(stderr, " flags=0x%08x\n", outarg.flags);
1025
fprintf(stderr, " max_readahead=0x%08x\n",
1026
outarg.max_readahead);
1027
fprintf(stderr, " max_write=0x%08x\n", outarg.max_write);
1030
send_reply_ok(req, &outarg, arg->minor < 5 ? 8 : sizeof(outarg));
1025
1033
static void do_destroy(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1027
struct fuse_ll *f = req->f;
1034
f->op.destroy(f->userdata);
1036
send_reply_ok(req, NULL, 0);
1035
struct fuse_ll *f = req->f;
1042
f->op.destroy(f->userdata);
1044
send_reply_ok(req, NULL, 0);
1039
1047
void *fuse_req_userdata(fuse_req_t req)
1041
return req->f->userdata;
1049
return req->f->userdata;
1044
1052
const struct fuse_ctx *fuse_req_ctx(fuse_req_t req)
1049
1057
void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func,
1052
pthread_mutex_lock(&req->lock);
1053
req->u.ni.func = func;
1054
req->u.ni.data = data;
1055
if (req->interrupted && func)
1057
pthread_mutex_unlock(&req->lock);
1060
pthread_mutex_lock(&req->lock);
1061
req->u.ni.func = func;
1062
req->u.ni.data = data;
1063
if (req->interrupted && func)
1065
pthread_mutex_unlock(&req->lock);
1060
1068
int fuse_req_interrupted(fuse_req_t req)
1064
pthread_mutex_lock(&req->f->lock);
1065
interrupted = req->interrupted;
1066
pthread_mutex_unlock(&req->f->lock);
1072
pthread_mutex_lock(&req->f->lock);
1073
interrupted = req->interrupted;
1074
pthread_mutex_unlock(&req->f->lock);
1071
1079
static struct {
1072
void (*func)(fuse_req_t, fuse_ino_t, const void *);
1080
void (*func)(fuse_req_t, fuse_ino_t, const void *);
1074
1082
} fuse_ll_ops[] = {
1075
[FUSE_LOOKUP] = { do_lookup, "LOOKUP" },
1076
[FUSE_FORGET] = { do_forget, "FORGET" },
1077
[FUSE_GETATTR] = { do_getattr, "GETATTR" },
1078
[FUSE_SETATTR] = { do_setattr, "SETATTR" },
1079
[FUSE_READLINK] = { do_readlink, "READLINK" },
1080
[FUSE_SYMLINK] = { do_symlink, "SYMLINK" },
1081
[FUSE_MKNOD] = { do_mknod, "MKNOD" },
1082
[FUSE_MKDIR] = { do_mkdir, "MKDIR" },
1083
[FUSE_UNLINK] = { do_unlink, "UNLINK" },
1084
[FUSE_RMDIR] = { do_rmdir, "RMDIR" },
1085
[FUSE_RENAME] = { do_rename, "RENAME" },
1086
[FUSE_LINK] = { do_link, "LINK" },
1087
[FUSE_OPEN] = { do_open, "OPEN" },
1088
[FUSE_READ] = { do_read, "READ" },
1089
[FUSE_WRITE] = { do_write, "WRITE" },
1090
[FUSE_STATFS] = { do_statfs, "STATFS" },
1091
[FUSE_RELEASE] = { do_release, "RELEASE" },
1092
[FUSE_FSYNC] = { do_fsync, "FSYNC" },
1093
[FUSE_SETXATTR] = { do_setxattr, "SETXATTR" },
1094
[FUSE_GETXATTR] = { do_getxattr, "GETXATTR" },
1095
[FUSE_LISTXATTR] = { do_listxattr, "LISTXATTR" },
1096
[FUSE_REMOVEXATTR] = { do_removexattr, "REMOVEXATTR" },
1097
[FUSE_FLUSH] = { do_flush, "FLUSH" },
1098
[FUSE_INIT] = { do_init, "INIT" },
1099
[FUSE_OPENDIR] = { do_opendir, "OPENDIR" },
1100
[FUSE_READDIR] = { do_readdir, "READDIR" },
1101
[FUSE_RELEASEDIR] = { do_releasedir, "RELEASEDIR" },
1102
[FUSE_FSYNCDIR] = { do_fsyncdir, "FSYNCDIR" },
1103
[FUSE_GETLK] = { do_getlk, "GETLK" },
1104
[FUSE_SETLK] = { do_setlk, "SETLK" },
1105
[FUSE_SETLKW] = { do_setlkw, "SETLKW" },
1106
[FUSE_ACCESS] = { do_access, "ACCESS" },
1107
[FUSE_CREATE] = { do_create, "CREATE" },
1108
[FUSE_INTERRUPT] = { do_interrupt, "INTERRUPT" },
1109
[FUSE_BMAP] = { do_bmap, "BMAP" },
1110
[FUSE_DESTROY] = { do_destroy, "DESTROY" },
1083
[FUSE_LOOKUP] = { do_lookup, "LOOKUP" },
1084
[FUSE_FORGET] = { do_forget, "FORGET" },
1085
[FUSE_GETATTR] = { do_getattr, "GETATTR" },
1086
[FUSE_SETATTR] = { do_setattr, "SETATTR" },
1087
[FUSE_READLINK] = { do_readlink, "READLINK" },
1088
[FUSE_SYMLINK] = { do_symlink, "SYMLINK" },
1089
[FUSE_MKNOD] = { do_mknod, "MKNOD" },
1090
[FUSE_MKDIR] = { do_mkdir, "MKDIR" },
1091
[FUSE_UNLINK] = { do_unlink, "UNLINK" },
1092
[FUSE_RMDIR] = { do_rmdir, "RMDIR" },
1093
[FUSE_RENAME] = { do_rename, "RENAME" },
1094
[FUSE_LINK] = { do_link, "LINK" },
1095
[FUSE_OPEN] = { do_open, "OPEN" },
1096
[FUSE_READ] = { do_read, "READ" },
1097
[FUSE_WRITE] = { do_write, "WRITE" },
1098
[FUSE_STATFS] = { do_statfs, "STATFS" },
1099
[FUSE_RELEASE] = { do_release, "RELEASE" },
1100
[FUSE_FSYNC] = { do_fsync, "FSYNC" },
1101
[FUSE_SETXATTR] = { do_setxattr, "SETXATTR" },
1102
[FUSE_GETXATTR] = { do_getxattr, "GETXATTR" },
1103
[FUSE_LISTXATTR] = { do_listxattr, "LISTXATTR" },
1104
[FUSE_REMOVEXATTR] = { do_removexattr, "REMOVEXATTR" },
1105
[FUSE_FLUSH] = { do_flush, "FLUSH" },
1106
[FUSE_INIT] = { do_init, "INIT" },
1107
[FUSE_OPENDIR] = { do_opendir, "OPENDIR" },
1108
[FUSE_READDIR] = { do_readdir, "READDIR" },
1109
[FUSE_RELEASEDIR] = { do_releasedir, "RELEASEDIR" },
1110
[FUSE_FSYNCDIR] = { do_fsyncdir, "FSYNCDIR" },
1111
[FUSE_GETLK] = { do_getlk, "GETLK" },
1112
[FUSE_SETLK] = { do_setlk, "SETLK" },
1113
[FUSE_SETLKW] = { do_setlkw, "SETLKW" },
1114
[FUSE_ACCESS] = { do_access, "ACCESS" },
1115
[FUSE_CREATE] = { do_create, "CREATE" },
1116
[FUSE_INTERRUPT] = { do_interrupt, "INTERRUPT" },
1117
[FUSE_BMAP] = { do_bmap, "BMAP" },
1118
[FUSE_DESTROY] = { do_destroy, "DESTROY" },
1113
1121
#define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0]))
1115
1123
static const char *opname(enum fuse_opcode opcode)
1117
if (opcode >= FUSE_MAXOP || !fuse_ll_ops[opcode].name)
1120
return fuse_ll_ops[opcode].name;
1125
if (opcode >= FUSE_MAXOP || !fuse_ll_ops[opcode].name)
1128
return fuse_ll_ops[opcode].name;
1123
1131
static void fuse_ll_process(void *data, const char *buf, size_t len,
1124
struct fuse_chan *ch)
1132
struct fuse_chan *ch)
1126
struct fuse_ll *f = (struct fuse_ll *) data;
1127
struct fuse_in_header *in = (struct fuse_in_header *) buf;
1128
const void *inarg = buf + sizeof(struct fuse_in_header);
1129
struct fuse_req *req;
1132
fprintf(stderr, "unique: %llu, opcode: %s (%i), nodeid: %lu, insize: %zu\n",
1133
(unsigned long long) in->unique,
1134
opname((enum fuse_opcode) in->opcode), in->opcode,
1135
(unsigned long) in->nodeid, len);
1137
req = (struct fuse_req *) calloc(1, sizeof(struct fuse_req));
1139
fprintf(stderr, "fuse: failed to allocate request\n");
1144
req->unique = in->unique;
1145
req->ctx.uid = in->uid;
1146
req->ctx.gid = in->gid;
1147
req->ctx.pid = in->pid;
1151
fuse_mutex_init(&req->lock);
1153
if (!f->got_init && in->opcode != FUSE_INIT)
1154
fuse_reply_err(req, EIO);
1155
else if (f->allow_root && in->uid != f->owner && in->uid != 0 &&
1156
in->opcode != FUSE_INIT && in->opcode != FUSE_READ &&
1157
in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC &&
1158
in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR &&
1159
in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR) {
1160
fuse_reply_err(req, EACCES);
1161
} else if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func)
1162
fuse_reply_err(req, ENOSYS);
1164
if (in->opcode != FUSE_INTERRUPT) {
1165
struct fuse_req *intr;
1166
pthread_mutex_lock(&f->lock);
1167
intr = check_interrupt(f, req);
1168
list_add_req(req, &f->list);
1169
pthread_mutex_unlock(&f->lock);
1171
fuse_reply_err(intr, EAGAIN);
1173
fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);
1134
struct fuse_ll *f = (struct fuse_ll *) data;
1135
struct fuse_in_header *in = (struct fuse_in_header *) buf;
1136
const void *inarg = buf + sizeof(struct fuse_in_header);
1137
struct fuse_req *req;
1141
"unique: %llu, opcode: %s (%i), nodeid: %lu, insize: %zu\n",
1142
(unsigned long long) in->unique,
1143
opname((enum fuse_opcode) in->opcode), in->opcode,
1144
(unsigned long) in->nodeid, len);
1146
req = (struct fuse_req *) calloc(1, sizeof(struct fuse_req));
1148
fprintf(stderr, "fuse: failed to allocate request\n");
1153
req->unique = in->unique;
1154
req->ctx.uid = in->uid;
1155
req->ctx.gid = in->gid;
1156
req->ctx.pid = in->pid;
1160
fuse_mutex_init(&req->lock);
1162
if (!f->got_init && in->opcode != FUSE_INIT)
1163
fuse_reply_err(req, EIO);
1164
else if (f->allow_root && in->uid != f->owner && in->uid != 0 &&
1165
in->opcode != FUSE_INIT && in->opcode != FUSE_READ &&
1166
in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC &&
1167
in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR &&
1168
in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR) {
1169
fuse_reply_err(req, EACCES);
1170
} else if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func)
1171
fuse_reply_err(req, ENOSYS);
1173
if (in->opcode != FUSE_INTERRUPT) {
1174
struct fuse_req *intr;
1175
pthread_mutex_lock(&f->lock);
1176
intr = check_interrupt(f, req);
1177
list_add_req(req, &f->list);
1178
pthread_mutex_unlock(&f->lock);
1180
fuse_reply_err(intr, EAGAIN);
1182
fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);
1182
1191
static struct fuse_opt fuse_ll_opts[] = {
1183
{ "debug", offsetof(struct fuse_ll, debug), 1 },
1184
{ "-d", offsetof(struct fuse_ll, debug), 1 },
1185
{ "allow_root", offsetof(struct fuse_ll, allow_root), 1 },
1186
{ "max_write=%u", offsetof(struct fuse_ll, conn.max_write), 0 },
1187
{ "max_readahead=%u", offsetof(struct fuse_ll, conn.max_readahead), 0 },
1188
{ "async_read", offsetof(struct fuse_ll, conn.async_read), 1 },
1189
{ "sync_read", offsetof(struct fuse_ll, conn.async_read), 0 },
1190
FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD),
1191
FUSE_OPT_KEY("-h", KEY_HELP),
1192
FUSE_OPT_KEY("--help", KEY_HELP),
1193
FUSE_OPT_KEY("-V", KEY_VERSION),
1194
FUSE_OPT_KEY("--version", KEY_VERSION),
1192
{ "debug", offsetof(struct fuse_ll, debug), 1 },
1193
{ "-d", offsetof(struct fuse_ll, debug), 1 },
1194
{ "allow_root", offsetof(struct fuse_ll, allow_root), 1 },
1195
{ "max_write=%u", offsetof(struct fuse_ll, conn.max_write), 0 },
1196
{ "max_readahead=%u", offsetof(struct fuse_ll, conn.max_readahead), 0 },
1197
{ "async_read", offsetof(struct fuse_ll, conn.async_read), 1 },
1198
{ "sync_read", offsetof(struct fuse_ll, conn.async_read), 0 },
1199
FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD),
1200
FUSE_OPT_KEY("-h", KEY_HELP),
1201
FUSE_OPT_KEY("--help", KEY_HELP),
1202
FUSE_OPT_KEY("-V", KEY_VERSION),
1203
FUSE_OPT_KEY("--version", KEY_VERSION),
1198
1207
static void fuse_ll_version(void)
1200
fprintf(stderr, "using FUSE kernel interface version %i.%i\n",
1201
FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
1209
fprintf(stderr, "using FUSE kernel interface version %i.%i\n",
1210
FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
1204
1213
static void fuse_ll_help(void)
1207
" -o max_write=N set maximum size of write requests\n"
1208
" -o max_readahead=N set maximum readahead\n"
1209
" -o async_read perform reads asynchronously (default)\n"
1210
" -o sync_read perform reads synchronously\n");
1216
" -o max_write=N set maximum size of write requests\n"
1217
" -o max_readahead=N set maximum readahead\n"
1218
" -o async_read perform reads asynchronously (default)\n"
1219
" -o sync_read perform reads synchronously\n");
1213
1222
static int fuse_ll_opt_proc(void *data, const char *arg, int key,
1214
struct fuse_args *outargs)
1223
struct fuse_args *outargs)
1216
(void) data; (void) outargs;
1228
fprintf(stderr, "fuse: unknown option `%s'\n", arg);
1225
(void) data; (void) outargs;
1237
fprintf(stderr, "fuse: unknown option `%s'\n", arg);
1234
1243
int fuse_lowlevel_is_lib_option(const char *opt)
1236
return fuse_opt_match(fuse_ll_opts, opt);
1245
return fuse_opt_match(fuse_ll_opts, opt);
1239
1248
static void fuse_ll_destroy(void *data)
1241
struct fuse_ll *f = (struct fuse_ll *) data;
1243
if (f->got_init && !f->got_destroy) {
1245
f->op.destroy(f->userdata);
1248
pthread_mutex_destroy(&f->lock);
1250
struct fuse_ll *f = (struct fuse_ll *) data;
1252
if (f->got_init && !f->got_destroy) {
1254
f->op.destroy(f->userdata);
1257
pthread_mutex_destroy(&f->lock);