1 /* 2 * Copyright 2001-2017, Axel Dörfler, axeld@pinc-software.de. 3 * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com 4 * All rights reserved. Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "system_dependencies.h" 9 #include "Directory.h" 10 #include "Inode.h" 11 #include "Volume.h" 12 13 14 #define XFS_IO_SIZE 65536 15 16 struct identify_cookie 17 { 18 /* super_block_struct super_block; 19 * No structure yet implemented. 20 */ 21 int cookie; 22 }; 23 24 25 //! xfs_io() callback hook 26 static status_t 27 iterative_io_get_vecs_hook(void *cookie, io_request *request, off_t offset, 28 size_t size, struct file_io_vec *vecs, size_t *_count) 29 { 30 return B_NOT_SUPPORTED; 31 } 32 33 34 //! xfs_io() callback hook 35 static status_t 36 iterative_io_finished_hook(void *cookie, io_request *request, status_t status, 37 bool partialTransfer, size_t bytesTransferred) 38 { 39 return B_NOT_SUPPORTED; 40 } 41 42 43 // #pragma mark - Scanning 44 45 46 static float 47 xfs_identify_partition(int fd, partition_data *partition, void **_cookie) 48 { 49 return B_NOT_SUPPORTED; 50 } 51 52 53 static status_t 54 xfs_scan_partition(int fd, partition_data *partition, void *_cookie) 55 { 56 return B_NOT_SUPPORTED; 57 } 58 59 60 static void 61 xfs_free_identify_partition_cookie(partition_data *partition, void *_cookie) 62 { 63 dprintf("Unsupported in XFS currently.\n"); 64 return; 65 } 66 67 68 // #pragma mark - 69 70 71 static status_t 72 xfs_mount(fs_volume *_volume, const char *device, uint32 flags, 73 const char *args, ino_t *_rootID) 74 { 75 TRACE("xfs_mount(): Trying to mount\n"); 76 77 Volume *volume = new (std::nothrow) Volume(_volume); 78 if (volume == NULL) 79 return B_NO_MEMORY; 80 81 _volume->private_volume = volume; 82 _volume->ops = &gxfsVolumeOps; 83 84 status_t status = volume->Mount(device, flags); 85 if (status != B_OK) { 86 ERROR("Failed mounting the volume. Error: %s\n", strerror(status)); 87 delete volume; 88 _volume->private_volume = NULL; 89 return status; 90 } 91 92 *_rootID = volume->Root(); 93 return B_OK; 94 } 95 96 97 static status_t 98 xfs_unmount(fs_volume *_volume) 99 { 100 Volume* volume = (Volume*) _volume->private_volume; 101 102 status_t status = volume->Unmount(); 103 delete volume; 104 TRACE("xfs_unmount(): Deleted volume"); 105 return status; 106 } 107 108 109 static status_t 110 xfs_read_fs_info(fs_volume *_volume, struct fs_info *info) 111 { 112 TRACE("XFS_READ_FS_INFO:\n"); 113 Volume* volume = (Volume*)_volume->private_volume; 114 115 info->flags = B_FS_IS_READONLY 116 | B_FS_HAS_ATTR | B_FS_IS_PERSISTENT; 117 118 info->io_size = XFS_IO_SIZE; 119 info->block_size = volume->SuperBlock().BlockSize(); 120 info->total_blocks = volume->SuperBlock().TotalBlocks(); 121 info->free_blocks = volume->SuperBlock().FreeBlocks(); 122 123 strlcpy(info->volume_name, volume->Name(), sizeof(info->volume_name)); 124 strlcpy(info->fsh_name, "xfs", sizeof(info->fsh_name)); 125 126 return B_OK; 127 } 128 129 130 // #pragma mark - 131 132 133 static status_t 134 xfs_get_vnode(fs_volume *_volume, ino_t id, fs_vnode *_node, int *_type, 135 uint32 *_flags, bool reenter) 136 { 137 TRACE("XFS_GET_VNODE:\n"); 138 Volume* volume = (Volume*)_volume->private_volume; 139 140 Inode* inode = new(std::nothrow) Inode(volume, id); 141 if (inode == NULL) 142 return B_NO_MEMORY; 143 144 status_t status = inode->Init(); 145 if (status != B_OK) { 146 delete inode; 147 ERROR("get_vnode: InitCheck() failed. Error: %s\n", strerror(status)); 148 return B_NO_INIT; 149 } 150 151 _node->private_node = inode; 152 _node->ops = &gxfsVnodeOps; 153 *_type = inode->Mode(); 154 *_flags = 0; 155 TRACE("(%ld)\n", inode->ID()); 156 return B_OK; 157 } 158 159 160 static status_t 161 xfs_put_vnode(fs_volume *_volume, fs_vnode *_node, bool reenter) 162 { 163 TRACE("XFS_PUT_VNODE:\n"); 164 delete (Inode*)_node->private_node; 165 return B_OK; 166 } 167 168 169 static bool 170 xfs_can_page(fs_volume *_volume, fs_vnode *_node, void *_cookie) 171 { 172 return B_NOT_SUPPORTED; 173 } 174 175 176 static status_t 177 xfs_read_pages(fs_volume *_volume, fs_vnode *_node, void *_cookie, 178 off_t pos, const iovec *vecs, size_t count, size_t *_numBytes) 179 { 180 return B_NOT_SUPPORTED; 181 } 182 183 184 static status_t 185 xfs_io(fs_volume *_volume, fs_vnode *_node, void *_cookie, 186 io_request *request) 187 { 188 return B_NOT_SUPPORTED; 189 } 190 191 192 static status_t 193 xfs_get_file_map(fs_volume *_volume, fs_vnode *_node, off_t offset, 194 size_t size, struct file_io_vec *vecs, size_t *_count) 195 { 196 return B_NOT_SUPPORTED; 197 } 198 199 200 // #pragma mark - 201 202 203 static status_t 204 xfs_lookup(fs_volume *_volume, fs_vnode *_directory, const char *name, 205 ino_t *_vnodeID) 206 { 207 TRACE("XFS_LOOKUP: %p (%s)\n", name, name); 208 Volume* volume = (Volume*)_volume->private_volume; 209 Inode* directory = (Inode*)_directory->private_node; 210 211 if (!directory->IsDirectory()) 212 return B_NOT_A_DIRECTORY; 213 214 status_t status = directory->CheckPermissions(X_OK); 215 if (status < B_OK) 216 return status; 217 218 DirectoryIterator* iterator = 219 new(std::nothrow) DirectoryIterator(directory); 220 if (iterator == NULL) 221 return B_NO_MEMORY; 222 223 status = iterator->Init(); 224 if (status != B_OK) { 225 delete iterator; 226 return status; 227 } 228 229 status = iterator->Lookup(name, strlen(name), (xfs_ino_t*)_vnodeID); 230 if (status != B_OK) { 231 delete iterator; 232 return status; 233 } 234 235 TRACE("XFS_LOOKUP: ID: (%ld)\n", *_vnodeID); 236 status = get_vnode(volume->FSVolume(), *_vnodeID, NULL); 237 TRACE("get_vnode status: (%d)\n", status); 238 return status; 239 } 240 241 242 static status_t 243 xfs_ioctl(fs_volume *_volume, fs_vnode *_node, void *_cookie, uint32 cmd, 244 void *buffer, size_t bufferLength) 245 { 246 return B_NOT_SUPPORTED; 247 } 248 249 250 static status_t 251 xfs_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat) 252 { 253 Inode* inode = (Inode*)_node->private_node; 254 TRACE("XFS_READ_STAT: id: (%ld)\n", inode->ID()); 255 stat->st_dev = inode->GetVolume()->ID(); 256 stat->st_ino = inode->ID(); 257 stat->st_nlink = 1; 258 stat->st_blksize = XFS_IO_SIZE; 259 260 stat->st_uid = inode->UserId(); 261 stat->st_gid = inode->GroupId(); 262 stat->st_mode = inode->Mode(); 263 stat->st_type = 0; // TODO 264 265 stat->st_size = inode->Size(); 266 stat->st_blocks = inode->BlockCount(); 267 268 inode->GetAccessTime(stat->st_atim); 269 inode->GetModificationTime(stat->st_mtim); 270 inode->GetChangeTime(stat->st_ctim); 271 272 /* TODO: Can we obtain the Creation Time in v4 system? */ 273 inode->GetChangeTime(stat->st_crtim); 274 275 return B_OK; 276 277 } 278 279 280 static status_t 281 xfs_open(fs_volume * /*_volume*/, fs_vnode *_node, int openMode, 282 void **_cookie) 283 { 284 return B_NOT_SUPPORTED; 285 } 286 287 288 static status_t 289 xfs_read(fs_volume *_volume, fs_vnode *_node, void *_cookie, off_t pos, 290 void *buffer, size_t *_length) 291 { 292 return B_NOT_SUPPORTED; 293 } 294 295 296 static status_t 297 xfs_close(fs_volume *_volume, fs_vnode *_node, void *_cookie) 298 { 299 return B_NOT_SUPPORTED; 300 } 301 302 303 static status_t 304 xfs_free_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie) 305 { 306 return B_NOT_SUPPORTED; 307 } 308 309 310 static status_t 311 xfs_access(fs_volume *_volume, fs_vnode *_node, int accessMode) 312 { 313 Inode* inode = (Inode*)_node->private_node; 314 return inode->CheckPermissions(accessMode); 315 } 316 317 318 static status_t 319 xfs_read_link(fs_volume *_volume, fs_vnode *_node, char *buffer, 320 size_t *_bufferSize) 321 { 322 return B_NOT_SUPPORTED; 323 } 324 325 326 status_t 327 xfs_unlink(fs_volume *_volume, fs_vnode *_directory, const char *name) 328 { 329 return B_NOT_SUPPORTED; 330 } 331 332 333 // #pragma mark - Directory functions 334 335 336 static status_t 337 xfs_create_dir(fs_volume *_volume, fs_vnode *_directory, const char *name, 338 int mode) 339 { 340 return B_NOT_SUPPORTED; 341 } 342 343 344 static status_t 345 xfs_remove_dir(fs_volume *_volume, fs_vnode *_directory, const char *name) 346 { 347 return B_NOT_SUPPORTED; 348 } 349 350 351 static status_t 352 xfs_open_dir(fs_volume * /*_volume*/, fs_vnode *_node, void **_cookie) 353 { 354 Inode* inode = (Inode*)_node->private_node; 355 TRACE("XFS_OPEN_DIR: (%ld)\n", inode->ID()); 356 357 status_t status = inode->CheckPermissions(R_OK); 358 if (status < B_OK) 359 return status; 360 361 if (!inode->IsDirectory()) 362 return B_NOT_A_DIRECTORY; 363 364 DirectoryIterator* iterator = new(std::nothrow) DirectoryIterator(inode); 365 if (iterator == NULL) { 366 delete iterator; 367 return B_NO_MEMORY; 368 } 369 status = iterator->Init(); 370 *_cookie = iterator; 371 return status; 372 } 373 374 375 static status_t 376 xfs_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie, 377 struct dirent *buffer, size_t bufferSize, uint32 *_num) 378 { 379 TRACE("XFS_READ_DIR\n"); 380 DirectoryIterator* iterator = (DirectoryIterator*)_cookie; 381 Volume* volume = (Volume*)_volume->private_volume; 382 383 uint32 maxCount = *_num; 384 uint32 count = 0; 385 386 while (count < maxCount && (bufferSize > sizeof(struct dirent))) { 387 size_t length = bufferSize - sizeof(struct dirent) + 1; 388 xfs_ino_t ino; 389 390 status_t status = iterator->GetNext(buffer->d_name, &length, &ino); 391 if (status == B_ENTRY_NOT_FOUND) 392 break; 393 if (status == B_BUFFER_OVERFLOW) { 394 if (count == 0) 395 return status; 396 break; 397 } 398 if (status != B_OK) 399 return status; 400 401 buffer->d_dev = volume->ID(); 402 buffer->d_ino = ino; 403 buffer->d_reclen = sizeof(struct dirent) + length; 404 bufferSize -= buffer->d_reclen; 405 buffer = (struct dirent*)((uint8*)buffer + buffer->d_reclen); 406 count++; 407 } 408 409 *_num = count; 410 TRACE("Count: (%d)\n", count); 411 return B_OK; 412 } 413 414 415 static status_t 416 xfs_rewind_dir(fs_volume * /*_volume*/, fs_vnode * /*node*/, void *_cookie) 417 { 418 return B_NOT_SUPPORTED; 419 } 420 421 422 static status_t 423 xfs_close_dir(fs_volume * /*_volume*/, fs_vnode * /*node*/, 424 void * /*_cookie*/) 425 { 426 return B_NOT_SUPPORTED; 427 } 428 429 430 static status_t 431 xfs_free_dir_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie) 432 { 433 return B_NOT_SUPPORTED; 434 } 435 436 437 static status_t 438 xfs_open_attr_dir(fs_volume *_volume, fs_vnode *_node, void **_cookie) 439 { 440 return B_NOT_SUPPORTED; 441 } 442 443 444 static status_t 445 xfs_close_attr_dir(fs_volume *_volume, fs_vnode *_node, void *cookie) 446 { 447 return B_NOT_SUPPORTED; 448 } 449 450 451 static status_t 452 xfs_free_attr_dir_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie) 453 { 454 return B_NOT_SUPPORTED; 455 } 456 457 458 static status_t 459 xfs_read_attr_dir(fs_volume *_volume, fs_vnode *_node, 460 void *_cookie, struct dirent *dirent, size_t bufferSize, uint32 *_num) 461 { 462 return B_NOT_SUPPORTED; 463 } 464 465 466 static status_t 467 xfs_rewind_attr_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie) 468 { 469 return B_NOT_SUPPORTED; 470 } 471 472 473 /* attribute operations */ 474 static status_t 475 xfs_create_attr(fs_volume *_volume, fs_vnode *_node, 476 const char *name, uint32 type, int openMode, void **_cookie) 477 { 478 return B_NOT_SUPPORTED; 479 } 480 481 482 static status_t 483 xfs_open_attr(fs_volume *_volume, fs_vnode *_node, const char *name, 484 int openMode, void **_cookie) 485 { 486 return B_NOT_SUPPORTED; 487 } 488 489 490 static status_t 491 xfs_close_attr(fs_volume *_volume, fs_vnode *_node, 492 void *cookie) 493 { 494 return B_NOT_SUPPORTED; 495 } 496 497 498 static status_t 499 xfs_free_attr_cookie(fs_volume *_volume, fs_vnode *_node, void *cookie) 500 { 501 return B_NOT_SUPPORTED; 502 } 503 504 505 static status_t 506 xfs_read_attr(fs_volume *_volume, fs_vnode *_node, void *_cookie, 507 off_t pos, void *buffer, size_t *_length) 508 { 509 return B_NOT_SUPPORTED; 510 } 511 512 513 static status_t 514 xfs_write_attr(fs_volume *_volume, fs_vnode *_node, void *cookie, 515 off_t pos, const void *buffer, size_t *length) 516 { 517 return B_NOT_SUPPORTED; 518 } 519 520 521 static status_t 522 xfs_read_attr_stat(fs_volume *_volume, fs_vnode *_node, 523 void *_cookie, struct stat *stat) 524 { 525 return B_NOT_SUPPORTED; 526 } 527 528 529 static status_t 530 xfs_write_attr_stat(fs_volume *_volume, fs_vnode *_node, 531 void *cookie, const struct stat *stat, int statMask) 532 { 533 return B_NOT_SUPPORTED; 534 } 535 536 537 static status_t 538 xfs_rename_attr(fs_volume *_volume, fs_vnode *fromVnode, 539 const char *fromName, fs_vnode *toVnode, const char *toName) 540 { 541 return B_NOT_SUPPORTED; 542 } 543 544 545 static status_t 546 xfs_remove_attr(fs_volume *_volume, fs_vnode *vnode, 547 const char *name) 548 { 549 return B_NOT_SUPPORTED; 550 } 551 552 553 static uint32 554 xfs_get_supported_operations(partition_data *partition, uint32 mask) 555 { 556 return B_NOT_SUPPORTED; 557 } 558 559 560 static status_t 561 xfs_initialize(int fd, partition_id partitionID, const char *name, 562 const char *parameterString, off_t partitionSize, disk_job_id job) 563 { 564 return B_NOT_SUPPORTED; 565 } 566 567 568 static status_t 569 xfs_uninitialize(int fd, partition_id partitionID, off_t partitionSize, 570 uint32 blockSize, disk_job_id job) 571 { 572 return B_NOT_SUPPORTED; 573 } 574 575 576 // #pragma mark - 577 578 579 static status_t 580 xfs_std_ops(int32 op, ...) 581 { 582 switch (op) 583 { 584 case B_MODULE_INIT: 585 #ifdef XFS_DEBUGGER_COMMANDS 586 // Perform nothing at the moment 587 // add_debugger_commands(); 588 #endif 589 return B_OK; 590 case B_MODULE_UNINIT: 591 #ifdef XFS_DEBUGGER_COMMANDS 592 // Perform nothing at the moment 593 // remove_debugger_commands(); 594 #endif 595 return B_OK; 596 597 default: 598 return B_ERROR; 599 } 600 } 601 602 603 fs_volume_ops gxfsVolumeOps = { 604 &xfs_unmount, 605 &xfs_read_fs_info, 606 NULL, // write_fs_info() 607 NULL, // fs_sync, 608 &xfs_get_vnode, 609 }; 610 611 612 fs_vnode_ops gxfsVnodeOps = { 613 /* vnode operations */ 614 &xfs_lookup, 615 NULL, // xfs_get_vnode_name- optional, and we can't do better 616 // than the fallback implementation, so leave as NULL. 617 &xfs_put_vnode, 618 NULL, // xfs_remove_vnode, 619 620 /* VM file access */ 621 &xfs_can_page, 622 &xfs_read_pages, 623 NULL, // xfs_write_pages, 624 625 &xfs_io, // io() 626 NULL, // cancel_io() 627 628 &xfs_get_file_map, 629 630 &xfs_ioctl, 631 NULL, 632 NULL, // fs_select 633 NULL, // fs_deselect 634 NULL, // fs_fsync, 635 636 &xfs_read_link, 637 NULL, // fs_create_symlink, 638 639 NULL, // fs_link, 640 &xfs_unlink, 641 NULL, // fs_rename, 642 643 &xfs_access, 644 &xfs_read_stat, 645 NULL, // fs_write_stat, 646 NULL, // fs_preallocate 647 648 /* file operations */ 649 NULL, // fs_create, 650 &xfs_open, 651 &xfs_close, 652 &xfs_free_cookie, 653 &xfs_read, 654 NULL, // fs_write, 655 656 /* directory operations */ 657 &xfs_create_dir, 658 &xfs_remove_dir, 659 &xfs_open_dir, 660 &xfs_close_dir, 661 &xfs_free_dir_cookie, 662 &xfs_read_dir, 663 &xfs_rewind_dir, 664 665 /* attribute directory operations */ 666 &xfs_open_attr_dir, 667 &xfs_close_attr_dir, 668 &xfs_free_attr_dir_cookie, 669 &xfs_read_attr_dir, 670 &xfs_rewind_attr_dir, 671 672 /* attribute operations */ 673 &xfs_create_attr, 674 &xfs_open_attr, 675 &xfs_close_attr, 676 &xfs_free_attr_cookie, 677 &xfs_read_attr, 678 &xfs_write_attr, 679 &xfs_read_attr_stat, 680 &xfs_write_attr_stat, 681 &xfs_rename_attr, 682 &xfs_remove_attr, 683 }; 684 685 686 static 687 file_system_module_info sxfsFileSystem = { 688 { 689 "file_systems/xfs" B_CURRENT_FS_API_VERSION, 690 0, 691 xfs_std_ops, 692 }, 693 694 "xfs", // short_name 695 "XFS File System", // pretty_name 696 697 // DDM flags 698 0 |B_DISK_SYSTEM_SUPPORTS_INITIALIZING |B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME 699 // | B_DISK_SYSTEM_SUPPORTS_WRITING 700 , 701 702 // scanning 703 xfs_identify_partition, 704 xfs_scan_partition, 705 xfs_free_identify_partition_cookie, 706 NULL, // free_partition_content_cookie() 707 708 &xfs_mount, 709 710 /* capability querying operations */ 711 &xfs_get_supported_operations, 712 713 NULL, // validate_resize 714 NULL, // validate_move 715 NULL, // validate_set_content_name 716 NULL, // validate_set_content_parameters 717 NULL, // validate_initialize, 718 719 /* shadow partition modification */ 720 NULL, // shadow_changed 721 722 /* writing */ 723 NULL, // defragment 724 NULL, // repair 725 NULL, // resize 726 NULL, // move 727 NULL, // set_content_name 728 NULL, // set_content_parameters 729 xfs_initialize, 730 xfs_uninitialize}; 731 732 module_info *modules[] = { 733 (module_info *)&sxfsFileSystem, 734 NULL, 735 }; 736