1 /* 2 * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de> 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <new> 8 9 #include <fs_info.h> 10 #include <fs_interface.h> 11 #include <KernelExport.h> 12 13 #include <vfs.h> 14 15 #include <AutoDeleter.h> 16 17 #include "DebugSupport.h" 18 #include "kernel_interface.h" 19 #include "Node.h" 20 #include "Utils.h" 21 #include "Volume.h" 22 23 24 /*! \brief Binds an arbitrary folder to a given path (which must be that of a 25 folder, too). All requests to the mounted path will be passed to the 26 corresponding node of the bound (source) filesystem. 27 28 TODO: node monitoring! 29 30 TODO: path filter, such that /dev can be bind-mounted with only a subset 31 of entries 32 */ 33 34 35 // #pragma mark - helper macros 36 37 38 #define FETCH_SOURCE_VOLUME_AND_NODE(volume, nodeID) \ 39 fs_volume* sourceVolume = volume->SourceFSVolume(); \ 40 if (sourceVolume == NULL) \ 41 RETURN_ERROR(B_ERROR); \ 42 vnode* sourceVnode; \ 43 status_t error = vfs_get_vnode(volume->SourceFSVolume()->id, \ 44 nodeID, true, &sourceVnode); \ 45 if (error != B_OK) \ 46 RETURN_ERROR(error); \ 47 VnodePutter putter(sourceVnode); \ 48 fs_vnode* sourceNode = vfs_fsnode_for_vnode(sourceVnode); \ 49 if (sourceNode == NULL) \ 50 RETURN_ERROR(B_ERROR); 51 52 53 // #pragma mark - Volume 54 55 56 static status_t 57 bindfs_mount(fs_volume* fsVolume, const char* device, uint32 flags, 58 const char* parameters, ino_t* _rootID) 59 { 60 FUNCTION("fsVolume: %p, device: \"%s\", flags: %#lx, parameters: \"%s\"\n", 61 fsVolume, device, flags, parameters); 62 63 // create a Volume object 64 Volume* volume = new(std::nothrow) Volume(fsVolume); 65 if (volume == NULL) 66 RETURN_ERROR(B_NO_MEMORY); 67 ObjectDeleter<Volume> volumeDeleter(volume); 68 69 status_t error = volume->Mount(parameters); 70 if (error != B_OK) 71 return error; 72 73 // set return values 74 *_rootID = volume->RootNode()->ID(); 75 fsVolume->private_volume = volumeDeleter.Detach(); 76 fsVolume->ops = &gBindFSVolumeOps; 77 78 return B_OK; 79 } 80 81 82 static status_t 83 bindfs_unmount(fs_volume* fsVolume) 84 { 85 Volume* volume = (Volume*)fsVolume->private_volume; 86 87 FUNCTION("volume: %p\n", volume); 88 89 volume->Unmount(); 90 delete volume; 91 92 return B_OK; 93 } 94 95 96 static status_t 97 bindfs_read_fs_info(fs_volume* fsVolume, struct fs_info* info) 98 { 99 Volume* volume = (Volume*)fsVolume->private_volume; 100 101 FUNCTION("volume: %p, info: %p\n", volume, info); 102 103 fs_volume* sourceVolume = volume->SourceFSVolume(); 104 105 if (sourceVolume->ops->read_fs_info != NULL) { 106 status_t error = sourceVolume->ops->read_fs_info(sourceVolume, info); 107 if (error != B_OK) 108 RETURN_ERROR(error); 109 } else { 110 info->block_size = 512; 111 info->io_size = 64 * 1024; 112 } 113 114 info->dev = volume->ID(); 115 info->root = volume->RootNode()->ID(); 116 info->total_blocks = info->free_blocks = 0; 117 info->total_nodes = info->free_nodes = 0; 118 119 strlcpy(info->volume_name, volume->Name(), sizeof(info->volume_name)); 120 121 return B_OK; 122 } 123 124 125 // #pragma mark - VNodes 126 127 128 static status_t 129 bindfs_lookup(fs_volume* fsVolume, fs_vnode* fsDir, const char* entryName, 130 ino_t* _vnid) 131 { 132 Volume* volume = (Volume*)fsVolume->private_volume; 133 Node* node = (Node*)fsDir->private_node; 134 135 FUNCTION("volume: %p, dir: %p (%lld), entry: \"%s\"\n", volume, node, 136 node->ID(), entryName); 137 138 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 139 140 error = sourceNode->ops->lookup(sourceVolume, sourceNode, entryName, _vnid); 141 if (error != B_OK) 142 RETURN_ERROR(error); 143 144 return get_vnode(fsVolume, *_vnid, NULL); 145 } 146 147 148 static status_t 149 bindfs_get_vnode(fs_volume* fsVolume, ino_t vnid, fs_vnode* fsNode, 150 int* _type, uint32* _flags, bool reenter) 151 { 152 Volume* volume = (Volume*)fsVolume->private_volume; 153 154 FUNCTION("volume: %p, vnid: %lld\n", volume, vnid); 155 156 FETCH_SOURCE_VOLUME_AND_NODE(volume, vnid); 157 158 struct stat st; 159 error = sourceNode->ops->read_stat(sourceVolume, sourceNode, &st); 160 161 Node* node = new(std::nothrow) Node(vnid, st.st_mode); 162 if (node == NULL) 163 RETURN_ERROR(B_NO_MEMORY); 164 165 fsNode->private_node = node; 166 fsNode->ops = const_cast<fs_vnode_ops*>(volume->VnodeOps()); 167 *_type = node->Mode() & S_IFMT; 168 *_flags = 0; 169 170 return B_OK; 171 } 172 173 174 static status_t 175 bindfs_get_vnode_name(fs_volume* fsVolume, fs_vnode* fsNode, char* buffer, 176 size_t bufferSize) 177 { 178 Volume* volume = (Volume*)fsVolume->private_volume; 179 Node* node = (Node*)fsNode->private_node; 180 181 FUNCTION("volume: %p, node: %p\n", volume, node); 182 183 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 184 185 return sourceNode->ops->get_vnode_name(sourceVolume, sourceNode, buffer, 186 bufferSize); 187 } 188 189 static status_t 190 bindfs_put_vnode(fs_volume* fsVolume, fs_vnode* fsNode, bool reenter) 191 { 192 Volume* volume = (Volume*)fsVolume->private_volume; 193 Node* node = (Node*)fsNode->private_node; 194 195 FUNCTION("volume: %p, node: %p\n", volume, node); 196 197 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 198 199 delete node; 200 201 return B_OK; 202 } 203 204 205 static status_t 206 bindfs_remove_vnode(fs_volume* fsVolume, fs_vnode* fsNode, bool reenter) 207 { 208 Volume* volume = (Volume*)fsVolume->private_volume; 209 Node* node = (Node*)fsNode->private_node; 210 211 FUNCTION("volume: %p, node: %p\n", volume, node); 212 213 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 214 215 delete node; 216 217 return sourceNode->ops->remove_vnode(sourceVolume, sourceNode, reenter); 218 } 219 220 221 // #pragma mark - VM access 222 223 224 static bool 225 bindfs_can_page(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie) 226 { 227 Volume* volume = (Volume*)fsVolume->private_volume; 228 Node* node = (Node*)fsNode->private_node; 229 230 FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, 231 node, node->ID(), cookie); 232 233 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 234 235 return sourceNode->ops->can_page(sourceVolume, sourceNode, cookie); 236 } 237 238 239 static status_t 240 bindfs_read_pages(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, 241 off_t pos, const iovec* vecs, size_t count, size_t* _numBytes) 242 { 243 Volume* volume = (Volume*)fsVolume->private_volume; 244 Node* node = (Node*)fsNode->private_node; 245 246 FUNCTION("volume: %p, node: %p (%lld), cookie: %p, pos: %lld, vecs: %p, " 247 "count: %ld\n", 248 volume, node, node->ID(), cookie, pos, vecs, count); 249 250 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 251 252 return sourceNode->ops->read_pages(sourceVolume, sourceNode, cookie, pos, 253 vecs, count, _numBytes); 254 } 255 256 257 static status_t 258 bindfs_write_pages(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, 259 off_t pos, const iovec* vecs, size_t count, size_t* _numBytes) 260 { 261 Volume* volume = (Volume*)fsVolume->private_volume; 262 Node* node = (Node*)fsNode->private_node; 263 264 FUNCTION("volume: %p, node: %p (%lld), cookie: %p, pos: %lld, vecs: %p, " 265 "count: %ld\n", 266 volume, node, node->ID(), cookie, pos, vecs, count); 267 268 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 269 270 return sourceNode->ops->write_pages(sourceVolume, sourceNode, cookie, pos, 271 vecs, count, _numBytes); 272 } 273 274 275 // #pragma mark - Request I/O 276 277 278 static status_t 279 bindfs_io(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, 280 io_request* request) 281 { 282 Volume* volume = (Volume*)fsVolume->private_volume; 283 Node* node = (Node*)fsNode->private_node; 284 285 FUNCTION("volume: %p, node: %p (%lld), cookie: %p, request: %p\n", volume, 286 node, node->ID(), cookie, request); 287 288 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 289 290 return sourceNode->ops->io(sourceVolume, sourceNode, cookie, request); 291 } 292 293 294 static status_t 295 bindfs_cancel_io(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, 296 io_request* request) 297 { 298 Volume* volume = (Volume*)fsVolume->private_volume; 299 Node* node = (Node*)fsNode->private_node; 300 301 FUNCTION("volume: %p, node: %p (%lld), cookie: %p, request: %p\n", volume, 302 node, node->ID(), cookie, request); 303 304 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 305 306 return sourceNode->ops->cancel_io(sourceVolume, sourceNode, cookie, 307 request); 308 } 309 310 311 // #pragma mark - File Map 312 313 314 static status_t 315 bindfs_get_file_map(fs_volume* fsVolume, fs_vnode* fsNode, off_t offset, 316 size_t size, struct file_io_vec* vecs, size_t* _count) 317 { 318 Volume* volume = (Volume*)fsVolume->private_volume; 319 Node* node = (Node*)fsNode->private_node; 320 321 FUNCTION("volume: %p, node: %p (%lld), offset: %lld, size: %ld, vecs: %p\n", 322 volume, node, node->ID(), offset, size, vecs); 323 324 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 325 326 return sourceNode->ops->get_file_map(sourceVolume, sourceNode, offset, size, 327 vecs, _count); 328 } 329 330 331 // #pragma mark - Special 332 333 334 static status_t 335 bindfs_ioctl(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, uint32 op, 336 void* buffer, size_t length) 337 { 338 Volume* volume = (Volume*)fsVolume->private_volume; 339 Node* node = (Node*)fsNode->private_node; 340 341 FUNCTION("volume: %p, node: %p (%lld), cookie: %p, op: %lx, buffer: %p, " 342 "length: %ld\n", 343 volume, node, node->ID(), cookie, op, buffer, length); 344 345 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 346 347 return sourceNode->ops->ioctl(sourceVolume, sourceNode, cookie, op, buffer, 348 length); 349 } 350 351 352 static status_t 353 bindfs_set_flags(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, int flags) 354 { 355 Volume* volume = (Volume*)fsVolume->private_volume; 356 Node* node = (Node*)fsNode->private_node; 357 358 FUNCTION("volume: %p, node: %p (%lld), cookie: %p, flags: %x\n", 359 volume, node, node->ID(), cookie, flags); 360 361 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 362 363 return sourceNode->ops->set_flags(sourceVolume, sourceNode, cookie, flags); 364 } 365 366 367 static status_t 368 bindfs_select(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, uint8 event, 369 selectsync* sync) 370 { 371 Volume* volume = (Volume*)fsVolume->private_volume; 372 Node* node = (Node*)fsNode->private_node; 373 374 FUNCTION("volume: %p, node: %p (%lld), cookie: %p, event: %x, sync: %p\n", 375 volume, node, node->ID(), cookie, event, sync); 376 377 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 378 379 return sourceNode->ops->select(sourceVolume, sourceNode, cookie, event, 380 sync); 381 } 382 383 384 static status_t 385 bindfs_deselect(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, 386 uint8 event, selectsync* sync) 387 { 388 Volume* volume = (Volume*)fsVolume->private_volume; 389 Node* node = (Node*)fsNode->private_node; 390 391 FUNCTION("volume: %p, node: %p (%lld), cookie: %p, event: %x, sync: %p\n", 392 volume, node, node->ID(), cookie, event, sync); 393 394 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 395 396 return sourceNode->ops->deselect(sourceVolume, sourceNode, cookie, event, 397 sync); 398 } 399 400 401 static status_t 402 bindfs_fsync(fs_volume* fsVolume, fs_vnode* fsNode) 403 { 404 Volume* volume = (Volume*)fsVolume->private_volume; 405 Node* node = (Node*)fsNode->private_node; 406 407 FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID()); 408 409 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 410 411 return sourceNode->ops->fsync(sourceVolume, sourceNode); 412 } 413 414 415 // #pragma mark - Nodes 416 417 418 static status_t 419 bindfs_read_symlink(fs_volume* fsVolume, fs_vnode* fsNode, char* buffer, 420 size_t* _bufferSize) 421 { 422 Volume* volume = (Volume*)fsVolume->private_volume; 423 Node* node = (Node*)fsNode->private_node; 424 425 FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID()); 426 427 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 428 429 return sourceNode->ops->read_symlink(sourceVolume, sourceNode, buffer, 430 _bufferSize); 431 } 432 433 434 static status_t 435 bindfs_create_symlink(fs_volume* fsVolume, fs_vnode* fsNode, const char* name, 436 const char* path, int mode) 437 { 438 Volume* volume = (Volume*)fsVolume->private_volume; 439 Node* node = (Node*)fsNode->private_node; 440 441 FUNCTION("volume: %p, node: %p (%lld), name: %s, path: %s, mode: %x\n", 442 volume, node, node->ID(), name, path, mode); 443 444 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 445 446 return sourceNode->ops->create_symlink(sourceVolume, sourceNode, name, path, 447 mode); 448 } 449 450 451 static status_t 452 bindfs_link(fs_volume* fsVolume, fs_vnode* fsNode, const char* name, 453 fs_vnode* toNode) 454 { 455 Volume* volume = (Volume*)fsVolume->private_volume; 456 Node* node = (Node*)fsNode->private_node; 457 458 FUNCTION("volume: %p, node: %p (%lld), name: %s, tonode: %p\n", 459 volume, node, node->ID(), name, toNode); 460 461 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 462 463 return sourceNode->ops->link(sourceVolume, sourceNode, name, toNode); 464 } 465 466 467 static status_t 468 bindfs_unlink(fs_volume* fsVolume, fs_vnode* fsNode, const char* name) 469 { 470 Volume* volume = (Volume*)fsVolume->private_volume; 471 Node* node = (Node*)fsNode->private_node; 472 473 FUNCTION("volume: %p, node: %p (%lld), name: %s\n", 474 volume, node, node->ID(), name); 475 476 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 477 478 return sourceNode->ops->unlink(sourceVolume, sourceNode, name); 479 } 480 481 482 static status_t 483 bindfs_rename(fs_volume* fsVolume, fs_vnode* fsNode, const char* fromName, 484 fs_vnode* toDir, const char* toName) 485 { 486 Volume* volume = (Volume*)fsVolume->private_volume; 487 Node* node = (Node*)fsNode->private_node; 488 489 FUNCTION("volume: %p, node: %p (%lld), from: %s, toDir: %p, to: %s\n", 490 volume, node, node->ID(), fromName, toDir, toName); 491 492 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 493 494 return sourceNode->ops->rename(sourceVolume, sourceNode, fromName, toDir, 495 toName); 496 } 497 498 499 static status_t 500 bindfs_access(fs_volume* fsVolume, fs_vnode* fsNode, int mode) 501 { 502 Volume* volume = (Volume*)fsVolume->private_volume; 503 Node* node = (Node*)fsNode->private_node; 504 505 FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID()); 506 507 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 508 509 return sourceNode->ops->access(sourceVolume, sourceNode, mode); 510 } 511 512 513 static status_t 514 bindfs_read_stat(fs_volume* fsVolume, fs_vnode* fsNode, struct stat* st) 515 { 516 Volume* volume = (Volume*)fsVolume->private_volume; 517 Node* node = (Node*)fsNode->private_node; 518 519 FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID()); 520 521 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 522 523 error = sourceNode->ops->read_stat(sourceVolume, sourceNode, st); 524 if (error != B_OK) 525 RETURN_ERROR(error); 526 527 st->st_dev = volume->ID(); 528 529 return B_OK; 530 } 531 532 533 static status_t 534 bindfs_write_stat(fs_volume* fsVolume, fs_vnode* fsNode, 535 const struct stat* _st, uint32 statMask) 536 { 537 Volume* volume = (Volume*)fsVolume->private_volume; 538 Node* node = (Node*)fsNode->private_node; 539 540 FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID()); 541 542 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 543 544 struct stat st; 545 memcpy(&st, _st, sizeof(st)); 546 st.st_dev = sourceVolume->id; 547 548 return sourceNode->ops->write_stat(sourceVolume, sourceNode, &st, statMask); 549 } 550 551 552 static status_t 553 bindfs_preallocate(fs_volume* fsVolume, fs_vnode* fsNode, off_t pos, 554 off_t length) 555 { 556 Volume* volume = (Volume*)fsVolume->private_volume; 557 Node* node = (Node*)fsNode->private_node; 558 559 FUNCTION("volume: %p, node: %p (%lld), pos: %lld, length: %lld\n", 560 volume, node, node->ID(), pos, length); 561 562 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 563 564 return sourceNode->ops->preallocate(sourceVolume, sourceNode, pos, length); 565 } 566 567 568 // #pragma mark - Files 569 570 571 static status_t 572 bindfs_create(fs_volume* fsVolume, fs_vnode* fsNode, const char* name, 573 int openMode, int perms, void** _cookie, ino_t* _newVnodeID) 574 { 575 Volume* volume = (Volume*)fsVolume->private_volume; 576 Node* node = (Node*)fsNode->private_node; 577 578 FUNCTION("volume: %p, node: %p (%lld), name: %s, openMode %#x, perms: %x\n", 579 volume, node, node->ID(), name, openMode, perms); 580 581 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 582 583 return sourceNode->ops->create(sourceVolume, sourceNode, name, openMode, 584 perms, _cookie, _newVnodeID); 585 } 586 587 588 static status_t 589 bindfs_open(fs_volume* fsVolume, fs_vnode* fsNode, int openMode, 590 void** _cookie) 591 { 592 Volume* volume = (Volume*)fsVolume->private_volume; 593 Node* node = (Node*)fsNode->private_node; 594 595 FUNCTION("volume: %p, node: %p (%lld), openMode %#x\n", volume, node, 596 node->ID(), openMode); 597 598 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 599 600 return sourceNode->ops->open(sourceVolume, sourceNode, openMode, _cookie); 601 } 602 603 604 static status_t 605 bindfs_close(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie) 606 { 607 Volume* volume = (Volume*)fsVolume->private_volume; 608 Node* node = (Node*)fsNode->private_node; 609 610 FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node, 611 node->ID(), cookie); 612 613 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 614 615 return sourceNode->ops->close(sourceVolume, sourceNode, cookie); 616 } 617 618 619 static status_t 620 bindfs_free_cookie(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie) 621 { 622 Volume* volume = (Volume*)fsVolume->private_volume; 623 Node* node = (Node*)fsNode->private_node; 624 625 FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node, 626 node->ID(), cookie); 627 628 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 629 630 return sourceNode->ops->free_cookie(sourceVolume, sourceNode, cookie); 631 } 632 633 634 static status_t 635 bindfs_read(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, 636 off_t offset, void* buffer, size_t* bufferSize) 637 { 638 Volume* volume = (Volume*)fsVolume->private_volume; 639 Node* node = (Node*)fsNode->private_node; 640 641 FUNCTION("volume: %p, node: %p (%lld), cookie: %p, offset: %lld, " 642 "buffer: %p, size: %lu\n", volume, node, node->ID(), cookie, offset, 643 buffer, *bufferSize); 644 645 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 646 647 return sourceNode->ops->read(sourceVolume, sourceNode, cookie, offset, 648 buffer, bufferSize); 649 } 650 651 652 static status_t 653 bindfs_write(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, 654 off_t offset, const void* buffer, size_t* bufferSize) 655 { 656 Volume* volume = (Volume*)fsVolume->private_volume; 657 Node* node = (Node*)fsNode->private_node; 658 659 FUNCTION("volume: %p, node: %p (%lld), cookie: %p, offset: %lld, " 660 "buffer: %p, size: %lu\n", volume, node, node->ID(), cookie, offset, 661 buffer, *bufferSize); 662 663 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 664 665 return sourceNode->ops->write(sourceVolume, sourceNode, cookie, offset, 666 buffer, bufferSize); 667 } 668 669 670 // #pragma mark - Directories 671 672 673 static status_t 674 bindfs_create_dir(fs_volume* fsVolume, fs_vnode* fsNode, const char* name, 675 int perms) 676 { 677 Volume* volume = (Volume*)fsVolume->private_volume; 678 Node* node = (Node*)fsNode->private_node; 679 680 FUNCTION("volume: %p, node: %p (%lld), name: %s, perms: %x\n", volume, node, 681 node->ID(), name, perms); 682 683 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 684 685 return sourceNode->ops->create_dir(sourceVolume, sourceNode, name, perms); 686 } 687 688 689 static status_t 690 bindfs_remove_dir(fs_volume* fsVolume, fs_vnode* fsNode, const char* name) 691 { 692 Volume* volume = (Volume*)fsVolume->private_volume; 693 Node* node = (Node*)fsNode->private_node; 694 695 FUNCTION("volume: %p, node: %p (%lld), name: %s\n", volume, node, 696 node->ID(), name); 697 698 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 699 700 return sourceNode->ops->remove_dir(sourceVolume, sourceNode, name); 701 } 702 703 704 static status_t 705 bindfs_open_dir(fs_volume* fsVolume, fs_vnode* fsNode, void** _cookie) 706 { 707 Volume* volume = (Volume*)fsVolume->private_volume; 708 Node* node = (Node*)fsNode->private_node; 709 710 FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID()); 711 712 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 713 714 return sourceNode->ops->open_dir(sourceVolume, sourceNode, _cookie); 715 } 716 717 718 static status_t 719 bindfs_close_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie) 720 { 721 Volume* volume = (Volume*)fsVolume->private_volume; 722 Node* node = (Node*)fsNode->private_node; 723 724 FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node, 725 node->ID(), cookie); 726 727 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 728 729 return sourceNode->ops->close_dir(sourceVolume, sourceNode, cookie); 730 } 731 732 733 static status_t 734 bindfs_free_dir_cookie(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie) 735 { 736 Volume* volume = (Volume*)fsVolume->private_volume; 737 Node* node = (Node*)fsNode->private_node; 738 739 FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node, 740 node->ID(), cookie); 741 742 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 743 744 return sourceNode->ops->free_dir_cookie(sourceVolume, sourceNode, cookie); 745 } 746 747 748 static status_t 749 bindfs_read_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, 750 struct dirent* buffer, size_t bufferSize, uint32* _count) 751 { 752 Volume* volume = (Volume*)fsVolume->private_volume; 753 Node* node = (Node*)fsNode->private_node; 754 755 FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node, 756 node->ID(), cookie); 757 758 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 759 760 return sourceNode->ops->read_dir(sourceVolume, sourceNode, cookie, buffer, 761 bufferSize, _count); 762 } 763 764 765 static status_t 766 bindfs_rewind_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie) 767 { 768 Volume* volume = (Volume*)fsVolume->private_volume; 769 Node* node = (Node*)fsNode->private_node; 770 771 FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node, 772 node->ID(), cookie); 773 774 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 775 776 return sourceNode->ops->rewind_dir(sourceVolume, sourceNode, cookie); 777 } 778 779 780 // #pragma mark - Attribute Directories 781 782 783 status_t 784 bindfs_open_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void** _cookie) 785 { 786 Volume* volume = (Volume*)fsVolume->private_volume; 787 Node* node = (Node*)fsNode->private_node; 788 789 FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID()); 790 791 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 792 793 return sourceNode->ops->open_attr_dir(sourceVolume, sourceNode, _cookie); 794 } 795 796 797 status_t 798 bindfs_close_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie) 799 { 800 Volume* volume = (Volume*)fsVolume->private_volume; 801 Node* node = (Node*)fsNode->private_node; 802 803 FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node, 804 node->ID(), cookie); 805 806 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 807 808 return sourceNode->ops->close_attr_dir(sourceVolume, sourceNode, cookie); 809 } 810 811 812 status_t 813 bindfs_free_attr_dir_cookie(fs_volume* fsVolume, fs_vnode* fsNode, 814 void* cookie) 815 { 816 Volume* volume = (Volume*)fsVolume->private_volume; 817 Node* node = (Node*)fsNode->private_node; 818 819 FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node, 820 node->ID(), cookie); 821 822 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 823 824 return sourceNode->ops->free_attr_dir_cookie(sourceVolume, sourceNode, 825 cookie); 826 } 827 828 829 status_t 830 bindfs_read_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, 831 struct dirent* buffer, size_t bufferSize, uint32* _count) 832 { 833 Volume* volume = (Volume*)fsVolume->private_volume; 834 Node* node = (Node*)fsNode->private_node; 835 836 FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node, 837 node->ID(), cookie); 838 839 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 840 841 return sourceNode->ops->read_attr_dir(sourceVolume, sourceNode, cookie, 842 buffer, bufferSize, _count); 843 } 844 845 846 status_t 847 bindfs_rewind_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie) 848 { 849 Volume* volume = (Volume*)fsVolume->private_volume; 850 Node* node = (Node*)fsNode->private_node; 851 852 FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node, 853 node->ID(), cookie); 854 855 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 856 857 return sourceNode->ops->rewind_attr_dir(sourceVolume, sourceNode, cookie); 858 } 859 860 861 // #pragma mark - Attribute Operations 862 863 864 status_t 865 bindfs_create_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* name, 866 uint32 type, int openMode, void** _cookie) 867 { 868 Volume* volume = (Volume*)fsVolume->private_volume; 869 Node* node = (Node*)fsNode->private_node; 870 871 FUNCTION("volume: %p, node: %p (%lld), name: \"%s\", type: %lx, " 872 "openMode %#x\n", 873 volume, node, node->ID(), name, type, openMode); 874 875 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 876 877 return sourceNode->ops->create_attr(sourceVolume, sourceNode, name, type, 878 openMode, _cookie); 879 } 880 881 882 status_t 883 bindfs_open_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* name, 884 int openMode, void** _cookie) 885 { 886 Volume* volume = (Volume*)fsVolume->private_volume; 887 Node* node = (Node*)fsNode->private_node; 888 889 FUNCTION("volume: %p, node: %p (%lld), name: \"%s\", openMode %#x\n", 890 volume, node, node->ID(), name, openMode); 891 892 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 893 894 return sourceNode->ops->open_attr(sourceVolume, sourceNode, name, openMode, 895 _cookie); 896 } 897 898 899 status_t 900 bindfs_close_attr(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie) 901 { 902 Volume* volume = (Volume*)fsVolume->private_volume; 903 Node* node = (Node*)fsNode->private_node; 904 905 FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node, 906 node->ID(), cookie); 907 908 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 909 910 return sourceNode->ops->close_attr(sourceVolume, sourceNode, cookie); 911 } 912 913 914 status_t 915 bindfs_free_attr_cookie(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie) 916 { 917 Volume* volume = (Volume*)fsVolume->private_volume; 918 Node* node = (Node*)fsNode->private_node; 919 920 FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node, 921 node->ID(), cookie); 922 923 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 924 925 return sourceNode->ops->free_attr_cookie(sourceVolume, sourceNode, cookie); 926 } 927 928 929 status_t 930 bindfs_read_attr(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, 931 off_t offset, void* buffer, size_t* bufferSize) 932 { 933 Volume* volume = (Volume*)fsVolume->private_volume; 934 Node* node = (Node*)fsNode->private_node; 935 936 FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node, 937 node->ID(), cookie); 938 939 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 940 941 return sourceNode->ops->read_attr(sourceVolume, sourceNode, cookie, offset, 942 buffer, bufferSize); 943 } 944 945 946 status_t 947 bindfs_write_attr(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, 948 off_t offset, const void* buffer, size_t* bufferSize) 949 { 950 Volume* volume = (Volume*)fsVolume->private_volume; 951 Node* node = (Node*)fsNode->private_node; 952 953 FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node, 954 node->ID(), cookie); 955 956 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 957 958 return sourceNode->ops->write_attr(sourceVolume, sourceNode, cookie, offset, 959 buffer, bufferSize); 960 } 961 962 963 status_t 964 bindfs_read_attr_stat(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, 965 struct stat* st) 966 { 967 Volume* volume = (Volume*)fsVolume->private_volume; 968 Node* node = (Node*)fsNode->private_node; 969 970 FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node, 971 node->ID(), cookie); 972 973 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 974 975 error 976 = sourceNode->ops->read_attr_stat(sourceVolume, sourceNode, cookie, st); 977 if (error != B_OK) 978 RETURN_ERROR(error); 979 980 st->st_dev = volume->ID(); 981 982 return B_OK; 983 } 984 985 986 status_t 987 bindfs_write_attr_stat(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, 988 const struct stat* _st, int statMask) 989 { 990 Volume* volume = (Volume*)fsVolume->private_volume; 991 Node* node = (Node*)fsNode->private_node; 992 993 FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node, 994 node->ID(), cookie); 995 996 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 997 998 struct stat st; 999 memcpy(&st, _st, sizeof(st)); 1000 st.st_dev = sourceVolume->id; 1001 1002 return sourceNode->ops->write_attr_stat(sourceVolume, sourceNode, cookie, 1003 &st, statMask); 1004 } 1005 1006 1007 static status_t 1008 bindfs_rename_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* fromName, 1009 fs_vnode* toDir, const char* toName) 1010 { 1011 Volume* volume = (Volume*)fsVolume->private_volume; 1012 Node* node = (Node*)fsNode->private_node; 1013 1014 FUNCTION("volume: %p, node: %p (%lld), from: %s, toDir: %p, to: %s\n", 1015 volume, node, node->ID(), fromName, toDir, toName); 1016 1017 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 1018 1019 return sourceNode->ops->rename_attr(sourceVolume, sourceNode, fromName, 1020 toDir, toName); 1021 } 1022 1023 1024 static status_t 1025 bindfs_remove_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* name) 1026 { 1027 Volume* volume = (Volume*)fsVolume->private_volume; 1028 Node* node = (Node*)fsNode->private_node; 1029 1030 FUNCTION("volume: %p, node: %p (%lld), name: %s\n", volume, node, 1031 node->ID(), name); 1032 1033 FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID()); 1034 1035 return sourceNode->ops->remove_attr(sourceVolume, sourceNode, name); 1036 } 1037 1038 1039 // #pragma mark - Module Interface 1040 1041 1042 static status_t 1043 bindfs_std_ops(int32 op, ...) 1044 { 1045 switch (op) { 1046 case B_MODULE_INIT: 1047 { 1048 init_debugging(); 1049 PRINT("bindfs_std_ops(): B_MODULE_INIT\n"); 1050 1051 return B_OK; 1052 } 1053 1054 case B_MODULE_UNINIT: 1055 { 1056 PRINT("bind_std_ops(): B_MODULE_UNINIT\n"); 1057 exit_debugging(); 1058 return B_OK; 1059 } 1060 1061 default: 1062 return B_ERROR; 1063 } 1064 } 1065 1066 1067 static file_system_module_info sBindFSModuleInfo = { 1068 { 1069 "file_systems/bindfs" B_CURRENT_FS_API_VERSION, 1070 0, 1071 bindfs_std_ops, 1072 }, 1073 1074 "bindfs", // short_name 1075 "Bind File System", // pretty_name 1076 0, // DDM flags 1077 1078 1079 // scanning 1080 NULL, // identify_partition, 1081 NULL, // scan_partition, 1082 NULL, // free_identify_partition_cookie, 1083 NULL, // free_partition_content_cookie() 1084 1085 &bindfs_mount 1086 }; 1087 1088 1089 fs_volume_ops gBindFSVolumeOps = { 1090 &bindfs_unmount, 1091 &bindfs_read_fs_info, 1092 NULL, // write_fs_info, 1093 NULL, // sync, 1094 1095 &bindfs_get_vnode 1096 1097 // TODO: index operations 1098 // TODO: query operations 1099 // TODO: FS layer operations 1100 }; 1101 1102 1103 fs_vnode_ops gBindFSVnodeOps = { 1104 // vnode operations 1105 &bindfs_lookup, 1106 &bindfs_get_vnode_name, 1107 &bindfs_put_vnode, 1108 &bindfs_remove_vnode, 1109 1110 // VM file access 1111 &bindfs_can_page, 1112 &bindfs_read_pages, 1113 &bindfs_write_pages, 1114 1115 &bindfs_io, 1116 &bindfs_cancel_io, 1117 1118 &bindfs_get_file_map, 1119 1120 &bindfs_ioctl, 1121 &bindfs_set_flags, 1122 &bindfs_select, 1123 &bindfs_deselect, 1124 &bindfs_fsync, 1125 1126 &bindfs_read_symlink, 1127 &bindfs_create_symlink, 1128 1129 &bindfs_link, 1130 &bindfs_unlink, 1131 &bindfs_rename, 1132 1133 &bindfs_access, 1134 &bindfs_read_stat, 1135 &bindfs_write_stat, 1136 &bindfs_preallocate, 1137 1138 // file operations 1139 &bindfs_create, 1140 &bindfs_open, 1141 &bindfs_close, 1142 &bindfs_free_cookie, 1143 &bindfs_read, 1144 &bindfs_write, 1145 1146 // directory operations 1147 &bindfs_create_dir, 1148 &bindfs_remove_dir, 1149 &bindfs_open_dir, 1150 &bindfs_close_dir, 1151 &bindfs_free_dir_cookie, 1152 &bindfs_read_dir, 1153 &bindfs_rewind_dir, 1154 1155 // attribute directory operations 1156 &bindfs_open_attr_dir, 1157 &bindfs_close_attr_dir, 1158 &bindfs_free_attr_dir_cookie, 1159 &bindfs_read_attr_dir, 1160 &bindfs_rewind_attr_dir, 1161 1162 // attribute operations 1163 &bindfs_create_attr, 1164 &bindfs_open_attr, 1165 &bindfs_close_attr, 1166 &bindfs_free_attr_cookie, 1167 &bindfs_read_attr, 1168 &bindfs_write_attr, 1169 1170 &bindfs_read_attr_stat, 1171 &bindfs_write_attr_stat, 1172 &bindfs_rename_attr, 1173 &bindfs_remove_attr, 1174 1175 // TODO: FS layer operations 1176 }; 1177 1178 1179 module_info *modules[] = { 1180 (module_info *)&sBindFSModuleInfo, 1181 NULL, 1182 }; 1183