1 /* 2 FUSE: Filesystem in Userspace 3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> 4 5 This program can be distributed under the terms of the GNU LGPLv2. 6 See the file COPYING.LIB 7 */ 8 9 #define _GNU_SOURCE 10 11 #include "config.h" 12 #include "fuse_i.h" 13 #include "fuse_kernel.h" 14 #include "fuse_opt.h" 15 #include "fuse_misc.h" 16 #include "fuse_common_compat.h" 17 #include "fuse_lowlevel_compat.h" 18 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <stddef.h> 22 #include <string.h> 23 #include <unistd.h> 24 #include <limits.h> 25 #include <errno.h> 26 #include <assert.h> 27 #include <sys/file.h> 28 29 #ifndef F_LINUX_SPECIFIC_BASE 30 #define F_LINUX_SPECIFIC_BASE 1024 31 #endif 32 #ifndef F_SETPIPE_SZ 33 #define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7) 34 #endif 35 36 37 #define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg))) 38 #define OFFSET_MAX 0x7fffffffffffffffLL 39 40 #define container_of(ptr, type, member) ({ \ 41 const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 42 (type *)( (char *)__mptr - offsetof(type,member) );}) 43 44 struct fuse_pollhandle { 45 uint64_t kh; 46 struct fuse_chan *ch; 47 struct fuse_ll *f; 48 }; 49 50 static size_t pagesize; 51 52 static __attribute__((constructor)) void fuse_ll_init_pagesize(void) 53 { 54 pagesize = getpagesize(); 55 } 56 57 static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr) 58 { 59 attr->ino = stbuf->st_ino; 60 attr->mode = stbuf->st_mode; 61 attr->nlink = stbuf->st_nlink; 62 attr->uid = stbuf->st_uid; 63 attr->gid = stbuf->st_gid; 64 attr->rdev = stbuf->st_rdev; 65 attr->size = stbuf->st_size; 66 attr->blksize = stbuf->st_blksize; 67 attr->blocks = stbuf->st_blocks; 68 attr->atime = stbuf->st_atime; 69 attr->mtime = stbuf->st_mtime; 70 attr->ctime = stbuf->st_ctime; 71 attr->atimensec = ST_ATIM_NSEC(stbuf); 72 attr->mtimensec = ST_MTIM_NSEC(stbuf); 73 attr->ctimensec = ST_CTIM_NSEC(stbuf); 74 } 75 76 static void convert_attr(const struct fuse_setattr_in *attr, struct stat *stbuf) 77 { 78 stbuf->st_mode = attr->mode; 79 stbuf->st_uid = attr->uid; 80 stbuf->st_gid = attr->gid; 81 stbuf->st_size = attr->size; 82 stbuf->st_atime = attr->atime; 83 stbuf->st_mtime = attr->mtime; 84 ST_ATIM_NSEC_SET(stbuf, attr->atimensec); 85 ST_MTIM_NSEC_SET(stbuf, attr->mtimensec); 86 } 87 88 static size_t iov_length(const struct iovec *iov, size_t count) 89 { 90 size_t seg; 91 size_t ret = 0; 92 93 for (seg = 0; seg < count; seg++) 94 ret += iov[seg].iov_len; 95 return ret; 96 } 97 98 static void list_init_req(struct fuse_req *req) 99 { 100 req->next = req; 101 req->prev = req; 102 } 103 104 static void list_del_req(struct fuse_req *req) 105 { 106 struct fuse_req *prev = req->prev; 107 struct fuse_req *next = req->next; 108 prev->next = next; 109 next->prev = prev; 110 } 111 112 static void list_add_req(struct fuse_req *req, struct fuse_req *next) 113 { 114 struct fuse_req *prev = next->prev; 115 req->next = next; 116 req->prev = prev; 117 prev->next = req; 118 next->prev = req; 119 } 120 121 static void destroy_req(fuse_req_t req) 122 { 123 pthread_mutex_destroy(&req->lock); 124 free(req); 125 } 126 127 void fuse_free_req(fuse_req_t req) 128 { 129 int ctr; 130 struct fuse_ll *f = req->f; 131 132 pthread_mutex_lock(&f->lock); 133 req->u.ni.func = NULL; 134 req->u.ni.data = NULL; 135 list_del_req(req); 136 ctr = --req->ctr; 137 pthread_mutex_unlock(&f->lock); 138 if (!ctr) 139 destroy_req(req); 140 } 141 142 static struct fuse_req *fuse_ll_alloc_req(struct fuse_ll *f) 143 { 144 struct fuse_req *req; 145 146 req = (struct fuse_req *) calloc(1, sizeof(struct fuse_req)); 147 if (req == NULL) { 148 fprintf(stderr, "fuse: failed to allocate request\n"); 149 } else { 150 req->f = f; 151 req->ctr = 1; 152 list_init_req(req); 153 fuse_mutex_init(&req->lock); 154 } 155 156 return req; 157 } 158 159 160 static int fuse_send_msg(struct fuse_ll *f, struct fuse_chan *ch, 161 struct iovec *iov, int count) 162 { 163 struct fuse_out_header *out = iov[0].iov_base; 164 165 out->len = iov_length(iov, count); 166 if (f->debug) { 167 if (out->unique == 0) { 168 fprintf(stderr, "NOTIFY: code=%d length=%u\n", 169 out->error, out->len); 170 } else if (out->error) { 171 fprintf(stderr, 172 " unique: %llu, error: %i (%s), outsize: %i\n", 173 (unsigned long long) out->unique, out->error, 174 strerror(-out->error), out->len); 175 } else { 176 fprintf(stderr, 177 " unique: %llu, success, outsize: %i\n", 178 (unsigned long long) out->unique, out->len); 179 } 180 } 181 182 return fuse_chan_send(ch, iov, count); 183 } 184 185 int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov, 186 int count) 187 { 188 struct fuse_out_header out; 189 190 if (error <= -1000 || error > 0) { 191 fprintf(stderr, "fuse: bad error value: %i\n", error); 192 error = -ERANGE; 193 } 194 195 out.unique = req->unique; 196 out.error = error; 197 198 iov[0].iov_base = &out; 199 iov[0].iov_len = sizeof(struct fuse_out_header); 200 201 return fuse_send_msg(req->f, req->ch, iov, count); 202 } 203 204 static int send_reply_iov(fuse_req_t req, int error, struct iovec *iov, 205 int count) 206 { 207 int res; 208 209 res = fuse_send_reply_iov_nofree(req, error, iov, count); 210 fuse_free_req(req); 211 return res; 212 } 213 214 static int send_reply(fuse_req_t req, int error, const void *arg, 215 size_t argsize) 216 { 217 struct iovec iov[2]; 218 int count = 1; 219 if (argsize) { 220 iov[1].iov_base = (void *) arg; 221 iov[1].iov_len = argsize; 222 count++; 223 } 224 return send_reply_iov(req, error, iov, count); 225 } 226 227 int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count) 228 { 229 int res; 230 struct iovec *padded_iov; 231 232 padded_iov = malloc((count + 1) * sizeof(struct iovec)); 233 if (padded_iov == NULL) 234 return fuse_reply_err(req, ENOMEM); 235 236 memcpy(padded_iov + 1, iov, count * sizeof(struct iovec)); 237 count++; 238 239 res = send_reply_iov(req, 0, padded_iov, count); 240 free(padded_iov); 241 242 return res; 243 } 244 245 size_t fuse_dirent_size(size_t namelen) 246 { 247 return FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + namelen); 248 } 249 250 char *fuse_add_dirent(char *buf, const char *name, const struct stat *stbuf, 251 off_t off) 252 { 253 unsigned namelen = strlen(name); 254 unsigned entlen = FUSE_NAME_OFFSET + namelen; 255 unsigned entsize = fuse_dirent_size(namelen); 256 unsigned padlen = entsize - entlen; 257 struct fuse_dirent *dirent = (struct fuse_dirent *) buf; 258 259 dirent->ino = stbuf->st_ino; 260 dirent->off = off; 261 dirent->namelen = namelen; 262 dirent->type = (stbuf->st_mode & 0170000) >> 12; 263 strncpy(dirent->name, name, namelen); 264 if (padlen) 265 memset(buf + entlen, 0, padlen); 266 267 return buf + entsize; 268 } 269 270 size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize, 271 const char *name, const struct stat *stbuf, off_t off) 272 { 273 size_t entsize; 274 275 (void) req; 276 entsize = fuse_dirent_size(strlen(name)); 277 if (entsize <= bufsize && buf) 278 fuse_add_dirent(buf, name, stbuf, off); 279 return entsize; 280 } 281 282 static void convert_statfs(const struct statvfs *stbuf, 283 struct fuse_kstatfs *kstatfs) 284 { 285 kstatfs->bsize = stbuf->f_bsize; 286 kstatfs->frsize = stbuf->f_frsize; 287 kstatfs->blocks = stbuf->f_blocks; 288 kstatfs->bfree = stbuf->f_bfree; 289 kstatfs->bavail = stbuf->f_bavail; 290 kstatfs->files = stbuf->f_files; 291 kstatfs->ffree = stbuf->f_ffree; 292 kstatfs->namelen = stbuf->f_namemax; 293 } 294 295 static int send_reply_ok(fuse_req_t req, const void *arg, size_t argsize) 296 { 297 return send_reply(req, 0, arg, argsize); 298 } 299 300 int fuse_reply_err(fuse_req_t req, int err) 301 { 302 return send_reply(req, -err, NULL, 0); 303 } 304 305 void fuse_reply_none(fuse_req_t req) 306 { 307 if (req->ch) 308 fuse_chan_send(req->ch, NULL, 0); 309 fuse_free_req(req); 310 } 311 312 static unsigned long calc_timeout_sec(double t) 313 { 314 if (t > (double) ULONG_MAX) 315 return ULONG_MAX; 316 else if (t < 0.0) 317 return 0; 318 else 319 return (unsigned long) t; 320 } 321 322 static unsigned int calc_timeout_nsec(double t) 323 { 324 double f = t - (double) calc_timeout_sec(t); 325 if (f < 0.0) 326 return 0; 327 else if (f >= 0.999999999) 328 return 999999999; 329 else 330 return (unsigned int) (f * 1.0e9); 331 } 332 333 static void fill_entry(struct fuse_entry_out *arg, 334 const struct fuse_entry_param *e) 335 { 336 arg->nodeid = e->ino; 337 arg->generation = e->generation; 338 arg->entry_valid = calc_timeout_sec(e->entry_timeout); 339 arg->entry_valid_nsec = calc_timeout_nsec(e->entry_timeout); 340 arg->attr_valid = calc_timeout_sec(e->attr_timeout); 341 arg->attr_valid_nsec = calc_timeout_nsec(e->attr_timeout); 342 convert_stat(&e->attr, &arg->attr); 343 } 344 345 static void fill_open(struct fuse_open_out *arg, 346 const struct fuse_file_info *f) 347 { 348 arg->fh = f->fh; 349 if (f->direct_io) 350 arg->open_flags |= FOPEN_DIRECT_IO; 351 if (f->keep_cache) 352 arg->open_flags |= FOPEN_KEEP_CACHE; 353 if (f->nonseekable) 354 arg->open_flags |= FOPEN_NONSEEKABLE; 355 } 356 357 int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e) 358 { 359 struct fuse_entry_out arg; 360 size_t size = req->f->conn.proto_minor < 9 ? 361 FUSE_COMPAT_ENTRY_OUT_SIZE : sizeof(arg); 362 363 /* before ABI 7.4 e->ino == 0 was invalid, only ENOENT meant 364 negative entry */ 365 if (!e->ino && req->f->conn.proto_minor < 4) 366 return fuse_reply_err(req, ENOENT); 367 368 memset(&arg, 0, sizeof(arg)); 369 fill_entry(&arg, e); 370 return send_reply_ok(req, &arg, size); 371 } 372 373 int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e, 374 const struct fuse_file_info *f) 375 { 376 char buf[sizeof(struct fuse_entry_out) + sizeof(struct fuse_open_out)]; 377 size_t entrysize = req->f->conn.proto_minor < 9 ? 378 FUSE_COMPAT_ENTRY_OUT_SIZE : sizeof(struct fuse_entry_out); 379 struct fuse_entry_out *earg = (struct fuse_entry_out *) buf; 380 struct fuse_open_out *oarg = (struct fuse_open_out *) (buf + entrysize); 381 382 memset(buf, 0, sizeof(buf)); 383 fill_entry(earg, e); 384 fill_open(oarg, f); 385 return send_reply_ok(req, buf, 386 entrysize + sizeof(struct fuse_open_out)); 387 } 388 389 int fuse_reply_attr(fuse_req_t req, const struct stat *attr, 390 double attr_timeout) 391 { 392 struct fuse_attr_out arg; 393 size_t size = req->f->conn.proto_minor < 9 ? 394 FUSE_COMPAT_ATTR_OUT_SIZE : sizeof(arg); 395 396 memset(&arg, 0, sizeof(arg)); 397 arg.attr_valid = calc_timeout_sec(attr_timeout); 398 arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout); 399 convert_stat(attr, &arg.attr); 400 401 return send_reply_ok(req, &arg, size); 402 } 403 404 int fuse_reply_readlink(fuse_req_t req, const char *linkname) 405 { 406 return send_reply_ok(req, linkname, strlen(linkname)); 407 } 408 409 int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *f) 410 { 411 struct fuse_open_out arg; 412 413 memset(&arg, 0, sizeof(arg)); 414 fill_open(&arg, f); 415 return send_reply_ok(req, &arg, sizeof(arg)); 416 } 417 418 int fuse_reply_write(fuse_req_t req, size_t count) 419 { 420 struct fuse_write_out arg; 421 422 memset(&arg, 0, sizeof(arg)); 423 arg.size = count; 424 425 return send_reply_ok(req, &arg, sizeof(arg)); 426 } 427 428 int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size) 429 { 430 return send_reply_ok(req, buf, size); 431 } 432 433 static int fuse_send_data_iov_fallback(struct fuse_ll *f, struct fuse_chan *ch, 434 struct iovec *iov, int iov_count, 435 struct fuse_bufvec *buf, 436 size_t len) 437 { 438 struct fuse_bufvec mem_buf = FUSE_BUFVEC_INIT(len); 439 void *mbuf; 440 int res; 441 442 /* Optimize common case */ 443 if (buf->count == 1 && buf->idx == 0 && buf->off == 0 && 444 !(buf->buf[0].flags & FUSE_BUF_IS_FD)) { 445 /* FIXME: also avoid memory copy if there are multiple buffers 446 but none of them contain an fd */ 447 448 iov[iov_count].iov_base = buf->buf[0].mem; 449 iov[iov_count].iov_len = len; 450 iov_count++; 451 return fuse_send_msg(f, ch, iov, iov_count); 452 } 453 454 res = posix_memalign(&mbuf, pagesize, len); 455 if (res != 0) 456 return res; 457 458 mem_buf.buf[0].mem = mbuf; 459 res = fuse_buf_copy(&mem_buf, buf, 0); 460 if (res < 0) { 461 free(mbuf); 462 return -res; 463 } 464 len = res; 465 466 iov[iov_count].iov_base = mbuf; 467 iov[iov_count].iov_len = len; 468 iov_count++; 469 res = fuse_send_msg(f, ch, iov, iov_count); 470 free(mbuf); 471 472 return res; 473 } 474 475 struct fuse_ll_pipe { 476 size_t size; 477 int can_grow; 478 int pipe[2]; 479 }; 480 481 static void fuse_ll_pipe_free(struct fuse_ll_pipe *llp) 482 { 483 close(llp->pipe[0]); 484 close(llp->pipe[1]); 485 free(llp); 486 } 487 488 #ifdef HAVE_SPLICE 489 static struct fuse_ll_pipe *fuse_ll_get_pipe(struct fuse_ll *f) 490 { 491 struct fuse_ll_pipe *llp = pthread_getspecific(f->pipe_key); 492 if (llp == NULL) { 493 int res; 494 495 llp = malloc(sizeof(struct fuse_ll_pipe)); 496 if (llp == NULL) 497 return NULL; 498 499 res = pipe(llp->pipe); 500 if (res == -1) { 501 free(llp); 502 return NULL; 503 } 504 505 if (fcntl(llp->pipe[0], F_SETFL, O_NONBLOCK) == -1 || 506 fcntl(llp->pipe[1], F_SETFL, O_NONBLOCK) == -1) { 507 close(llp->pipe[0]); 508 close(llp->pipe[1]); 509 free(llp); 510 return NULL; 511 } 512 513 /* 514 *the default size is 16 pages on linux 515 */ 516 llp->size = pagesize * 16; 517 llp->can_grow = 1; 518 519 pthread_setspecific(f->pipe_key, llp); 520 } 521 522 return llp; 523 } 524 #endif 525 526 static void fuse_ll_clear_pipe(struct fuse_ll *f) 527 { 528 struct fuse_ll_pipe *llp = pthread_getspecific(f->pipe_key); 529 if (llp) { 530 pthread_setspecific(f->pipe_key, NULL); 531 fuse_ll_pipe_free(llp); 532 } 533 } 534 535 #if defined(HAVE_SPLICE) && defined(HAVE_VMSPLICE) 536 static int read_back(int fd, char *buf, size_t len) 537 { 538 int res; 539 540 res = read(fd, buf, len); 541 if (res == -1) { 542 fprintf(stderr, "fuse: internal error: failed to read back from pipe: %s\n", strerror(errno)); 543 return -EIO; 544 } 545 if (res != len) { 546 fprintf(stderr, "fuse: internal error: short read back from pipe: %i from %zi\n", res, len); 547 return -EIO; 548 } 549 return 0; 550 } 551 552 static int fuse_send_data_iov(struct fuse_ll *f, struct fuse_chan *ch, 553 struct iovec *iov, int iov_count, 554 struct fuse_bufvec *buf, unsigned int flags) 555 { 556 int res; 557 size_t len = fuse_buf_size(buf); 558 struct fuse_out_header *out = iov[0].iov_base; 559 struct fuse_ll_pipe *llp; 560 int splice_flags; 561 size_t pipesize; 562 size_t total_fd_size; 563 size_t idx; 564 size_t headerlen; 565 struct fuse_bufvec pipe_buf = FUSE_BUFVEC_INIT(len); 566 567 if (f->broken_splice_nonblock) 568 goto fallback; 569 570 if (flags & FUSE_BUF_NO_SPLICE) 571 goto fallback; 572 573 total_fd_size = 0; 574 for (idx = buf->idx; idx < buf->count; idx++) { 575 if (buf->buf[idx].flags & FUSE_BUF_IS_FD) { 576 total_fd_size = buf->buf[idx].size; 577 if (idx == buf->idx) 578 total_fd_size -= buf->off; 579 } 580 } 581 if (total_fd_size < 2 * pagesize) 582 goto fallback; 583 584 if (f->conn.proto_minor < 14 || 585 !(f->conn.want & FUSE_CAP_SPLICE_WRITE)) 586 goto fallback; 587 588 llp = fuse_ll_get_pipe(f); 589 if (llp == NULL) 590 goto fallback; 591 592 593 headerlen = iov_length(iov, iov_count); 594 595 out->len = headerlen + len; 596 597 /* 598 * Heuristic for the required pipe size, does not work if the 599 * source contains less than page size fragments 600 */ 601 pipesize = pagesize * (iov_count + buf->count + 1) + out->len; 602 603 if (llp->size < pipesize) { 604 if (llp->can_grow) { 605 res = fcntl(llp->pipe[0], F_SETPIPE_SZ, pipesize); 606 if (res == -1) { 607 llp->can_grow = 0; 608 goto fallback; 609 } 610 llp->size = res; 611 } 612 if (llp->size < pipesize) 613 goto fallback; 614 } 615 616 617 res = vmsplice(llp->pipe[1], iov, iov_count, SPLICE_F_NONBLOCK); 618 if (res == -1) 619 goto fallback; 620 621 if (res != headerlen) { 622 res = -EIO; 623 fprintf(stderr, "fuse: short vmsplice to pipe: %u/%zu\n", res, 624 headerlen); 625 goto clear_pipe; 626 } 627 628 pipe_buf.buf[0].flags = FUSE_BUF_IS_FD; 629 pipe_buf.buf[0].fd = llp->pipe[1]; 630 631 res = fuse_buf_copy(&pipe_buf, buf, 632 FUSE_BUF_FORCE_SPLICE | FUSE_BUF_SPLICE_NONBLOCK); 633 if (res < 0) { 634 if (res == -EAGAIN || res == -EINVAL) { 635 /* 636 * Should only get EAGAIN on kernels with 637 * broken SPLICE_F_NONBLOCK support (<= 638 * 2.6.35) where this error or a short read is 639 * returned even if the pipe itself is not 640 * full 641 * 642 * EINVAL might mean that splice can't handle 643 * this combination of input and output. 644 */ 645 if (res == -EAGAIN) 646 f->broken_splice_nonblock = 1; 647 648 pthread_setspecific(f->pipe_key, NULL); 649 fuse_ll_pipe_free(llp); 650 goto fallback; 651 } 652 res = -res; 653 goto clear_pipe; 654 } 655 656 if (res != 0 && res < len) { 657 struct fuse_bufvec mem_buf = FUSE_BUFVEC_INIT(len); 658 void *mbuf; 659 size_t now_len = res; 660 /* 661 * For regular files a short count is either 662 * 1) due to EOF, or 663 * 2) because of broken SPLICE_F_NONBLOCK (see above) 664 * 665 * For other inputs it's possible that we overflowed 666 * the pipe because of small buffer fragments. 667 */ 668 669 res = posix_memalign(&mbuf, pagesize, len); 670 if (res != 0) 671 goto clear_pipe; 672 673 mem_buf.buf[0].mem = mbuf; 674 mem_buf.off = now_len; 675 res = fuse_buf_copy(&mem_buf, buf, 0); 676 if (res > 0) { 677 char *tmpbuf; 678 size_t extra_len = res; 679 /* 680 * Trickiest case: got more data. Need to get 681 * back the data from the pipe and then fall 682 * back to regular write. 683 */ 684 tmpbuf = malloc(headerlen); 685 if (tmpbuf == NULL) { 686 free(mbuf); 687 res = ENOMEM; 688 goto clear_pipe; 689 } 690 res = read_back(llp->pipe[0], tmpbuf, headerlen); 691 free(tmpbuf); 692 if (res != 0) { 693 free(mbuf); 694 goto clear_pipe; 695 } 696 res = read_back(llp->pipe[0], mbuf, now_len); 697 if (res != 0) { 698 free(mbuf); 699 goto clear_pipe; 700 } 701 len = now_len + extra_len; 702 iov[iov_count].iov_base = mbuf; 703 iov[iov_count].iov_len = len; 704 iov_count++; 705 res = fuse_send_msg(f, ch, iov, iov_count); 706 free(mbuf); 707 return res; 708 } 709 free(mbuf); 710 res = now_len; 711 } 712 len = res; 713 out->len = headerlen + len; 714 715 if (f->debug) { 716 fprintf(stderr, 717 " unique: %llu, success, outsize: %i (splice)\n", 718 (unsigned long long) out->unique, out->len); 719 } 720 721 splice_flags = 0; 722 if ((flags & FUSE_BUF_SPLICE_MOVE) && 723 (f->conn.want & FUSE_CAP_SPLICE_MOVE)) 724 splice_flags |= SPLICE_F_MOVE; 725 726 res = splice(llp->pipe[0], NULL, 727 fuse_chan_fd(ch), NULL, out->len, splice_flags); 728 if (res == -1) { 729 res = -errno; 730 perror("fuse: splice from pipe"); 731 goto clear_pipe; 732 } 733 if (res != out->len) { 734 res = -EIO; 735 fprintf(stderr, "fuse: short splice from pipe: %u/%u\n", 736 res, out->len); 737 goto clear_pipe; 738 } 739 return 0; 740 741 clear_pipe: 742 fuse_ll_clear_pipe(f); 743 return res; 744 745 fallback: 746 return fuse_send_data_iov_fallback(f, ch, iov, iov_count, buf, len); 747 } 748 #else 749 static int fuse_send_data_iov(struct fuse_ll *f, struct fuse_chan *ch, 750 struct iovec *iov, int iov_count, 751 struct fuse_bufvec *buf, unsigned int flags) 752 { 753 size_t len = fuse_buf_size(buf); 754 (void) flags; 755 756 return fuse_send_data_iov_fallback(f, ch, iov, iov_count, buf, len); 757 } 758 #endif 759 760 int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv, 761 enum fuse_buf_copy_flags flags) 762 { 763 struct iovec iov[2]; 764 struct fuse_out_header out; 765 int res; 766 767 iov[0].iov_base = &out; 768 iov[0].iov_len = sizeof(struct fuse_out_header); 769 770 out.unique = req->unique; 771 out.error = 0; 772 773 res = fuse_send_data_iov(req->f, req->ch, iov, 1, bufv, flags); 774 if (res <= 0) { 775 fuse_free_req(req); 776 return res; 777 } else { 778 return fuse_reply_err(req, res); 779 } 780 } 781 782 int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf) 783 { 784 struct fuse_statfs_out arg; 785 size_t size = req->f->conn.proto_minor < 4 ? 786 FUSE_COMPAT_STATFS_SIZE : sizeof(arg); 787 788 memset(&arg, 0, sizeof(arg)); 789 convert_statfs(stbuf, &arg.st); 790 791 return send_reply_ok(req, &arg, size); 792 } 793 794 int fuse_reply_xattr(fuse_req_t req, size_t count) 795 { 796 struct fuse_getxattr_out arg; 797 798 memset(&arg, 0, sizeof(arg)); 799 arg.size = count; 800 801 return send_reply_ok(req, &arg, sizeof(arg)); 802 } 803 804 int fuse_reply_lock(fuse_req_t req, const struct flock *lock) 805 { 806 struct fuse_lk_out arg; 807 808 memset(&arg, 0, sizeof(arg)); 809 arg.lk.type = lock->l_type; 810 if (lock->l_type != F_UNLCK) { 811 arg.lk.start = lock->l_start; 812 if (lock->l_len == 0) 813 arg.lk.end = OFFSET_MAX; 814 else 815 arg.lk.end = lock->l_start + lock->l_len - 1; 816 } 817 arg.lk.pid = lock->l_pid; 818 return send_reply_ok(req, &arg, sizeof(arg)); 819 } 820 821 int fuse_reply_bmap(fuse_req_t req, uint64_t idx) 822 { 823 struct fuse_bmap_out arg; 824 825 memset(&arg, 0, sizeof(arg)); 826 arg.block = idx; 827 828 return send_reply_ok(req, &arg, sizeof(arg)); 829 } 830 831 static struct fuse_ioctl_iovec *fuse_ioctl_iovec_copy(const struct iovec *iov, 832 size_t count) 833 { 834 struct fuse_ioctl_iovec *fiov; 835 size_t i; 836 837 fiov = malloc(sizeof(fiov[0]) * count); 838 if (!fiov) 839 return NULL; 840 841 for (i = 0; i < count; i++) { 842 fiov[i].base = (uintptr_t) iov[i].iov_base; 843 fiov[i].len = iov[i].iov_len; 844 } 845 846 return fiov; 847 } 848 849 int fuse_reply_ioctl_retry(fuse_req_t req, 850 const struct iovec *in_iov, size_t in_count, 851 const struct iovec *out_iov, size_t out_count) 852 { 853 struct fuse_ioctl_out arg; 854 struct fuse_ioctl_iovec *in_fiov = NULL; 855 struct fuse_ioctl_iovec *out_fiov = NULL; 856 struct iovec iov[4]; 857 size_t count = 1; 858 int res; 859 860 memset(&arg, 0, sizeof(arg)); 861 arg.flags |= FUSE_IOCTL_RETRY; 862 arg.in_iovs = in_count; 863 arg.out_iovs = out_count; 864 iov[count].iov_base = &arg; 865 iov[count].iov_len = sizeof(arg); 866 count++; 867 868 if (req->f->conn.proto_minor < 16) { 869 if (in_count) { 870 iov[count].iov_base = (void *)in_iov; 871 iov[count].iov_len = sizeof(in_iov[0]) * in_count; 872 count++; 873 } 874 875 if (out_count) { 876 iov[count].iov_base = (void *)out_iov; 877 iov[count].iov_len = sizeof(out_iov[0]) * out_count; 878 count++; 879 } 880 } else { 881 /* Can't handle non-compat 64bit ioctls on 32bit */ 882 if (sizeof(void *) == 4 && req->ioctl_64bit) { 883 res = fuse_reply_err(req, EINVAL); 884 goto out; 885 } 886 887 if (in_count) { 888 in_fiov = fuse_ioctl_iovec_copy(in_iov, in_count); 889 if (!in_fiov) 890 goto enomem; 891 892 iov[count].iov_base = (void *)in_fiov; 893 iov[count].iov_len = sizeof(in_fiov[0]) * in_count; 894 count++; 895 } 896 if (out_count) { 897 out_fiov = fuse_ioctl_iovec_copy(out_iov, out_count); 898 if (!out_fiov) 899 goto enomem; 900 901 iov[count].iov_base = (void *)out_fiov; 902 iov[count].iov_len = sizeof(out_fiov[0]) * out_count; 903 count++; 904 } 905 } 906 907 res = send_reply_iov(req, 0, iov, count); 908 out: 909 free(in_fiov); 910 free(out_fiov); 911 912 return res; 913 914 enomem: 915 res = fuse_reply_err(req, ENOMEM); 916 goto out; 917 } 918 919 int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size) 920 { 921 struct fuse_ioctl_out arg; 922 struct iovec iov[3]; 923 size_t count = 1; 924 925 memset(&arg, 0, sizeof(arg)); 926 arg.result = result; 927 iov[count].iov_base = &arg; 928 iov[count].iov_len = sizeof(arg); 929 count++; 930 931 if (size) { 932 iov[count].iov_base = (char *) buf; 933 iov[count].iov_len = size; 934 count++; 935 } 936 937 return send_reply_iov(req, 0, iov, count); 938 } 939 940 int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov, 941 int count) 942 { 943 struct iovec *padded_iov; 944 struct fuse_ioctl_out arg; 945 int res; 946 947 padded_iov = malloc((count + 2) * sizeof(struct iovec)); 948 if (padded_iov == NULL) 949 return fuse_reply_err(req, ENOMEM); 950 951 memset(&arg, 0, sizeof(arg)); 952 arg.result = result; 953 padded_iov[1].iov_base = &arg; 954 padded_iov[1].iov_len = sizeof(arg); 955 956 memcpy(&padded_iov[2], iov, count * sizeof(struct iovec)); 957 958 res = send_reply_iov(req, 0, padded_iov, count + 2); 959 free(padded_iov); 960 961 return res; 962 } 963 964 int fuse_reply_poll(fuse_req_t req, unsigned revents) 965 { 966 struct fuse_poll_out arg; 967 968 memset(&arg, 0, sizeof(arg)); 969 arg.revents = revents; 970 971 return send_reply_ok(req, &arg, sizeof(arg)); 972 } 973 974 static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 975 { 976 char *name = (char *) inarg; 977 978 if (req->f->op.lookup) 979 req->f->op.lookup(req, nodeid, name); 980 else 981 fuse_reply_err(req, ENOSYS); 982 } 983 984 static void do_forget(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 985 { 986 struct fuse_forget_in *arg = (struct fuse_forget_in *) inarg; 987 988 if (req->f->op.forget) 989 req->f->op.forget(req, nodeid, arg->nlookup); 990 else 991 fuse_reply_none(req); 992 } 993 994 static void do_batch_forget(fuse_req_t req, fuse_ino_t nodeid, 995 const void *inarg) 996 { 997 struct fuse_batch_forget_in *arg = (void *) inarg; 998 struct fuse_forget_one *param = (void *) PARAM(arg); 999 unsigned int i; 1000 1001 (void) nodeid; 1002 1003 if (req->f->op.forget_multi) { 1004 req->f->op.forget_multi(req, arg->count, 1005 (struct fuse_forget_data *) param); 1006 } else if (req->f->op.forget) { 1007 for (i = 0; i < arg->count; i++) { 1008 struct fuse_forget_one *forget = ¶m[i]; 1009 struct fuse_req *dummy_req; 1010 1011 dummy_req = fuse_ll_alloc_req(req->f); 1012 if (dummy_req == NULL) 1013 break; 1014 1015 dummy_req->unique = req->unique; 1016 dummy_req->ctx = req->ctx; 1017 dummy_req->ch = NULL; 1018 1019 req->f->op.forget(dummy_req, forget->nodeid, 1020 forget->nlookup); 1021 } 1022 fuse_reply_none(req); 1023 } else { 1024 fuse_reply_none(req); 1025 } 1026 } 1027 1028 static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1029 { 1030 struct fuse_file_info *fip = NULL; 1031 struct fuse_file_info fi; 1032 1033 if (req->f->conn.proto_minor >= 9) { 1034 struct fuse_getattr_in *arg = (struct fuse_getattr_in *) inarg; 1035 1036 if (arg->getattr_flags & FUSE_GETATTR_FH) { 1037 memset(&fi, 0, sizeof(fi)); 1038 fi.fh = arg->fh; 1039 fi.fh_old = fi.fh; 1040 fip = &fi; 1041 } 1042 } 1043 1044 if (req->f->op.getattr) 1045 req->f->op.getattr(req, nodeid, fip); 1046 else 1047 fuse_reply_err(req, ENOSYS); 1048 } 1049 1050 static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1051 { 1052 struct fuse_setattr_in *arg = (struct fuse_setattr_in *) inarg; 1053 1054 if (req->f->op.setattr) { 1055 struct fuse_file_info *fi = NULL; 1056 struct fuse_file_info fi_store; 1057 struct stat stbuf; 1058 memset(&stbuf, 0, sizeof(stbuf)); 1059 convert_attr(arg, &stbuf); 1060 if (arg->valid & FATTR_FH) { 1061 arg->valid &= ~FATTR_FH; 1062 memset(&fi_store, 0, sizeof(fi_store)); 1063 fi = &fi_store; 1064 fi->fh = arg->fh; 1065 fi->fh_old = fi->fh; 1066 } 1067 arg->valid &= 1068 FUSE_SET_ATTR_MODE | 1069 FUSE_SET_ATTR_UID | 1070 FUSE_SET_ATTR_GID | 1071 FUSE_SET_ATTR_SIZE | 1072 FUSE_SET_ATTR_ATIME | 1073 FUSE_SET_ATTR_MTIME | 1074 FUSE_SET_ATTR_ATIME_NOW | 1075 FUSE_SET_ATTR_MTIME_NOW; 1076 1077 req->f->op.setattr(req, nodeid, &stbuf, arg->valid, fi); 1078 } else 1079 fuse_reply_err(req, ENOSYS); 1080 } 1081 1082 static void do_access(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1083 { 1084 struct fuse_access_in *arg = (struct fuse_access_in *) inarg; 1085 1086 if (req->f->op.access) 1087 req->f->op.access(req, nodeid, arg->mask); 1088 else 1089 fuse_reply_err(req, ENOSYS); 1090 } 1091 1092 static void do_readlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1093 { 1094 (void) inarg; 1095 1096 if (req->f->op.readlink) 1097 req->f->op.readlink(req, nodeid); 1098 else 1099 fuse_reply_err(req, ENOSYS); 1100 } 1101 1102 static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1103 { 1104 struct fuse_mknod_in *arg = (struct fuse_mknod_in *) inarg; 1105 char *name = PARAM(arg); 1106 1107 if (req->f->conn.proto_minor >= 12) 1108 req->ctx.umask = arg->umask; 1109 else 1110 name = (char *) inarg + FUSE_COMPAT_MKNOD_IN_SIZE; 1111 1112 if (req->f->op.mknod) 1113 req->f->op.mknod(req, nodeid, name, arg->mode, arg->rdev); 1114 else 1115 fuse_reply_err(req, ENOSYS); 1116 } 1117 1118 static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1119 { 1120 struct fuse_mkdir_in *arg = (struct fuse_mkdir_in *) inarg; 1121 1122 if (req->f->conn.proto_minor >= 12) 1123 req->ctx.umask = arg->umask; 1124 1125 if (req->f->op.mkdir) 1126 req->f->op.mkdir(req, nodeid, PARAM(arg), arg->mode); 1127 else 1128 fuse_reply_err(req, ENOSYS); 1129 } 1130 1131 static void do_unlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1132 { 1133 char *name = (char *) inarg; 1134 1135 if (req->f->op.unlink) 1136 req->f->op.unlink(req, nodeid, name); 1137 else 1138 fuse_reply_err(req, ENOSYS); 1139 } 1140 1141 static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1142 { 1143 char *name = (char *) inarg; 1144 1145 if (req->f->op.rmdir) 1146 req->f->op.rmdir(req, nodeid, name); 1147 else 1148 fuse_reply_err(req, ENOSYS); 1149 } 1150 1151 static void do_symlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1152 { 1153 char *name = (char *) inarg; 1154 char *linkname = ((char *) inarg) + strlen((char *) inarg) + 1; 1155 1156 if (req->f->op.symlink) 1157 req->f->op.symlink(req, linkname, nodeid, name); 1158 else 1159 fuse_reply_err(req, ENOSYS); 1160 } 1161 1162 static void do_rename(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1163 { 1164 struct fuse_rename_in *arg = (struct fuse_rename_in *) inarg; 1165 char *oldname = PARAM(arg); 1166 char *newname = oldname + strlen(oldname) + 1; 1167 1168 if (req->f->op.rename) 1169 req->f->op.rename(req, nodeid, oldname, arg->newdir, newname); 1170 else 1171 fuse_reply_err(req, ENOSYS); 1172 } 1173 1174 static void do_link(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1175 { 1176 struct fuse_link_in *arg = (struct fuse_link_in *) inarg; 1177 1178 if (req->f->op.link) 1179 req->f->op.link(req, arg->oldnodeid, nodeid, PARAM(arg)); 1180 else 1181 fuse_reply_err(req, ENOSYS); 1182 } 1183 1184 static void do_create(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1185 { 1186 struct fuse_create_in *arg = (struct fuse_create_in *) inarg; 1187 1188 if (req->f->op.create) { 1189 struct fuse_file_info fi; 1190 char *name = PARAM(arg); 1191 1192 memset(&fi, 0, sizeof(fi)); 1193 fi.flags = arg->flags; 1194 1195 if (req->f->conn.proto_minor >= 12) 1196 req->ctx.umask = arg->umask; 1197 else 1198 name = (char *) inarg + sizeof(struct fuse_open_in); 1199 1200 req->f->op.create(req, nodeid, name, arg->mode, &fi); 1201 } else 1202 fuse_reply_err(req, ENOSYS); 1203 } 1204 1205 static void do_open(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1206 { 1207 struct fuse_open_in *arg = (struct fuse_open_in *) inarg; 1208 struct fuse_file_info fi; 1209 1210 memset(&fi, 0, sizeof(fi)); 1211 fi.flags = arg->flags; 1212 1213 if (req->f->op.open) 1214 req->f->op.open(req, nodeid, &fi); 1215 else 1216 fuse_reply_open(req, &fi); 1217 } 1218 1219 static void do_read(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1220 { 1221 struct fuse_read_in *arg = (struct fuse_read_in *) inarg; 1222 1223 if (req->f->op.read) { 1224 struct fuse_file_info fi; 1225 1226 memset(&fi, 0, sizeof(fi)); 1227 fi.fh = arg->fh; 1228 fi.fh_old = fi.fh; 1229 if (req->f->conn.proto_minor >= 9) { 1230 fi.lock_owner = arg->lock_owner; 1231 fi.flags = arg->flags; 1232 } 1233 req->f->op.read(req, nodeid, arg->size, arg->offset, &fi); 1234 } else 1235 fuse_reply_err(req, ENOSYS); 1236 } 1237 1238 static void do_write(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1239 { 1240 struct fuse_write_in *arg = (struct fuse_write_in *) inarg; 1241 struct fuse_file_info fi; 1242 char *param; 1243 1244 memset(&fi, 0, sizeof(fi)); 1245 fi.fh = arg->fh; 1246 fi.fh_old = fi.fh; 1247 fi.writepage = arg->write_flags & 1; 1248 1249 if (req->f->conn.proto_minor < 9) { 1250 param = ((char *) arg) + FUSE_COMPAT_WRITE_IN_SIZE; 1251 } else { 1252 fi.lock_owner = arg->lock_owner; 1253 fi.flags = arg->flags; 1254 param = PARAM(arg); 1255 } 1256 1257 if (req->f->op.write) 1258 req->f->op.write(req, nodeid, param, arg->size, 1259 arg->offset, &fi); 1260 else 1261 fuse_reply_err(req, ENOSYS); 1262 } 1263 1264 static void do_write_buf(fuse_req_t req, fuse_ino_t nodeid, const void *inarg, 1265 const struct fuse_buf *ibuf) 1266 { 1267 struct fuse_ll *f = req->f; 1268 struct fuse_bufvec bufv = { 1269 .buf[0] = *ibuf, 1270 .count = 1, 1271 }; 1272 struct fuse_write_in *arg = (struct fuse_write_in *) inarg; 1273 struct fuse_file_info fi; 1274 1275 memset(&fi, 0, sizeof(fi)); 1276 fi.fh = arg->fh; 1277 fi.fh_old = fi.fh; 1278 fi.writepage = arg->write_flags & 1; 1279 1280 if (req->f->conn.proto_minor < 9) { 1281 bufv.buf[0].mem = ((char *) arg) + FUSE_COMPAT_WRITE_IN_SIZE; 1282 bufv.buf[0].size -= sizeof(struct fuse_in_header) + 1283 FUSE_COMPAT_WRITE_IN_SIZE; 1284 assert(!(bufv.buf[0].flags & FUSE_BUF_IS_FD)); 1285 } else { 1286 fi.lock_owner = arg->lock_owner; 1287 fi.flags = arg->flags; 1288 if (!(bufv.buf[0].flags & FUSE_BUF_IS_FD)) 1289 bufv.buf[0].mem = PARAM(arg); 1290 1291 bufv.buf[0].size -= sizeof(struct fuse_in_header) + 1292 sizeof(struct fuse_write_in); 1293 } 1294 if (bufv.buf[0].size < arg->size) { 1295 fprintf(stderr, "fuse: do_write_buf: buffer size too small\n"); 1296 fuse_reply_err(req, EIO); 1297 goto out; 1298 } 1299 bufv.buf[0].size = arg->size; 1300 1301 req->f->op.write_buf(req, nodeid, &bufv, arg->offset, &fi); 1302 1303 out: 1304 /* Need to reset the pipe if ->write_buf() didn't consume all data */ 1305 if ((ibuf->flags & FUSE_BUF_IS_FD) && bufv.idx < bufv.count) 1306 fuse_ll_clear_pipe(f); 1307 } 1308 1309 static void do_flush(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1310 { 1311 struct fuse_flush_in *arg = (struct fuse_flush_in *) inarg; 1312 struct fuse_file_info fi; 1313 1314 memset(&fi, 0, sizeof(fi)); 1315 fi.fh = arg->fh; 1316 fi.fh_old = fi.fh; 1317 fi.flush = 1; 1318 if (req->f->conn.proto_minor >= 7) 1319 fi.lock_owner = arg->lock_owner; 1320 1321 if (req->f->op.flush) 1322 req->f->op.flush(req, nodeid, &fi); 1323 else 1324 fuse_reply_err(req, ENOSYS); 1325 } 1326 1327 static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1328 { 1329 struct fuse_release_in *arg = (struct fuse_release_in *) inarg; 1330 struct fuse_file_info fi; 1331 1332 memset(&fi, 0, sizeof(fi)); 1333 fi.flags = arg->flags; 1334 fi.fh = arg->fh; 1335 fi.fh_old = fi.fh; 1336 if (req->f->conn.proto_minor >= 8) { 1337 fi.flush = (arg->release_flags & FUSE_RELEASE_FLUSH) ? 1 : 0; 1338 fi.lock_owner = arg->lock_owner; 1339 } 1340 if (arg->release_flags & FUSE_RELEASE_FLOCK_UNLOCK) { 1341 fi.flock_release = 1; 1342 fi.lock_owner = arg->lock_owner; 1343 } 1344 1345 if (req->f->op.release) 1346 req->f->op.release(req, nodeid, &fi); 1347 else 1348 fuse_reply_err(req, 0); 1349 } 1350 1351 static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1352 { 1353 struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg; 1354 struct fuse_file_info fi; 1355 1356 memset(&fi, 0, sizeof(fi)); 1357 fi.fh = arg->fh; 1358 fi.fh_old = fi.fh; 1359 1360 if (req->f->op.fsync) 1361 req->f->op.fsync(req, nodeid, arg->fsync_flags & 1, &fi); 1362 else 1363 fuse_reply_err(req, ENOSYS); 1364 } 1365 1366 static void do_opendir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1367 { 1368 struct fuse_open_in *arg = (struct fuse_open_in *) inarg; 1369 struct fuse_file_info fi; 1370 1371 memset(&fi, 0, sizeof(fi)); 1372 fi.flags = arg->flags; 1373 1374 if (req->f->op.opendir) 1375 req->f->op.opendir(req, nodeid, &fi); 1376 else 1377 fuse_reply_open(req, &fi); 1378 } 1379 1380 static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1381 { 1382 struct fuse_read_in *arg = (struct fuse_read_in *) inarg; 1383 struct fuse_file_info fi; 1384 1385 memset(&fi, 0, sizeof(fi)); 1386 fi.fh = arg->fh; 1387 fi.fh_old = fi.fh; 1388 1389 if (req->f->op.readdir) 1390 req->f->op.readdir(req, nodeid, arg->size, arg->offset, &fi); 1391 else 1392 fuse_reply_err(req, ENOSYS); 1393 } 1394 1395 static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1396 { 1397 struct fuse_release_in *arg = (struct fuse_release_in *) inarg; 1398 struct fuse_file_info fi; 1399 1400 memset(&fi, 0, sizeof(fi)); 1401 fi.flags = arg->flags; 1402 fi.fh = arg->fh; 1403 fi.fh_old = fi.fh; 1404 1405 if (req->f->op.releasedir) 1406 req->f->op.releasedir(req, nodeid, &fi); 1407 else 1408 fuse_reply_err(req, 0); 1409 } 1410 1411 static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1412 { 1413 struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg; 1414 struct fuse_file_info fi; 1415 1416 memset(&fi, 0, sizeof(fi)); 1417 fi.fh = arg->fh; 1418 fi.fh_old = fi.fh; 1419 1420 if (req->f->op.fsyncdir) 1421 req->f->op.fsyncdir(req, nodeid, arg->fsync_flags & 1, &fi); 1422 else 1423 fuse_reply_err(req, ENOSYS); 1424 } 1425 1426 static void do_statfs(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1427 { 1428 (void) nodeid; 1429 (void) inarg; 1430 1431 if (req->f->op.statfs) 1432 req->f->op.statfs(req, nodeid); 1433 else { 1434 struct statvfs buf = { 1435 .f_namemax = 255, 1436 .f_bsize = 512, 1437 }; 1438 fuse_reply_statfs(req, &buf); 1439 } 1440 } 1441 1442 static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1443 { 1444 struct fuse_setxattr_in *arg = (struct fuse_setxattr_in *) inarg; 1445 char *name = PARAM(arg); 1446 char *value = name + strlen(name) + 1; 1447 1448 if (req->f->op.setxattr) 1449 req->f->op.setxattr(req, nodeid, name, value, arg->size, 1450 arg->flags); 1451 else 1452 fuse_reply_err(req, ENOSYS); 1453 } 1454 1455 static void do_getxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1456 { 1457 struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg; 1458 1459 if (req->f->op.getxattr) 1460 req->f->op.getxattr(req, nodeid, PARAM(arg), arg->size); 1461 else 1462 fuse_reply_err(req, ENOSYS); 1463 } 1464 1465 static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1466 { 1467 struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg; 1468 1469 if (req->f->op.listxattr) 1470 req->f->op.listxattr(req, nodeid, arg->size); 1471 else 1472 fuse_reply_err(req, ENOSYS); 1473 } 1474 1475 static void do_removexattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1476 { 1477 char *name = (char *) inarg; 1478 1479 if (req->f->op.removexattr) 1480 req->f->op.removexattr(req, nodeid, name); 1481 else 1482 fuse_reply_err(req, ENOSYS); 1483 } 1484 1485 static void convert_fuse_file_lock(struct fuse_file_lock *fl, 1486 struct flock *flock) 1487 { 1488 memset(flock, 0, sizeof(struct flock)); 1489 flock->l_type = fl->type; 1490 flock->l_whence = SEEK_SET; 1491 flock->l_start = fl->start; 1492 if (fl->end == OFFSET_MAX) 1493 flock->l_len = 0; 1494 else 1495 flock->l_len = fl->end - fl->start + 1; 1496 flock->l_pid = fl->pid; 1497 } 1498 1499 static void do_getlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1500 { 1501 struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg; 1502 struct fuse_file_info fi; 1503 struct flock flock; 1504 1505 memset(&fi, 0, sizeof(fi)); 1506 fi.fh = arg->fh; 1507 fi.lock_owner = arg->owner; 1508 1509 convert_fuse_file_lock(&arg->lk, &flock); 1510 if (req->f->op.getlk) 1511 req->f->op.getlk(req, nodeid, &fi, &flock); 1512 else 1513 fuse_reply_err(req, ENOSYS); 1514 } 1515 1516 static void do_setlk_common(fuse_req_t req, fuse_ino_t nodeid, 1517 const void *inarg, int sleep) 1518 { 1519 struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg; 1520 struct fuse_file_info fi; 1521 struct flock flock; 1522 1523 memset(&fi, 0, sizeof(fi)); 1524 fi.fh = arg->fh; 1525 fi.lock_owner = arg->owner; 1526 1527 if (arg->lk_flags & FUSE_LK_FLOCK) { 1528 int op = 0; 1529 1530 switch (arg->lk.type) { 1531 case F_RDLCK: 1532 op = LOCK_SH; 1533 break; 1534 case F_WRLCK: 1535 op = LOCK_EX; 1536 break; 1537 case F_UNLCK: 1538 op = LOCK_UN; 1539 break; 1540 } 1541 if (!sleep) 1542 op |= LOCK_NB; 1543 1544 if (req->f->op.flock) 1545 req->f->op.flock(req, nodeid, &fi, op); 1546 else 1547 fuse_reply_err(req, ENOSYS); 1548 } else { 1549 convert_fuse_file_lock(&arg->lk, &flock); 1550 if (req->f->op.setlk) 1551 req->f->op.setlk(req, nodeid, &fi, &flock, sleep); 1552 else 1553 fuse_reply_err(req, ENOSYS); 1554 } 1555 } 1556 1557 static void do_setlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1558 { 1559 do_setlk_common(req, nodeid, inarg, 0); 1560 } 1561 1562 static void do_setlkw(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1563 { 1564 do_setlk_common(req, nodeid, inarg, 1); 1565 } 1566 1567 static int find_interrupted(struct fuse_ll *f, struct fuse_req *req) 1568 { 1569 struct fuse_req *curr; 1570 1571 for (curr = f->list.next; curr != &f->list; curr = curr->next) { 1572 if (curr->unique == req->u.i.unique) { 1573 fuse_interrupt_func_t func; 1574 void *data; 1575 1576 curr->ctr++; 1577 pthread_mutex_unlock(&f->lock); 1578 1579 /* Ugh, ugly locking */ 1580 pthread_mutex_lock(&curr->lock); 1581 pthread_mutex_lock(&f->lock); 1582 curr->interrupted = 1; 1583 func = curr->u.ni.func; 1584 data = curr->u.ni.data; 1585 pthread_mutex_unlock(&f->lock); 1586 if (func) 1587 func(curr, data); 1588 pthread_mutex_unlock(&curr->lock); 1589 1590 pthread_mutex_lock(&f->lock); 1591 curr->ctr--; 1592 if (!curr->ctr) 1593 destroy_req(curr); 1594 1595 return 1; 1596 } 1597 } 1598 for (curr = f->interrupts.next; curr != &f->interrupts; 1599 curr = curr->next) { 1600 if (curr->u.i.unique == req->u.i.unique) 1601 return 1; 1602 } 1603 return 0; 1604 } 1605 1606 static void do_interrupt(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1607 { 1608 struct fuse_interrupt_in *arg = (struct fuse_interrupt_in *) inarg; 1609 struct fuse_ll *f = req->f; 1610 1611 (void) nodeid; 1612 if (f->debug) 1613 fprintf(stderr, "INTERRUPT: %llu\n", 1614 (unsigned long long) arg->unique); 1615 1616 req->u.i.unique = arg->unique; 1617 1618 pthread_mutex_lock(&f->lock); 1619 if (find_interrupted(f, req)) 1620 destroy_req(req); 1621 else 1622 list_add_req(req, &f->interrupts); 1623 pthread_mutex_unlock(&f->lock); 1624 } 1625 1626 static struct fuse_req *check_interrupt(struct fuse_ll *f, struct fuse_req *req) 1627 { 1628 struct fuse_req *curr; 1629 1630 for (curr = f->interrupts.next; curr != &f->interrupts; 1631 curr = curr->next) { 1632 if (curr->u.i.unique == req->unique) { 1633 req->interrupted = 1; 1634 list_del_req(curr); 1635 free(curr); 1636 return NULL; 1637 } 1638 } 1639 curr = f->interrupts.next; 1640 if (curr != &f->interrupts) { 1641 list_del_req(curr); 1642 list_init_req(curr); 1643 return curr; 1644 } else 1645 return NULL; 1646 } 1647 1648 static void do_bmap(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1649 { 1650 struct fuse_bmap_in *arg = (struct fuse_bmap_in *) inarg; 1651 1652 if (req->f->op.bmap) 1653 req->f->op.bmap(req, nodeid, arg->blocksize, arg->block); 1654 else 1655 fuse_reply_err(req, ENOSYS); 1656 } 1657 1658 static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1659 { 1660 struct fuse_ioctl_in *arg = (struct fuse_ioctl_in *) inarg; 1661 unsigned int flags = arg->flags; 1662 void *in_buf = arg->in_size ? PARAM(arg) : NULL; 1663 struct fuse_file_info fi; 1664 1665 if (flags & FUSE_IOCTL_DIR && 1666 !(req->f->conn.want & FUSE_CAP_IOCTL_DIR)) { 1667 fuse_reply_err(req, ENOTTY); 1668 return; 1669 } 1670 1671 memset(&fi, 0, sizeof(fi)); 1672 fi.fh = arg->fh; 1673 fi.fh_old = fi.fh; 1674 1675 if (sizeof(void *) == 4 && req->f->conn.proto_minor >= 16 && 1676 !(flags & FUSE_IOCTL_32BIT)) { 1677 req->ioctl_64bit = 1; 1678 } 1679 1680 if (req->f->op.ioctl) 1681 req->f->op.ioctl(req, nodeid, arg->cmd, 1682 (void *)(uintptr_t)arg->arg, &fi, flags, 1683 in_buf, arg->in_size, arg->out_size); 1684 else 1685 fuse_reply_err(req, ENOSYS); 1686 } 1687 1688 void fuse_pollhandle_destroy(struct fuse_pollhandle *ph) 1689 { 1690 free(ph); 1691 } 1692 1693 static void do_poll(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1694 { 1695 struct fuse_poll_in *arg = (struct fuse_poll_in *) inarg; 1696 struct fuse_file_info fi; 1697 1698 memset(&fi, 0, sizeof(fi)); 1699 fi.fh = arg->fh; 1700 fi.fh_old = fi.fh; 1701 1702 if (req->f->op.poll) { 1703 struct fuse_pollhandle *ph = NULL; 1704 1705 if (arg->flags & FUSE_POLL_SCHEDULE_NOTIFY) { 1706 ph = malloc(sizeof(struct fuse_pollhandle)); 1707 if (ph == NULL) { 1708 fuse_reply_err(req, ENOMEM); 1709 return; 1710 } 1711 ph->kh = arg->kh; 1712 ph->ch = req->ch; 1713 ph->f = req->f; 1714 } 1715 1716 req->f->op.poll(req, nodeid, &fi, ph); 1717 } else { 1718 fuse_reply_err(req, ENOSYS); 1719 } 1720 } 1721 1722 static void do_fallocate(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1723 { 1724 struct fuse_fallocate_in *arg = (struct fuse_fallocate_in *) inarg; 1725 struct fuse_file_info fi; 1726 1727 memset(&fi, 0, sizeof(fi)); 1728 fi.fh = arg->fh; 1729 1730 if (req->f->op.fallocate) 1731 req->f->op.fallocate(req, nodeid, arg->mode, arg->offset, arg->length, &fi); 1732 else 1733 fuse_reply_err(req, ENOSYS); 1734 } 1735 1736 static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1737 { 1738 struct fuse_init_in *arg = (struct fuse_init_in *) inarg; 1739 struct fuse_init_out outarg; 1740 struct fuse_ll *f = req->f; 1741 size_t bufsize = fuse_chan_bufsize(req->ch); 1742 1743 (void) nodeid; 1744 if (f->debug) { 1745 fprintf(stderr, "INIT: %u.%u\n", arg->major, arg->minor); 1746 if (arg->major == 7 && arg->minor >= 6) { 1747 fprintf(stderr, "flags=0x%08x\n", arg->flags); 1748 fprintf(stderr, "max_readahead=0x%08x\n", 1749 arg->max_readahead); 1750 } 1751 } 1752 f->conn.proto_major = arg->major; 1753 f->conn.proto_minor = arg->minor; 1754 f->conn.capable = 0; 1755 f->conn.want = 0; 1756 1757 memset(&outarg, 0, sizeof(outarg)); 1758 outarg.major = FUSE_KERNEL_VERSION; 1759 outarg.minor = FUSE_KERNEL_MINOR_VERSION; 1760 1761 if (arg->major < 7) { 1762 fprintf(stderr, "fuse: unsupported protocol version: %u.%u\n", 1763 arg->major, arg->minor); 1764 fuse_reply_err(req, EPROTO); 1765 return; 1766 } 1767 1768 if (arg->major > 7) { 1769 /* Wait for a second INIT request with a 7.X version */ 1770 send_reply_ok(req, &outarg, sizeof(outarg)); 1771 return; 1772 } 1773 1774 if (arg->minor >= 6) { 1775 if (f->conn.async_read) 1776 f->conn.async_read = arg->flags & FUSE_ASYNC_READ; 1777 if (arg->max_readahead < f->conn.max_readahead) 1778 f->conn.max_readahead = arg->max_readahead; 1779 if (arg->flags & FUSE_ASYNC_READ) 1780 f->conn.capable |= FUSE_CAP_ASYNC_READ; 1781 if (arg->flags & FUSE_POSIX_LOCKS) 1782 f->conn.capable |= FUSE_CAP_POSIX_LOCKS; 1783 if (arg->flags & FUSE_ATOMIC_O_TRUNC) 1784 f->conn.capable |= FUSE_CAP_ATOMIC_O_TRUNC; 1785 if (arg->flags & FUSE_EXPORT_SUPPORT) 1786 f->conn.capable |= FUSE_CAP_EXPORT_SUPPORT; 1787 if (arg->flags & FUSE_BIG_WRITES) 1788 f->conn.capable |= FUSE_CAP_BIG_WRITES; 1789 if (arg->flags & FUSE_DONT_MASK) 1790 f->conn.capable |= FUSE_CAP_DONT_MASK; 1791 if (arg->flags & FUSE_FLOCK_LOCKS) 1792 f->conn.capable |= FUSE_CAP_FLOCK_LOCKS; 1793 } else { 1794 f->conn.async_read = 0; 1795 f->conn.max_readahead = 0; 1796 } 1797 1798 if (req->f->conn.proto_minor >= 14) { 1799 #ifdef HAVE_SPLICE 1800 #ifdef HAVE_VMSPLICE 1801 f->conn.capable |= FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE; 1802 if (f->splice_write) 1803 f->conn.want |= FUSE_CAP_SPLICE_WRITE; 1804 if (f->splice_move) 1805 f->conn.want |= FUSE_CAP_SPLICE_MOVE; 1806 #endif 1807 f->conn.capable |= FUSE_CAP_SPLICE_READ; 1808 if (f->splice_read) 1809 f->conn.want |= FUSE_CAP_SPLICE_READ; 1810 #endif 1811 } 1812 if (req->f->conn.proto_minor >= 18) 1813 f->conn.capable |= FUSE_CAP_IOCTL_DIR; 1814 1815 if (f->atomic_o_trunc) 1816 f->conn.want |= FUSE_CAP_ATOMIC_O_TRUNC; 1817 if (f->op.getlk && f->op.setlk && !f->no_remote_posix_lock) 1818 f->conn.want |= FUSE_CAP_POSIX_LOCKS; 1819 if (f->op.flock && !f->no_remote_flock) 1820 f->conn.want |= FUSE_CAP_FLOCK_LOCKS; 1821 if (f->big_writes) 1822 f->conn.want |= FUSE_CAP_BIG_WRITES; 1823 1824 if (bufsize < FUSE_MIN_READ_BUFFER) { 1825 fprintf(stderr, "fuse: warning: buffer size too small: %zu\n", 1826 bufsize); 1827 bufsize = FUSE_MIN_READ_BUFFER; 1828 } 1829 1830 bufsize -= 4096; 1831 if (bufsize < f->conn.max_write) 1832 f->conn.max_write = bufsize; 1833 1834 f->got_init = 1; 1835 if (f->op.init) 1836 f->op.init(f->userdata, &f->conn); 1837 1838 if (f->no_splice_read) 1839 f->conn.want &= ~FUSE_CAP_SPLICE_READ; 1840 if (f->no_splice_write) 1841 f->conn.want &= ~FUSE_CAP_SPLICE_WRITE; 1842 if (f->no_splice_move) 1843 f->conn.want &= ~FUSE_CAP_SPLICE_MOVE; 1844 1845 if (f->conn.async_read || (f->conn.want & FUSE_CAP_ASYNC_READ)) 1846 outarg.flags |= FUSE_ASYNC_READ; 1847 if (f->conn.want & FUSE_CAP_POSIX_LOCKS) 1848 outarg.flags |= FUSE_POSIX_LOCKS; 1849 if (f->conn.want & FUSE_CAP_ATOMIC_O_TRUNC) 1850 outarg.flags |= FUSE_ATOMIC_O_TRUNC; 1851 if (f->conn.want & FUSE_CAP_EXPORT_SUPPORT) 1852 outarg.flags |= FUSE_EXPORT_SUPPORT; 1853 if (f->conn.want & FUSE_CAP_BIG_WRITES) 1854 outarg.flags |= FUSE_BIG_WRITES; 1855 if (f->conn.want & FUSE_CAP_DONT_MASK) 1856 outarg.flags |= FUSE_DONT_MASK; 1857 if (f->conn.want & FUSE_CAP_FLOCK_LOCKS) 1858 outarg.flags |= FUSE_FLOCK_LOCKS; 1859 outarg.max_readahead = f->conn.max_readahead; 1860 outarg.max_write = f->conn.max_write; 1861 if (f->conn.proto_minor >= 13) { 1862 if (f->conn.max_background >= (1 << 16)) 1863 f->conn.max_background = (1 << 16) - 1; 1864 if (f->conn.congestion_threshold > f->conn.max_background) 1865 f->conn.congestion_threshold = f->conn.max_background; 1866 if (!f->conn.congestion_threshold) { 1867 f->conn.congestion_threshold = 1868 f->conn.max_background * 3 / 4; 1869 } 1870 1871 outarg.max_background = f->conn.max_background; 1872 outarg.congestion_threshold = f->conn.congestion_threshold; 1873 } 1874 1875 if (f->debug) { 1876 fprintf(stderr, " INIT: %u.%u\n", outarg.major, outarg.minor); 1877 fprintf(stderr, " flags=0x%08x\n", outarg.flags); 1878 fprintf(stderr, " max_readahead=0x%08x\n", 1879 outarg.max_readahead); 1880 fprintf(stderr, " max_write=0x%08x\n", outarg.max_write); 1881 fprintf(stderr, " max_background=%i\n", 1882 outarg.max_background); 1883 fprintf(stderr, " congestion_threshold=%i\n", 1884 outarg.congestion_threshold); 1885 } 1886 1887 send_reply_ok(req, &outarg, arg->minor < 5 ? 8 : sizeof(outarg)); 1888 } 1889 1890 static void do_destroy(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) 1891 { 1892 struct fuse_ll *f = req->f; 1893 1894 (void) nodeid; 1895 (void) inarg; 1896 1897 f->got_destroy = 1; 1898 if (f->op.destroy) 1899 f->op.destroy(f->userdata); 1900 1901 send_reply_ok(req, NULL, 0); 1902 } 1903 1904 static void list_del_nreq(struct fuse_notify_req *nreq) 1905 { 1906 struct fuse_notify_req *prev = nreq->prev; 1907 struct fuse_notify_req *next = nreq->next; 1908 prev->next = next; 1909 next->prev = prev; 1910 } 1911 1912 static void list_add_nreq(struct fuse_notify_req *nreq, 1913 struct fuse_notify_req *next) 1914 { 1915 struct fuse_notify_req *prev = next->prev; 1916 nreq->next = next; 1917 nreq->prev = prev; 1918 prev->next = nreq; 1919 next->prev = nreq; 1920 } 1921 1922 static void list_init_nreq(struct fuse_notify_req *nreq) 1923 { 1924 nreq->next = nreq; 1925 nreq->prev = nreq; 1926 } 1927 1928 static void do_notify_reply(fuse_req_t req, fuse_ino_t nodeid, 1929 const void *inarg, const struct fuse_buf *buf) 1930 { 1931 struct fuse_ll *f = req->f; 1932 struct fuse_notify_req *nreq; 1933 struct fuse_notify_req *head; 1934 1935 pthread_mutex_lock(&f->lock); 1936 head = &f->notify_list; 1937 for (nreq = head->next; nreq != head; nreq = nreq->next) { 1938 if (nreq->unique == req->unique) { 1939 list_del_nreq(nreq); 1940 break; 1941 } 1942 } 1943 pthread_mutex_unlock(&f->lock); 1944 1945 if (nreq != head) 1946 nreq->reply(nreq, req, nodeid, inarg, buf); 1947 } 1948 1949 static int send_notify_iov(struct fuse_ll *f, struct fuse_chan *ch, 1950 int notify_code, struct iovec *iov, int count) 1951 { 1952 struct fuse_out_header out; 1953 1954 if (!f->got_init) 1955 return -ENOTCONN; 1956 1957 out.unique = 0; 1958 out.error = notify_code; 1959 iov[0].iov_base = &out; 1960 iov[0].iov_len = sizeof(struct fuse_out_header); 1961 1962 return fuse_send_msg(f, ch, iov, count); 1963 } 1964 1965 int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph) 1966 { 1967 if (ph != NULL) { 1968 struct fuse_notify_poll_wakeup_out outarg; 1969 struct iovec iov[2]; 1970 1971 outarg.kh = ph->kh; 1972 1973 iov[1].iov_base = &outarg; 1974 iov[1].iov_len = sizeof(outarg); 1975 1976 return send_notify_iov(ph->f, ph->ch, FUSE_NOTIFY_POLL, iov, 2); 1977 } else { 1978 return 0; 1979 } 1980 } 1981 1982 int fuse_lowlevel_notify_inval_inode(struct fuse_chan *ch, fuse_ino_t ino, 1983 off_t off, off_t len) 1984 { 1985 struct fuse_notify_inval_inode_out outarg; 1986 struct fuse_ll *f; 1987 struct iovec iov[2]; 1988 1989 if (!ch) 1990 return -EINVAL; 1991 1992 f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch)); 1993 if (!f) 1994 return -ENODEV; 1995 1996 outarg.ino = ino; 1997 outarg.off = off; 1998 outarg.len = len; 1999 2000 iov[1].iov_base = &outarg; 2001 iov[1].iov_len = sizeof(outarg); 2002 2003 return send_notify_iov(f, ch, FUSE_NOTIFY_INVAL_INODE, iov, 2); 2004 } 2005 2006 int fuse_lowlevel_notify_inval_entry(struct fuse_chan *ch, fuse_ino_t parent, 2007 const char *name, size_t namelen) 2008 { 2009 struct fuse_notify_inval_entry_out outarg; 2010 struct fuse_ll *f; 2011 struct iovec iov[3]; 2012 2013 if (!ch) 2014 return -EINVAL; 2015 2016 f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch)); 2017 if (!f) 2018 return -ENODEV; 2019 2020 outarg.parent = parent; 2021 outarg.namelen = namelen; 2022 outarg.padding = 0; 2023 2024 iov[1].iov_base = &outarg; 2025 iov[1].iov_len = sizeof(outarg); 2026 iov[2].iov_base = (void *)name; 2027 iov[2].iov_len = namelen + 1; 2028 2029 return send_notify_iov(f, ch, FUSE_NOTIFY_INVAL_ENTRY, iov, 3); 2030 } 2031 2032 int fuse_lowlevel_notify_delete(struct fuse_chan *ch, 2033 fuse_ino_t parent, fuse_ino_t child, 2034 const char *name, size_t namelen) 2035 { 2036 struct fuse_notify_delete_out outarg; 2037 struct fuse_ll *f; 2038 struct iovec iov[3]; 2039 2040 if (!ch) 2041 return -EINVAL; 2042 2043 f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch)); 2044 if (!f) 2045 return -ENODEV; 2046 2047 if (f->conn.proto_minor < 18) 2048 return -ENOSYS; 2049 2050 outarg.parent = parent; 2051 outarg.child = child; 2052 outarg.namelen = namelen; 2053 outarg.padding = 0; 2054 2055 iov[1].iov_base = &outarg; 2056 iov[1].iov_len = sizeof(outarg); 2057 iov[2].iov_base = (void *)name; 2058 iov[2].iov_len = namelen + 1; 2059 2060 return send_notify_iov(f, ch, FUSE_NOTIFY_DELETE, iov, 3); 2061 } 2062 2063 int fuse_lowlevel_notify_store(struct fuse_chan *ch, fuse_ino_t ino, 2064 off_t offset, struct fuse_bufvec *bufv, 2065 enum fuse_buf_copy_flags flags) 2066 { 2067 struct fuse_out_header out; 2068 struct fuse_notify_store_out outarg; 2069 struct fuse_ll *f; 2070 struct iovec iov[3]; 2071 size_t size = fuse_buf_size(bufv); 2072 int res; 2073 2074 if (!ch) 2075 return -EINVAL; 2076 2077 f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch)); 2078 if (!f) 2079 return -ENODEV; 2080 2081 if (f->conn.proto_minor < 15) 2082 return -ENOSYS; 2083 2084 out.unique = 0; 2085 out.error = FUSE_NOTIFY_STORE; 2086 2087 outarg.nodeid = ino; 2088 outarg.offset = offset; 2089 outarg.size = size; 2090 outarg.padding = 0; 2091 2092 iov[0].iov_base = &out; 2093 iov[0].iov_len = sizeof(out); 2094 iov[1].iov_base = &outarg; 2095 iov[1].iov_len = sizeof(outarg); 2096 2097 res = fuse_send_data_iov(f, ch, iov, 2, bufv, flags); 2098 if (res > 0) 2099 res = -res; 2100 2101 return res; 2102 } 2103 2104 struct fuse_retrieve_req { 2105 struct fuse_notify_req nreq; 2106 void *cookie; 2107 }; 2108 2109 static void fuse_ll_retrieve_reply(struct fuse_notify_req *nreq, 2110 fuse_req_t req, fuse_ino_t ino, 2111 const void *inarg, 2112 const struct fuse_buf *ibuf) 2113 { 2114 struct fuse_ll *f = req->f; 2115 struct fuse_retrieve_req *rreq = 2116 container_of(nreq, struct fuse_retrieve_req, nreq); 2117 const struct fuse_notify_retrieve_in *arg = inarg; 2118 struct fuse_bufvec bufv = { 2119 .buf[0] = *ibuf, 2120 .count = 1, 2121 }; 2122 2123 if (!(bufv.buf[0].flags & FUSE_BUF_IS_FD)) 2124 bufv.buf[0].mem = PARAM(arg); 2125 2126 bufv.buf[0].size -= sizeof(struct fuse_in_header) + 2127 sizeof(struct fuse_notify_retrieve_in); 2128 2129 if (bufv.buf[0].size < arg->size) { 2130 fprintf(stderr, "fuse: retrieve reply: buffer size too small\n"); 2131 fuse_reply_none(req); 2132 goto out; 2133 } 2134 bufv.buf[0].size = arg->size; 2135 2136 if (req->f->op.retrieve_reply) { 2137 req->f->op.retrieve_reply(req, rreq->cookie, ino, 2138 arg->offset, &bufv); 2139 } else { 2140 fuse_reply_none(req); 2141 } 2142 out: 2143 free(rreq); 2144 if ((ibuf->flags & FUSE_BUF_IS_FD) && bufv.idx < bufv.count) 2145 fuse_ll_clear_pipe(f); 2146 } 2147 2148 int fuse_lowlevel_notify_retrieve(struct fuse_chan *ch, fuse_ino_t ino, 2149 size_t size, off_t offset, void *cookie) 2150 { 2151 struct fuse_notify_retrieve_out outarg; 2152 struct fuse_ll *f; 2153 struct iovec iov[2]; 2154 struct fuse_retrieve_req *rreq; 2155 int err; 2156 2157 if (!ch) 2158 return -EINVAL; 2159 2160 f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch)); 2161 if (!f) 2162 return -ENODEV; 2163 2164 if (f->conn.proto_minor < 15) 2165 return -ENOSYS; 2166 2167 rreq = malloc(sizeof(*rreq)); 2168 if (rreq == NULL) 2169 return -ENOMEM; 2170 2171 pthread_mutex_lock(&f->lock); 2172 rreq->cookie = cookie; 2173 rreq->nreq.unique = f->notify_ctr++; 2174 rreq->nreq.reply = fuse_ll_retrieve_reply; 2175 list_add_nreq(&rreq->nreq, &f->notify_list); 2176 pthread_mutex_unlock(&f->lock); 2177 2178 outarg.notify_unique = rreq->nreq.unique; 2179 outarg.nodeid = ino; 2180 outarg.offset = offset; 2181 outarg.size = size; 2182 2183 iov[1].iov_base = &outarg; 2184 iov[1].iov_len = sizeof(outarg); 2185 2186 err = send_notify_iov(f, ch, FUSE_NOTIFY_RETRIEVE, iov, 2); 2187 if (err) { 2188 pthread_mutex_lock(&f->lock); 2189 list_del_nreq(&rreq->nreq); 2190 pthread_mutex_unlock(&f->lock); 2191 free(rreq); 2192 } 2193 2194 return err; 2195 } 2196 2197 void *fuse_req_userdata(fuse_req_t req) 2198 { 2199 return req->f->userdata; 2200 } 2201 2202 const struct fuse_ctx *fuse_req_ctx(fuse_req_t req) 2203 { 2204 return &req->ctx; 2205 } 2206 2207 /* 2208 * The size of fuse_ctx got extended, so need to be careful about 2209 * incompatibility (i.e. a new binary cannot work with an old 2210 * library). 2211 */ 2212 const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req); 2213 const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req) 2214 { 2215 return fuse_req_ctx(req); 2216 } 2217 #ifndef __NetBSD__ 2218 FUSE_SYMVER(".symver fuse_req_ctx_compat24,fuse_req_ctx@FUSE_2.4"); 2219 #endif 2220 2221 2222 void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func, 2223 void *data) 2224 { 2225 pthread_mutex_lock(&req->lock); 2226 pthread_mutex_lock(&req->f->lock); 2227 req->u.ni.func = func; 2228 req->u.ni.data = data; 2229 pthread_mutex_unlock(&req->f->lock); 2230 if (req->interrupted && func) 2231 func(req, data); 2232 pthread_mutex_unlock(&req->lock); 2233 } 2234 2235 int fuse_req_interrupted(fuse_req_t req) 2236 { 2237 int interrupted; 2238 2239 pthread_mutex_lock(&req->f->lock); 2240 interrupted = req->interrupted; 2241 pthread_mutex_unlock(&req->f->lock); 2242 2243 return interrupted; 2244 } 2245 2246 static struct { 2247 void (*func)(fuse_req_t, fuse_ino_t, const void *); 2248 const char *name; 2249 } fuse_ll_ops[] = { 2250 [FUSE_LOOKUP] = { do_lookup, "LOOKUP" }, 2251 [FUSE_FORGET] = { do_forget, "FORGET" }, 2252 [FUSE_GETATTR] = { do_getattr, "GETATTR" }, 2253 [FUSE_SETATTR] = { do_setattr, "SETATTR" }, 2254 [FUSE_READLINK] = { do_readlink, "READLINK" }, 2255 [FUSE_SYMLINK] = { do_symlink, "SYMLINK" }, 2256 [FUSE_MKNOD] = { do_mknod, "MKNOD" }, 2257 [FUSE_MKDIR] = { do_mkdir, "MKDIR" }, 2258 [FUSE_UNLINK] = { do_unlink, "UNLINK" }, 2259 [FUSE_RMDIR] = { do_rmdir, "RMDIR" }, 2260 [FUSE_RENAME] = { do_rename, "RENAME" }, 2261 [FUSE_LINK] = { do_link, "LINK" }, 2262 [FUSE_OPEN] = { do_open, "OPEN" }, 2263 [FUSE_READ] = { do_read, "READ" }, 2264 [FUSE_WRITE] = { do_write, "WRITE" }, 2265 [FUSE_STATFS] = { do_statfs, "STATFS" }, 2266 [FUSE_RELEASE] = { do_release, "RELEASE" }, 2267 [FUSE_FSYNC] = { do_fsync, "FSYNC" }, 2268 [FUSE_SETXATTR] = { do_setxattr, "SETXATTR" }, 2269 [FUSE_GETXATTR] = { do_getxattr, "GETXATTR" }, 2270 [FUSE_LISTXATTR] = { do_listxattr, "LISTXATTR" }, 2271 [FUSE_REMOVEXATTR] = { do_removexattr, "REMOVEXATTR" }, 2272 [FUSE_FLUSH] = { do_flush, "FLUSH" }, 2273 [FUSE_INIT] = { do_init, "INIT" }, 2274 [FUSE_OPENDIR] = { do_opendir, "OPENDIR" }, 2275 [FUSE_READDIR] = { do_readdir, "READDIR" }, 2276 [FUSE_RELEASEDIR] = { do_releasedir, "RELEASEDIR" }, 2277 [FUSE_FSYNCDIR] = { do_fsyncdir, "FSYNCDIR" }, 2278 [FUSE_GETLK] = { do_getlk, "GETLK" }, 2279 [FUSE_SETLK] = { do_setlk, "SETLK" }, 2280 [FUSE_SETLKW] = { do_setlkw, "SETLKW" }, 2281 [FUSE_ACCESS] = { do_access, "ACCESS" }, 2282 [FUSE_CREATE] = { do_create, "CREATE" }, 2283 [FUSE_INTERRUPT] = { do_interrupt, "INTERRUPT" }, 2284 [FUSE_BMAP] = { do_bmap, "BMAP" }, 2285 [FUSE_IOCTL] = { do_ioctl, "IOCTL" }, 2286 [FUSE_POLL] = { do_poll, "POLL" }, 2287 [FUSE_FALLOCATE] = { do_fallocate, "FALLOCATE" }, 2288 [FUSE_DESTROY] = { do_destroy, "DESTROY" }, 2289 [FUSE_NOTIFY_REPLY] = { (void *) 1, "NOTIFY_REPLY" }, 2290 [FUSE_BATCH_FORGET] = { do_batch_forget, "BATCH_FORGET" }, 2291 [CUSE_INIT] = { cuse_lowlevel_init, "CUSE_INIT" }, 2292 }; 2293 2294 #define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0])) 2295 2296 static const char *opname(enum fuse_opcode opcode) 2297 { 2298 if (opcode >= FUSE_MAXOP || !fuse_ll_ops[opcode].name) 2299 return "???"; 2300 else 2301 return fuse_ll_ops[opcode].name; 2302 } 2303 2304 static int fuse_ll_copy_from_pipe(struct fuse_bufvec *dst, 2305 struct fuse_bufvec *src) 2306 { 2307 int res = fuse_buf_copy(dst, src, 0); 2308 if (res < 0) { 2309 fprintf(stderr, "fuse: copy from pipe: %s\n", strerror(-res)); 2310 return res; 2311 } 2312 if (res < fuse_buf_size(dst)) { 2313 fprintf(stderr, "fuse: copy from pipe: short read\n"); 2314 return -1; 2315 } 2316 return 0; 2317 } 2318 2319 static void fuse_ll_process_buf(void *data, const struct fuse_buf *buf, 2320 struct fuse_chan *ch) 2321 { 2322 struct fuse_ll *f = (struct fuse_ll *) data; 2323 const size_t write_header_size = sizeof(struct fuse_in_header) + 2324 sizeof(struct fuse_write_in); 2325 struct fuse_bufvec bufv = { .buf[0] = *buf, .count = 1 }; 2326 struct fuse_bufvec tmpbuf = FUSE_BUFVEC_INIT(write_header_size); 2327 struct fuse_in_header *in; 2328 const void *inarg; 2329 struct fuse_req *req; 2330 void *mbuf = NULL; 2331 int err; 2332 int res; 2333 2334 if (buf->flags & FUSE_BUF_IS_FD) { 2335 if (buf->size < tmpbuf.buf[0].size) 2336 tmpbuf.buf[0].size = buf->size; 2337 2338 mbuf = malloc(tmpbuf.buf[0].size); 2339 if (mbuf == NULL) { 2340 fprintf(stderr, "fuse: failed to allocate header\n"); 2341 goto clear_pipe; 2342 } 2343 tmpbuf.buf[0].mem = mbuf; 2344 2345 res = fuse_ll_copy_from_pipe(&tmpbuf, &bufv); 2346 if (res < 0) 2347 goto clear_pipe; 2348 2349 in = mbuf; 2350 } else { 2351 in = buf->mem; 2352 } 2353 2354 if (f->debug) { 2355 fprintf(stderr, 2356 "unique: %llu, opcode: %s (%i), nodeid: %lu, insize: %zu, pid: %u\n", 2357 (unsigned long long) in->unique, 2358 opname((enum fuse_opcode) in->opcode), in->opcode, 2359 (unsigned long) in->nodeid, buf->size, in->pid); 2360 } 2361 2362 req = fuse_ll_alloc_req(f); 2363 if (req == NULL) { 2364 struct fuse_out_header out = { 2365 .unique = in->unique, 2366 .error = -ENOMEM, 2367 }; 2368 struct iovec iov = { 2369 .iov_base = &out, 2370 .iov_len = sizeof(struct fuse_out_header), 2371 }; 2372 2373 fuse_send_msg(f, ch, &iov, 1); 2374 goto clear_pipe; 2375 } 2376 2377 req->unique = in->unique; 2378 req->ctx.uid = in->uid; 2379 req->ctx.gid = in->gid; 2380 req->ctx.pid = in->pid; 2381 req->ch = ch; 2382 2383 err = EIO; 2384 if (!f->got_init) { 2385 enum fuse_opcode expected; 2386 2387 expected = f->cuse_data ? CUSE_INIT : FUSE_INIT; 2388 if (in->opcode != expected) 2389 goto reply_err; 2390 } else if (in->opcode == FUSE_INIT || in->opcode == CUSE_INIT) 2391 goto reply_err; 2392 2393 err = EACCES; 2394 if (f->allow_root && in->uid != f->owner && in->uid != 0 && 2395 in->opcode != FUSE_INIT && in->opcode != FUSE_READ && 2396 in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC && 2397 in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR && 2398 in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR && 2399 in->opcode != FUSE_NOTIFY_REPLY) 2400 goto reply_err; 2401 2402 err = ENOSYS; 2403 if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func) 2404 goto reply_err; 2405 if (in->opcode != FUSE_INTERRUPT) { 2406 struct fuse_req *intr; 2407 pthread_mutex_lock(&f->lock); 2408 intr = check_interrupt(f, req); 2409 list_add_req(req, &f->list); 2410 pthread_mutex_unlock(&f->lock); 2411 if (intr) 2412 fuse_reply_err(intr, EAGAIN); 2413 } 2414 2415 if ((buf->flags & FUSE_BUF_IS_FD) && write_header_size < buf->size && 2416 (in->opcode != FUSE_WRITE || !f->op.write_buf) && 2417 in->opcode != FUSE_NOTIFY_REPLY) { 2418 void *newmbuf; 2419 2420 err = ENOMEM; 2421 newmbuf = realloc(mbuf, buf->size); 2422 if (newmbuf == NULL) 2423 goto reply_err; 2424 mbuf = newmbuf; 2425 2426 tmpbuf = FUSE_BUFVEC_INIT(buf->size - write_header_size); 2427 tmpbuf.buf[0].mem = mbuf + write_header_size; 2428 2429 res = fuse_ll_copy_from_pipe(&tmpbuf, &bufv); 2430 err = -res; 2431 if (res < 0) 2432 goto reply_err; 2433 2434 in = mbuf; 2435 } 2436 2437 inarg = (void *) &in[1]; 2438 if (in->opcode == FUSE_WRITE && f->op.write_buf) 2439 do_write_buf(req, in->nodeid, inarg, buf); 2440 else if (in->opcode == FUSE_NOTIFY_REPLY) 2441 do_notify_reply(req, in->nodeid, inarg, buf); 2442 else 2443 fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg); 2444 2445 out_free: 2446 free(mbuf); 2447 return; 2448 2449 reply_err: 2450 fuse_reply_err(req, err); 2451 clear_pipe: 2452 if (buf->flags & FUSE_BUF_IS_FD) 2453 fuse_ll_clear_pipe(f); 2454 goto out_free; 2455 } 2456 2457 static void fuse_ll_process(void *data, const char *buf, size_t len, 2458 struct fuse_chan *ch) 2459 { 2460 struct fuse_buf fbuf = { 2461 .mem = (void *) buf, 2462 .size = len, 2463 }; 2464 2465 fuse_ll_process_buf(data, &fbuf, ch); 2466 } 2467 2468 enum { 2469 KEY_HELP, 2470 KEY_VERSION, 2471 }; 2472 2473 static const struct fuse_opt fuse_ll_opts[] = { 2474 { "debug", offsetof(struct fuse_ll, debug), 1 }, 2475 { "-d", offsetof(struct fuse_ll, debug), 1 }, 2476 { "allow_root", offsetof(struct fuse_ll, allow_root), 1 }, 2477 { "max_write=%u", offsetof(struct fuse_ll, conn.max_write), 0 }, 2478 { "max_readahead=%u", offsetof(struct fuse_ll, conn.max_readahead), 0 }, 2479 { "max_background=%u", offsetof(struct fuse_ll, conn.max_background), 0 }, 2480 { "congestion_threshold=%u", 2481 offsetof(struct fuse_ll, conn.congestion_threshold), 0 }, 2482 { "async_read", offsetof(struct fuse_ll, conn.async_read), 1 }, 2483 { "sync_read", offsetof(struct fuse_ll, conn.async_read), 0 }, 2484 { "atomic_o_trunc", offsetof(struct fuse_ll, atomic_o_trunc), 1}, 2485 { "no_remote_lock", offsetof(struct fuse_ll, no_remote_posix_lock), 1}, 2486 { "no_remote_lock", offsetof(struct fuse_ll, no_remote_flock), 1}, 2487 { "no_remote_flock", offsetof(struct fuse_ll, no_remote_flock), 1}, 2488 { "no_remote_posix_lock", offsetof(struct fuse_ll, no_remote_posix_lock), 1}, 2489 { "big_writes", offsetof(struct fuse_ll, big_writes), 1}, 2490 { "splice_write", offsetof(struct fuse_ll, splice_write), 1}, 2491 { "no_splice_write", offsetof(struct fuse_ll, no_splice_write), 1}, 2492 { "splice_move", offsetof(struct fuse_ll, splice_move), 1}, 2493 { "no_splice_move", offsetof(struct fuse_ll, no_splice_move), 1}, 2494 { "splice_read", offsetof(struct fuse_ll, splice_read), 1}, 2495 { "no_splice_read", offsetof(struct fuse_ll, no_splice_read), 1}, 2496 FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD), 2497 FUSE_OPT_KEY("-h", KEY_HELP), 2498 FUSE_OPT_KEY("--help", KEY_HELP), 2499 FUSE_OPT_KEY("-V", KEY_VERSION), 2500 FUSE_OPT_KEY("--version", KEY_VERSION), 2501 FUSE_OPT_END 2502 }; 2503 2504 static void fuse_ll_version(void) 2505 { 2506 fprintf(stderr, "using FUSE kernel interface version %i.%i\n", 2507 FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); 2508 } 2509 2510 static void fuse_ll_help(void) 2511 { 2512 fprintf(stderr, 2513 " -o max_write=N set maximum size of write requests\n" 2514 " -o max_readahead=N set maximum readahead\n" 2515 " -o max_background=N set number of maximum background requests\n" 2516 " -o congestion_threshold=N set kernel's congestion threshold\n" 2517 " -o async_read perform reads asynchronously (default)\n" 2518 " -o sync_read perform reads synchronously\n" 2519 " -o atomic_o_trunc enable atomic open+truncate support\n" 2520 " -o big_writes enable larger than 4kB writes\n" 2521 " -o no_remote_lock disable remote file locking\n" 2522 " -o no_remote_flock disable remote file locking (BSD)\n" 2523 " -o no_remote_posix_lock disable remove file locking (POSIX)\n" 2524 " -o [no_]splice_write use splice to write to the fuse device\n" 2525 " -o [no_]splice_move move data while splicing to the fuse device\n" 2526 " -o [no_]splice_read use splice to read from the fuse device\n" 2527 ); 2528 } 2529 2530 static int fuse_ll_opt_proc(void *data, const char *arg, int key, 2531 struct fuse_args *outargs) 2532 { 2533 (void) data; (void) outargs; 2534 2535 switch (key) { 2536 case KEY_HELP: 2537 fuse_ll_help(); 2538 break; 2539 2540 case KEY_VERSION: 2541 fuse_ll_version(); 2542 break; 2543 2544 default: 2545 fprintf(stderr, "fuse: unknown option `%s'\n", arg); 2546 } 2547 2548 return -1; 2549 } 2550 2551 int fuse_lowlevel_is_lib_option(const char *opt) 2552 { 2553 return fuse_opt_match(fuse_ll_opts, opt); 2554 } 2555 2556 static void fuse_ll_destroy(void *data) 2557 { 2558 struct fuse_ll *f = (struct fuse_ll *) data; 2559 struct fuse_ll_pipe *llp; 2560 2561 if (f->got_init && !f->got_destroy) { 2562 if (f->op.destroy) 2563 f->op.destroy(f->userdata); 2564 } 2565 llp = pthread_getspecific(f->pipe_key); 2566 if (llp != NULL) 2567 fuse_ll_pipe_free(llp); 2568 pthread_key_delete(f->pipe_key); 2569 pthread_mutex_destroy(&f->lock); 2570 free(f->cuse_data); 2571 free(f); 2572 } 2573 2574 static void fuse_ll_pipe_destructor(void *data) 2575 { 2576 struct fuse_ll_pipe *llp = data; 2577 fuse_ll_pipe_free(llp); 2578 } 2579 2580 #ifdef HAVE_SPLICE 2581 static int fuse_ll_receive_buf(struct fuse_session *se, struct fuse_buf *buf, 2582 struct fuse_chan **chp) 2583 { 2584 struct fuse_chan *ch = *chp; 2585 struct fuse_ll *f = fuse_session_data(se); 2586 size_t bufsize = buf->size; 2587 struct fuse_ll_pipe *llp; 2588 struct fuse_buf tmpbuf; 2589 int err; 2590 int res; 2591 2592 if (f->conn.proto_minor < 14 || !(f->conn.want & FUSE_CAP_SPLICE_READ)) 2593 goto fallback; 2594 2595 llp = fuse_ll_get_pipe(f); 2596 if (llp == NULL) 2597 goto fallback; 2598 2599 if (llp->size < bufsize) { 2600 if (llp->can_grow) { 2601 res = fcntl(llp->pipe[0], F_SETPIPE_SZ, bufsize); 2602 if (res == -1) { 2603 llp->can_grow = 0; 2604 goto fallback; 2605 } 2606 llp->size = res; 2607 } 2608 if (llp->size < bufsize) 2609 goto fallback; 2610 } 2611 2612 res = splice(fuse_chan_fd(ch), NULL, llp->pipe[1], NULL, bufsize, 0); 2613 err = errno; 2614 2615 if (fuse_session_exited(se)) 2616 return 0; 2617 2618 if (res == -1) { 2619 if (err == ENODEV) { 2620 fuse_session_exit(se); 2621 return 0; 2622 } 2623 if (err != EINTR && err != EAGAIN) 2624 perror("fuse: splice from device"); 2625 return -err; 2626 } 2627 2628 if (res < sizeof(struct fuse_in_header)) { 2629 fprintf(stderr, "short splice from fuse device\n"); 2630 return -EIO; 2631 } 2632 2633 tmpbuf = (struct fuse_buf) { 2634 .size = res, 2635 .flags = FUSE_BUF_IS_FD, 2636 .fd = llp->pipe[0], 2637 }; 2638 2639 /* 2640 * Don't bother with zero copy for small requests. 2641 * fuse_loop_mt() needs to check for FORGET so this more than 2642 * just an optimization. 2643 */ 2644 if (res < sizeof(struct fuse_in_header) + 2645 sizeof(struct fuse_write_in) + pagesize) { 2646 struct fuse_bufvec src = { .buf[0] = tmpbuf, .count = 1 }; 2647 struct fuse_bufvec dst = { .buf[0] = *buf, .count = 1 }; 2648 2649 res = fuse_buf_copy(&dst, &src, 0); 2650 if (res < 0) { 2651 fprintf(stderr, "fuse: copy from pipe: %s\n", 2652 strerror(-res)); 2653 fuse_ll_clear_pipe(f); 2654 return res; 2655 } 2656 if (res < tmpbuf.size) { 2657 fprintf(stderr, "fuse: copy from pipe: short read\n"); 2658 fuse_ll_clear_pipe(f); 2659 return -EIO; 2660 } 2661 buf->size = tmpbuf.size; 2662 return buf->size; 2663 } 2664 2665 *buf = tmpbuf; 2666 2667 return res; 2668 2669 fallback: 2670 res = fuse_chan_recv(chp, buf->mem, bufsize); 2671 if (res <= 0) 2672 return res; 2673 2674 buf->size = res; 2675 2676 return res; 2677 } 2678 #else 2679 static int fuse_ll_receive_buf(struct fuse_session *se, struct fuse_buf *buf, 2680 struct fuse_chan **chp) 2681 { 2682 (void) se; 2683 2684 int res = fuse_chan_recv(chp, buf->mem, buf->size); 2685 if (res <= 0) 2686 return res; 2687 2688 buf->size = res; 2689 2690 return res; 2691 } 2692 #endif 2693 2694 2695 /* 2696 * always call fuse_lowlevel_new_common() internally, to work around a 2697 * misfeature in the FreeBSD runtime linker, which links the old 2698 * version of a symbol to internal references. 2699 */ 2700 struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args, 2701 const struct fuse_lowlevel_ops *op, 2702 size_t op_size, void *userdata) 2703 { 2704 int err; 2705 struct fuse_ll *f; 2706 struct fuse_session *se; 2707 struct fuse_session_ops sop = { 2708 .process = fuse_ll_process, 2709 .destroy = fuse_ll_destroy, 2710 }; 2711 2712 if (sizeof(struct fuse_lowlevel_ops) < op_size) { 2713 fprintf(stderr, "fuse: warning: library too old, some operations may not work\n"); 2714 op_size = sizeof(struct fuse_lowlevel_ops); 2715 } 2716 2717 f = (struct fuse_ll *) calloc(1, sizeof(struct fuse_ll)); 2718 if (f == NULL) { 2719 fprintf(stderr, "fuse: failed to allocate fuse object\n"); 2720 goto out; 2721 } 2722 2723 f->conn.async_read = 1; 2724 f->conn.max_write = UINT_MAX; 2725 f->conn.max_readahead = UINT_MAX; 2726 f->atomic_o_trunc = 0; 2727 list_init_req(&f->list); 2728 list_init_req(&f->interrupts); 2729 list_init_nreq(&f->notify_list); 2730 f->notify_ctr = 1; 2731 fuse_mutex_init(&f->lock); 2732 2733 err = pthread_key_create(&f->pipe_key, fuse_ll_pipe_destructor); 2734 if (err) { 2735 fprintf(stderr, "fuse: failed to create thread specific key: %s\n", 2736 strerror(err)); 2737 goto out_free; 2738 } 2739 2740 if (fuse_opt_parse(args, f, fuse_ll_opts, fuse_ll_opt_proc) == -1) 2741 goto out_key_destroy; 2742 2743 if (f->debug) 2744 fprintf(stderr, "FUSE library version: %s\n", PACKAGE_VERSION); 2745 2746 memcpy(&f->op, op, op_size); 2747 f->owner = getuid(); 2748 f->userdata = userdata; 2749 2750 se = fuse_session_new(&sop, f); 2751 if (!se) 2752 goto out_key_destroy; 2753 2754 se->receive_buf = fuse_ll_receive_buf; 2755 se->process_buf = fuse_ll_process_buf; 2756 2757 return se; 2758 2759 out_key_destroy: 2760 pthread_key_delete(f->pipe_key); 2761 out_free: 2762 pthread_mutex_destroy(&f->lock); 2763 free(f); 2764 out: 2765 return NULL; 2766 } 2767 2768 2769 struct fuse_session *fuse_lowlevel_new(struct fuse_args *args, 2770 const struct fuse_lowlevel_ops *op, 2771 size_t op_size, void *userdata) 2772 { 2773 return fuse_lowlevel_new_common(args, op, op_size, userdata); 2774 } 2775 2776 #ifdef linux 2777 int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[]) 2778 { 2779 char *buf; 2780 size_t bufsize = 1024; 2781 char path[128]; 2782 int ret; 2783 int fd; 2784 unsigned long pid = req->ctx.pid; 2785 char *s; 2786 2787 sprintf(path, "/proc/%lu/task/%lu/status", pid, pid); 2788 2789 retry: 2790 buf = malloc(bufsize); 2791 if (buf == NULL) 2792 return -ENOMEM; 2793 2794 ret = -EIO; 2795 fd = open(path, O_RDONLY); 2796 if (fd == -1) 2797 goto out_free; 2798 2799 ret = read(fd, buf, bufsize); 2800 close(fd); 2801 if (ret == -1) { 2802 ret = -EIO; 2803 goto out_free; 2804 } 2805 2806 if (ret == bufsize) { 2807 free(buf); 2808 bufsize *= 4; 2809 goto retry; 2810 } 2811 2812 ret = -EIO; 2813 s = strstr(buf, "\nGroups:"); 2814 if (s == NULL) 2815 goto out_free; 2816 2817 s += 8; 2818 ret = 0; 2819 while (1) { 2820 char *end; 2821 unsigned long val = strtoul(s, &end, 0); 2822 if (end == s) 2823 break; 2824 2825 s = end; 2826 if (ret < size) 2827 list[ret] = val; 2828 ret++; 2829 } 2830 2831 out_free: 2832 free(buf); 2833 return ret; 2834 } 2835 #else /* linux */ 2836 /* 2837 * This is currently not implemented on other than Linux... 2838 */ 2839 int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[]) 2840 { 2841 return -ENOSYS; 2842 } 2843 #endif 2844 2845 #if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__) 2846 2847 static void fill_open_compat(struct fuse_open_out *arg, 2848 const struct fuse_file_info_compat *f) 2849 { 2850 arg->fh = f->fh; 2851 if (f->direct_io) 2852 arg->open_flags |= FOPEN_DIRECT_IO; 2853 if (f->keep_cache) 2854 arg->open_flags |= FOPEN_KEEP_CACHE; 2855 } 2856 2857 static void convert_statfs_compat(const struct statfs *compatbuf, 2858 struct statvfs *buf) 2859 { 2860 buf->f_bsize = compatbuf->f_bsize; 2861 buf->f_blocks = compatbuf->f_blocks; 2862 buf->f_bfree = compatbuf->f_bfree; 2863 buf->f_bavail = compatbuf->f_bavail; 2864 buf->f_files = compatbuf->f_files; 2865 buf->f_ffree = compatbuf->f_ffree; 2866 buf->f_namemax = compatbuf->f_namelen; 2867 } 2868 2869 int fuse_reply_open_compat(fuse_req_t req, 2870 const struct fuse_file_info_compat *f) 2871 { 2872 struct fuse_open_out arg; 2873 2874 memset(&arg, 0, sizeof(arg)); 2875 fill_open_compat(&arg, f); 2876 return send_reply_ok(req, &arg, sizeof(arg)); 2877 } 2878 2879 int fuse_reply_statfs_compat(fuse_req_t req, const struct statfs *stbuf) 2880 { 2881 struct statvfs newbuf; 2882 2883 memset(&newbuf, 0, sizeof(newbuf)); 2884 convert_statfs_compat(stbuf, &newbuf); 2885 2886 return fuse_reply_statfs(req, &newbuf); 2887 } 2888 2889 struct fuse_session *fuse_lowlevel_new_compat(const char *opts, 2890 const struct fuse_lowlevel_ops_compat *op, 2891 size_t op_size, void *userdata) 2892 { 2893 struct fuse_session *se; 2894 struct fuse_args args = FUSE_ARGS_INIT(0, NULL); 2895 2896 if (opts && 2897 (fuse_opt_add_arg(&args, "") == -1 || 2898 fuse_opt_add_arg(&args, "-o") == -1 || 2899 fuse_opt_add_arg(&args, opts) == -1)) { 2900 fuse_opt_free_args(&args); 2901 return NULL; 2902 } 2903 se = fuse_lowlevel_new(&args, (const struct fuse_lowlevel_ops *) op, 2904 op_size, userdata); 2905 fuse_opt_free_args(&args); 2906 2907 return se; 2908 } 2909 2910 struct fuse_ll_compat_conf { 2911 unsigned max_read; 2912 int set_max_read; 2913 }; 2914 2915 static const struct fuse_opt fuse_ll_opts_compat[] = { 2916 { "max_read=", offsetof(struct fuse_ll_compat_conf, set_max_read), 1 }, 2917 { "max_read=%u", offsetof(struct fuse_ll_compat_conf, max_read), 0 }, 2918 FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_KEEP), 2919 FUSE_OPT_END 2920 }; 2921 2922 int fuse_sync_compat_args(struct fuse_args *args) 2923 { 2924 struct fuse_ll_compat_conf conf; 2925 2926 memset(&conf, 0, sizeof(conf)); 2927 if (fuse_opt_parse(args, &conf, fuse_ll_opts_compat, NULL) == -1) 2928 return -1; 2929 2930 if (fuse_opt_insert_arg(args, 1, "-osync_read")) 2931 return -1; 2932 2933 if (conf.set_max_read) { 2934 char tmpbuf[64]; 2935 2936 sprintf(tmpbuf, "-omax_readahead=%u", conf.max_read); 2937 if (fuse_opt_insert_arg(args, 1, tmpbuf) == -1) 2938 return -1; 2939 } 2940 return 0; 2941 } 2942 2943 FUSE_SYMVER(".symver fuse_reply_statfs_compat,fuse_reply_statfs@FUSE_2.4"); 2944 FUSE_SYMVER(".symver fuse_reply_open_compat,fuse_reply_open@FUSE_2.4"); 2945 FUSE_SYMVER(".symver fuse_lowlevel_new_compat,fuse_lowlevel_new@FUSE_2.4"); 2946 2947 #else /* __FreeBSD__ || __NetBSD__ */ 2948 2949 int fuse_sync_compat_args(struct fuse_args *args) 2950 { 2951 (void) args; 2952 return 0; 2953 } 2954 2955 #endif /* __FreeBSD__ || __NetBSD__ */ 2956 2957 struct fuse_session *fuse_lowlevel_new_compat25(struct fuse_args *args, 2958 const struct fuse_lowlevel_ops_compat25 *op, 2959 size_t op_size, void *userdata) 2960 { 2961 if (fuse_sync_compat_args(args) == -1) 2962 return NULL; 2963 2964 return fuse_lowlevel_new_common(args, 2965 (const struct fuse_lowlevel_ops *) op, 2966 op_size, userdata); 2967 } 2968 2969 FUSE_SYMVER(".symver fuse_lowlevel_new_compat25,fuse_lowlevel_new@FUSE_2.5"); 2970