Changeset 368ee04 in mainline for uspace/lib/fs/libfs.c
- Timestamp:
- 2017-04-05T18:10:39Z (8 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 93ad8166
- Parents:
- 39f892a9 (diff), 2166728 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/fs/libfs.c
r39f892a9 r368ee04 36 36 37 37 #include "libfs.h" 38 #include "../../srv/vfs/vfs.h"39 38 #include <macros.h> 40 39 #include <errno.h> … … 44 43 #include <dirent.h> 45 44 #include <mem.h> 46 #include <sys/stat.h> 47 #include <sys/statfs.h> 45 #include <str.h> 48 46 #include <stdlib.h> 47 #include <fibril_synch.h> 48 #include <ipc/vfs.h> 49 #include <vfs/vfs.h> 49 50 50 51 #define on_error(rc, action) \ … … 68 69 static libfs_ops_t *libfs_ops = NULL; 69 70 70 static void libfs_mount(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *); 71 static void libfs_unmount(libfs_ops_t *, ipc_callid_t, ipc_call_t *); 71 static char fs_name[FS_NAME_MAXLEN + 1]; 72 73 static void libfs_link(libfs_ops_t *, fs_handle_t, ipc_callid_t, 74 ipc_call_t *); 72 75 static void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t, 73 76 ipc_call_t *); … … 75 78 static void libfs_open_node(libfs_ops_t *, fs_handle_t, ipc_callid_t, 76 79 ipc_call_t *); 77 static void libfs_statfs(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *); 80 static void libfs_statfs(libfs_ops_t *, fs_handle_t, ipc_callid_t, 81 ipc_call_t *); 78 82 79 83 static void vfs_out_mounted(ipc_callid_t rid, ipc_call_t *req) … … 104 108 } 105 109 106 static void vfs_out_mount(ipc_callid_t rid, ipc_call_t *req)107 {108 libfs_mount(libfs_ops, reg.fs_handle, rid, req);109 }110 111 110 static void vfs_out_unmounted(ipc_callid_t rid, ipc_call_t *req) 112 111 { … … 119 118 } 120 119 121 static void vfs_out_unmount(ipc_callid_t rid, ipc_call_t *req) 122 { 123 124 libfs_unmount(libfs_ops, rid, req); 120 static void vfs_out_link(ipc_callid_t rid, ipc_call_t *req) 121 { 122 libfs_link(libfs_ops, reg.fs_handle, rid, req); 125 123 } 126 124 … … 159 157 rc = vfs_out_ops->write(service_id, index, pos, &wbytes, &nsize); 160 158 161 if (rc == EOK) 162 async_answer_3(rid, EOK, wbytes, LOWER32(nsize), UPPER32(nsize)); 163 else 159 if (rc == EOK) { 160 async_answer_3(rid, EOK, wbytes, LOWER32(nsize), 161 UPPER32(nsize)); 162 } else 164 163 async_answer_0(rid, rc); 165 164 } … … 193 192 service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req); 194 193 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req); 194 195 195 int rc; 196 197 rc = vfs_out_ops->destroy(service_id, index); 198 196 fs_node_t *node = NULL; 197 rc = libfs_ops->node_get(&node, service_id, index); 198 if (rc == EOK && node != NULL) { 199 bool destroy = (libfs_ops->lnkcnt_get(node) == 0); 200 libfs_ops->node_put(node); 201 if (destroy) 202 rc = vfs_out_ops->destroy(service_id, index); 203 } 199 204 async_answer_0(rid, rc); 200 205 } … … 225 230 libfs_statfs(libfs_ops, reg.fs_handle, rid, req); 226 231 } 232 233 static void vfs_out_is_empty(ipc_callid_t rid, ipc_call_t *req) 234 { 235 service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req); 236 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req); 237 int rc; 238 239 fs_node_t *node = NULL; 240 rc = libfs_ops->node_get(&node, service_id, index); 241 if (rc != EOK) 242 async_answer_0(rid, rc); 243 if (node == NULL) 244 async_answer_0(rid, EINVAL); 245 246 bool children = false; 247 rc = libfs_ops->has_children(&children, node); 248 libfs_ops->node_put(node); 249 250 if (rc != EOK) 251 async_answer_0(rid, rc); 252 async_answer_0(rid, children ? ENOTEMPTY : EOK); 253 } 254 227 255 static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 228 256 { … … 247 275 vfs_out_mounted(callid, &call); 248 276 break; 249 case VFS_OUT_MOUNT:250 vfs_out_mount(callid, &call);251 break;252 277 case VFS_OUT_UNMOUNTED: 253 278 vfs_out_unmounted(callid, &call); 254 279 break; 255 case VFS_OUT_ UNMOUNT:256 vfs_out_ unmount(callid, &call);280 case VFS_OUT_LINK: 281 vfs_out_link(callid, &call); 257 282 break; 258 283 case VFS_OUT_LOOKUP: … … 285 310 case VFS_OUT_STATFS: 286 311 vfs_out_statfs(callid, &call); 312 break; 313 case VFS_OUT_IS_EMPTY: 314 vfs_out_is_empty(callid, &call); 287 315 break; 288 316 default: … … 338 366 vfs_out_ops = vops; 339 367 libfs_ops = lops; 368 369 str_cpy(fs_name, sizeof(fs_name), info->name); 340 370 341 371 /* … … 383 413 } 384 414 385 void libfs_mount(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, 415 static char plb_get_char(unsigned pos) 416 { 417 return reg.plb_ro[pos % PLB_SIZE]; 418 } 419 420 static int plb_get_component(char *dest, unsigned *sz, unsigned *ppos, 421 unsigned last) 422 { 423 unsigned pos = *ppos; 424 unsigned size = 0; 425 426 if (pos == last) { 427 *sz = 0; 428 return ERANGE; 429 } 430 431 char c = plb_get_char(pos); 432 if (c == '/') 433 pos++; 434 435 for (int i = 0; i <= NAME_MAX; i++) { 436 c = plb_get_char(pos); 437 if (pos == last || c == '/') { 438 dest[i] = 0; 439 *ppos = pos; 440 *sz = size; 441 return EOK; 442 } 443 dest[i] = c; 444 pos++; 445 size++; 446 } 447 return ENAMETOOLONG; 448 } 449 450 static int receive_fname(char *buffer) 451 { 452 size_t size; 453 ipc_callid_t wcall; 454 455 if (!async_data_write_receive(&wcall, &size)) 456 return ENOENT; 457 if (size > NAME_MAX + 1) { 458 async_answer_0(wcall, ERANGE); 459 return ERANGE; 460 } 461 return async_data_write_finalize(wcall, buffer, size); 462 } 463 464 /** Link a file at a path. 465 */ 466 void libfs_link(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, 386 467 ipc_call_t *req) 387 468 { 388 service_id_t mp_service_id = (service_id_t)IPC_GET_ARG1(*req);389 fs_index_t mp_fs_index = (fs_index_t)IPC_GET_ARG2(*req);390 fs_ handle_t mr_fs_handle = (fs_handle_t)IPC_GET_ARG3(*req);391 service_id_t mr_service_id = (service_id_t) IPC_GET_ARG4(*req);392 393 async_sess_t *mountee_sess = async_clone_receive(EXCHANGE_PARALLEL);394 if ( mountee_sess == NULL) {395 async_answer_0(rid, EINVAL);469 service_id_t parent_sid = IPC_GET_ARG1(*req); 470 fs_index_t parent_index = IPC_GET_ARG2(*req); 471 fs_index_t child_index = IPC_GET_ARG3(*req); 472 473 char component[NAME_MAX + 1]; 474 int rc = receive_fname(component); 475 if (rc != EOK) { 476 async_answer_0(rid, rc); 396 477 return; 397 478 } 398 399 fs_node_t *fn; 400 int res = ops->node_get(&fn, mp_service_id, mp_fs_index); 401 if ((res != EOK) || (!fn)) { 402 async_hangup(mountee_sess); 403 async_data_write_void(combine_rc(res, ENOENT)); 404 async_answer_0(rid, combine_rc(res, ENOENT)); 479 480 fs_node_t *parent = NULL; 481 rc = ops->node_get(&parent, parent_sid, parent_index); 482 if (parent == NULL) { 483 async_answer_0(rid, rc == EOK ? EBADF : rc); 405 484 return; 406 485 } 407 486 408 if (fn->mp_data.mp_active) {409 async_hangup(mountee_sess);410 (void) ops->node_put(fn);411 async_ data_write_void(EBUSY);412 async_answer_0(rid, EBUSY);487 fs_node_t *child = NULL; 488 rc = ops->node_get(&child, parent_sid, child_index); 489 if (child == NULL) { 490 async_answer_0(rid, rc == EOK ? EBADF : rc); 491 ops->node_put(parent); 413 492 return; 414 493 } 415 494 416 async_exch_t *exch = async_exchange_begin(mountee_sess); 417 async_sess_t *sess = async_clone_establish(EXCHANGE_PARALLEL, exch); 418 419 if (!sess) { 420 async_exchange_end(exch); 421 async_hangup(mountee_sess); 422 (void) ops->node_put(fn); 423 async_data_write_void(errno); 424 async_answer_0(rid, errno); 425 return; 426 } 427 428 ipc_call_t answer; 429 int rc = async_data_write_forward_1_1(exch, VFS_OUT_MOUNTED, 430 mr_service_id, &answer); 431 async_exchange_end(exch); 432 433 if (rc == EOK) { 434 fn->mp_data.mp_active = true; 435 fn->mp_data.fs_handle = mr_fs_handle; 436 fn->mp_data.service_id = mr_service_id; 437 fn->mp_data.sess = mountee_sess; 438 } 439 440 /* 441 * Do not release the FS node so that it stays in memory. 442 */ 443 async_answer_4(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer), 444 IPC_GET_ARG3(answer), IPC_GET_ARG4(answer)); 445 } 446 447 void libfs_unmount(libfs_ops_t *ops, ipc_callid_t rid, ipc_call_t *req) 448 { 449 service_id_t mp_service_id = (service_id_t) IPC_GET_ARG1(*req); 450 fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*req); 451 fs_node_t *fn; 452 int res; 453 454 res = ops->node_get(&fn, mp_service_id, mp_fs_index); 455 if ((res != EOK) || (!fn)) { 456 async_answer_0(rid, combine_rc(res, ENOENT)); 457 return; 458 } 459 460 /* 461 * We are clearly expecting to find the mount point active. 462 */ 463 if (!fn->mp_data.mp_active) { 464 (void) ops->node_put(fn); 465 async_answer_0(rid, EINVAL); 466 return; 467 } 468 469 /* 470 * Tell the mounted file system to unmount. 471 */ 472 async_exch_t *exch = async_exchange_begin(fn->mp_data.sess); 473 res = async_req_1_0(exch, VFS_OUT_UNMOUNTED, fn->mp_data.service_id); 474 async_exchange_end(exch); 475 476 /* 477 * If everything went well, perform the clean-up on our side. 478 */ 479 if (res == EOK) { 480 async_hangup(fn->mp_data.sess); 481 fn->mp_data.mp_active = false; 482 fn->mp_data.fs_handle = 0; 483 fn->mp_data.service_id = 0; 484 fn->mp_data.sess = NULL; 485 486 /* Drop the reference created in libfs_mount(). */ 487 (void) ops->node_put(fn); 488 } 489 490 (void) ops->node_put(fn); 491 async_answer_0(rid, res); 492 } 493 494 static char plb_get_char(unsigned pos) 495 { 496 return reg.plb_ro[pos % PLB_SIZE]; 495 rc = ops->link(parent, child, component); 496 ops->node_put(parent); 497 ops->node_put(child); 498 async_answer_0(rid, rc); 497 499 } 498 500 … … 513 515 ipc_call_t *req) 514 516 { 515 unsigned int first = IPC_GET_ARG1(*req); 516 unsigned int last = IPC_GET_ARG2(*req); 517 unsigned int next = first; 517 unsigned first = IPC_GET_ARG1(*req); 518 unsigned len = IPC_GET_ARG2(*req); 518 519 service_id_t service_id = IPC_GET_ARG3(*req); 519 int lflag = IPC_GET_ARG4(*req); 520 fs_index_t index = IPC_GET_ARG5(*req); 520 fs_index_t index = IPC_GET_ARG4(*req); 521 int lflag = IPC_GET_ARG5(*req); 522 523 // TODO: Validate flags. 524 525 unsigned next = first; 526 unsigned last = first + len; 527 521 528 char component[NAME_MAX + 1]; 522 int len;523 529 int rc; 524 525 if (last < next)526 last += PLB_SIZE;527 530 528 531 fs_node_t *par = NULL; 529 532 fs_node_t *cur = NULL; 530 533 fs_node_t *tmp = NULL; 531 532 rc = ops->root_get(&cur, service_id); 533 on_error(rc, goto out_with_answer); 534 535 if (cur->mp_data.mp_active) { 536 async_exch_t *exch = async_exchange_begin(cur->mp_data.sess); 537 async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next, last, 538 cur->mp_data.service_id, lflag, index, 539 IPC_FF_ROUTE_FROM_ME); 540 async_exchange_end(exch); 534 unsigned clen = 0; 535 536 rc = ops->node_get(&cur, service_id, index); 537 if (rc != EOK) { 538 async_answer_0(rid, rc); 539 goto out; 540 } 541 542 assert(cur != NULL); 543 544 /* Find the file and its parent. */ 545 546 unsigned last_next = 0; 547 548 while (next != last) { 549 if (cur == NULL) { 550 assert(par != NULL); 551 goto out1; 552 } 553 554 if (!ops->is_directory(cur)) { 555 async_answer_0(rid, ENOTDIR); 556 goto out; 557 } 541 558 542 (void) ops->node_put(cur); 543 return; 544 } 545 546 /* Eat slash */ 547 if (plb_get_char(next) == '/') 548 next++; 549 550 while (next <= last) { 551 bool has_children; 559 last_next = next; 560 /* Collect the component */ 561 rc = plb_get_component(component, &clen, &next, last); 562 assert(rc != ERANGE); 563 if (rc != EOK) { 564 async_answer_0(rid, rc); 565 goto out; 566 } 552 567 553 rc = ops->has_children(&has_children, cur);554 on_error(rc, goto out_with_answer);555 if (!has_children)556 break;568 if (clen == 0) { 569 /* The path is just "/". */ 570 break; 571 } 557 572 558 /* Collect the component */ 559 len = 0; 560 while ((next <= last) && (plb_get_char(next) != '/')) { 561 if (len + 1 == NAME_MAX) { 562 /* Component length overflow */ 563 async_answer_0(rid, ENAMETOOLONG); 564 goto out; 565 } 566 component[len++] = plb_get_char(next); 567 /* Process next character */ 568 next++; 569 } 570 571 assert(len); 572 component[len] = '\0'; 573 /* Eat slash */ 574 next++; 573 assert(component[clen] == 0); 575 574 576 575 /* Match the component */ 577 576 rc = ops->match(&tmp, cur, component); 578 on_error(rc, goto out_with_answer); 577 if (rc != EOK) { 578 async_answer_0(rid, rc); 579 goto out; 580 } 579 581 580 /* 581 * If the matching component is a mount point, there are two 582 * legitimate semantics of the lookup operation. The first is 583 * the commonly used one in which the lookup crosses each mount 584 * point into the mounted file system. The second semantics is 585 * used mostly during unmount() and differs from the first one 586 * only in that the last mount point in the looked up path, 587 * which is also its last component, is not crossed. 588 */ 589 590 if ((tmp) && (tmp->mp_data.mp_active) && 591 (!(lflag & L_MP) || (next <= last))) { 592 if (next > last) 593 next = last = first; 594 else 595 next--; 596 597 async_exch_t *exch = async_exchange_begin(tmp->mp_data.sess); 598 async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next, 599 last, tmp->mp_data.service_id, lflag, index, 600 IPC_FF_ROUTE_FROM_ME); 601 async_exchange_end(exch); 602 603 (void) ops->node_put(cur); 604 (void) ops->node_put(tmp); 605 if (par) 606 (void) ops->node_put(par); 607 return; 582 /* Descend one level */ 583 if (par) { 584 rc = ops->node_put(par); 585 if (rc != EOK) { 586 async_answer_0(rid, rc); 587 goto out; 588 } 608 589 } 609 590 610 /* Handle miss: match amongst siblings */ 611 if (!tmp) { 612 if (next <= last) { 613 /* There are unprocessed components */ 614 async_answer_0(rid, ENOENT); 591 par = cur; 592 cur = tmp; 593 tmp = NULL; 594 } 595 596 /* At this point, par is either NULL or a directory. 597 * If cur is NULL, the looked up file does not exist yet. 598 */ 599 600 assert(par == NULL || ops->is_directory(par)); 601 assert(par != NULL || cur != NULL); 602 603 /* Check for some error conditions. */ 604 605 if (cur && (lflag & L_FILE) && (ops->is_directory(cur))) { 606 async_answer_0(rid, EISDIR); 607 goto out; 608 } 609 610 if (cur && (lflag & L_DIRECTORY) && (ops->is_file(cur))) { 611 async_answer_0(rid, ENOTDIR); 612 goto out; 613 } 614 615 /* Unlink. */ 616 617 if (lflag & L_UNLINK) { 618 if (!cur) { 619 async_answer_0(rid, ENOENT); 620 goto out; 621 } 622 if (!par) { 623 async_answer_0(rid, EINVAL); 624 goto out; 625 } 626 627 rc = ops->unlink(par, cur, component); 628 if (rc == EOK) { 629 aoff64_t size = ops->size_get(cur); 630 async_answer_5(rid, fs_handle, service_id, 631 ops->index_get(cur), 632 (ops->is_directory(cur) << 16) | last, 633 LOWER32(size), UPPER32(size)); 634 } else { 635 async_answer_0(rid, rc); 636 } 637 goto out; 638 } 639 640 /* Create. */ 641 642 if (lflag & L_CREATE) { 643 if (cur && (lflag & L_EXCLUSIVE)) { 644 async_answer_0(rid, EEXIST); 645 goto out; 646 } 647 648 if (!cur) { 649 rc = ops->create(&cur, service_id, 650 lflag & (L_FILE | L_DIRECTORY)); 651 if (rc != EOK) { 652 async_answer_0(rid, rc); 653 goto out; 654 } 655 if (!cur) { 656 async_answer_0(rid, ENOSPC); 615 657 goto out; 616 658 } 617 659 618 /* Miss in the last component */ 619 if (lflag & (L_CREATE | L_LINK)) { 620 /* Request to create a new link */ 621 if (!ops->is_directory(cur)) { 622 async_answer_0(rid, ENOTDIR); 623 goto out; 624 } 625 626 fs_node_t *fn; 627 if (lflag & L_CREATE) 628 rc = ops->create(&fn, service_id, 629 lflag); 630 else 631 rc = ops->node_get(&fn, service_id, 632 index); 633 on_error(rc, goto out_with_answer); 634 635 if (fn) { 636 rc = ops->link(cur, fn, component); 637 if (rc != EOK) { 638 if (lflag & L_CREATE) 639 (void) ops->destroy(fn); 640 else 641 (void) ops->node_put(fn); 642 async_answer_0(rid, rc); 643 } else { 644 (void) ops->node_put(cur); 645 cur = fn; 646 goto out_with_answer; 647 } 648 } else 649 async_answer_0(rid, ENOSPC); 650 660 rc = ops->link(par, cur, component); 661 if (rc != EOK) { 662 (void) ops->destroy(cur); 663 cur = NULL; 664 async_answer_0(rid, rc); 651 665 goto out; 652 666 } 653 654 async_answer_0(rid, ENOENT); 655 goto out; 656 } 657 658 if (par) { 659 rc = ops->node_put(par); 660 on_error(rc, goto out_with_answer); 661 } 662 663 /* Descend one level */ 664 par = cur; 665 cur = tmp; 666 tmp = NULL; 667 } 668 669 /* Handle miss: excessive components */ 670 if (next <= last) { 671 bool has_children; 672 rc = ops->has_children(&has_children, cur); 673 on_error(rc, goto out_with_answer); 674 675 if (has_children) 676 goto skip_miss; 677 678 if (lflag & (L_CREATE | L_LINK)) { 679 if (!ops->is_directory(cur)) { 680 async_answer_0(rid, ENOTDIR); 681 goto out; 682 } 683 684 /* Collect next component */ 685 len = 0; 686 while (next <= last) { 687 if (plb_get_char(next) == '/') { 688 /* More than one component */ 689 async_answer_0(rid, ENOENT); 690 goto out; 691 } 692 693 if (len + 1 == NAME_MAX) { 694 /* Component length overflow */ 695 async_answer_0(rid, ENAMETOOLONG); 696 goto out; 697 } 698 699 component[len++] = plb_get_char(next); 700 /* Process next character */ 701 next++; 702 } 703 704 assert(len); 705 component[len] = '\0'; 706 707 fs_node_t *fn; 708 if (lflag & L_CREATE) 709 rc = ops->create(&fn, service_id, lflag); 710 else 711 rc = ops->node_get(&fn, service_id, index); 712 on_error(rc, goto out_with_answer); 713 714 if (fn) { 715 rc = ops->link(cur, fn, component); 716 if (rc != EOK) { 717 if (lflag & L_CREATE) 718 (void) ops->destroy(fn); 719 else 720 (void) ops->node_put(fn); 721 async_answer_0(rid, rc); 722 } else { 723 (void) ops->node_put(cur); 724 cur = fn; 725 goto out_with_answer; 726 } 727 } else 728 async_answer_0(rid, ENOSPC); 729 730 goto out; 731 } 732 733 async_answer_0(rid, ENOENT); 667 } 668 } 669 670 /* Return. */ 671 out1: 672 if (!cur) { 673 async_answer_5(rid, fs_handle, service_id, ops->index_get(par), 674 last_next, -1, true); 734 675 goto out; 735 676 } 736 677 737 skip_miss: 738 739 /* Handle hit */ 740 if (lflag & L_UNLINK) { 741 unsigned int old_lnkcnt = ops->lnkcnt_get(cur); 742 rc = ops->unlink(par, cur, component); 743 744 if (rc == EOK) { 745 aoff64_t size = ops->size_get(cur); 746 async_answer_5(rid, fs_handle, service_id, 747 ops->index_get(cur), LOWER32(size), UPPER32(size), 748 old_lnkcnt); 749 } else 750 async_answer_0(rid, rc); 751 752 goto out; 753 } 754 755 if (((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) || 756 (lflag & L_LINK)) { 757 async_answer_0(rid, EEXIST); 758 goto out; 759 } 760 761 if ((lflag & L_FILE) && (ops->is_directory(cur))) { 762 async_answer_0(rid, EISDIR); 763 goto out; 764 } 765 766 if ((lflag & L_DIRECTORY) && (ops->is_file(cur))) { 767 async_answer_0(rid, ENOTDIR); 768 goto out; 769 } 770 771 if ((lflag & L_ROOT) && par) { 772 async_answer_0(rid, EINVAL); 773 goto out; 774 } 775 776 out_with_answer: 777 778 if (rc == EOK) { 779 if (lflag & L_OPEN) 780 rc = ops->node_open(cur); 781 782 if (rc == EOK) { 783 aoff64_t size = ops->size_get(cur); 784 async_answer_5(rid, fs_handle, service_id, 785 ops->index_get(cur), LOWER32(size), UPPER32(size), 786 ops->lnkcnt_get(cur)); 787 } else 788 async_answer_0(rid, rc); 789 790 } else 791 async_answer_0(rid, rc); 678 aoff64_t size = ops->size_get(cur); 679 async_answer_5(rid, fs_handle, service_id, ops->index_get(cur), 680 (ops->is_directory(cur) << 16) | last, LOWER32(size), 681 UPPER32(size)); 792 682 793 683 out: 794 795 684 if (par) 796 685 (void) ops->node_put(par); … … 862 751 memset(&st, 0, sizeof(struct statfs)); 863 752 753 str_cpy(st.fs_name, sizeof(st.fs_name), fs_name); 754 864 755 if (ops->size_block != NULL) { 865 756 rc = ops->size_block(service_id, &st.f_bsize); … … 919 810 async_answer_4(rid, rc, LOWER32(size), UPPER32(size), 920 811 ops->lnkcnt_get(fn), 921 (ops->is_file(fn) ? L_FILE : 0) | (ops->is_directory(fn) ? L_DIRECTORY : 0)); 812 (ops->is_file(fn) ? L_FILE : 0) | 813 (ops->is_directory(fn) ? L_DIRECTORY : 0)); 922 814 923 815 (void) ops->node_put(fn);
Note:
See TracChangeset
for help on using the changeset viewer.