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 //TODO: pretend everything is accessible. We should actually checking 215 //for permission here. 216 DirectoryIterator* iterator = 217 new(std::nothrow) DirectoryIterator(directory); 218 if (iterator == NULL) 219 return B_NO_MEMORY; 220 221 status_t status = iterator->Init(); 222 if (status != B_OK) { 223 delete iterator; 224 return status; 225 } 226 227 status = iterator->Lookup(name, strlen(name), (xfs_ino_t*)_vnodeID); 228 if (status != B_OK) { 229 delete iterator; 230 return status; 231 } 232 233 TRACE("XFS_LOOKUP: ID: (%ld)\n", *_vnodeID); 234 status = get_vnode(volume->FSVolume(), *_vnodeID, NULL); 235 TRACE("get_vnode status: (%d)\n", status); 236 return status; 237 } 238 239 240 static status_t 241 xfs_ioctl(fs_volume *_volume, fs_vnode *_node, void *_cookie, uint32 cmd, 242 void *buffer, size_t bufferLength) 243 { 244 return B_NOT_SUPPORTED; 245 } 246 247 248 static status_t 249 xfs_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat) 250 { 251 Inode* inode = (Inode*)_node->private_node; 252 TRACE("XFS_READ_STAT: id: (%ld)\n", inode->ID()); 253 stat->st_dev = inode->GetVolume()->ID(); 254 stat->st_ino = inode->ID(); 255 stat->st_nlink = 1; 256 stat->st_blksize = XFS_IO_SIZE; 257 258 stat->st_uid = inode->UserId(); 259 stat->st_gid = inode->GroupId(); 260 stat->st_mode = inode->Mode(); 261 stat->st_type = 0; // TODO 262 263 stat->st_size = inode->Size(); 264 stat->st_blocks = inode->BlockCount(); 265 266 inode->GetAccessTime(stat->st_atim); 267 inode->GetModificationTime(stat->st_mtim); 268 inode->GetChangeTime(stat->st_ctim); 269 270 /* TODO: Can we obtain the Creation Time in v4 system? */ 271 inode->GetChangeTime(stat->st_crtim); 272 273 return B_OK; 274 275 } 276 277 278 static status_t 279 xfs_open(fs_volume * /*_volume*/, fs_vnode *_node, int openMode, 280 void **_cookie) 281 { 282 return B_NOT_SUPPORTED; 283 } 284 285 286 static status_t 287 xfs_read(fs_volume *_volume, fs_vnode *_node, void *_cookie, off_t pos, 288 void *buffer, size_t *_length) 289 { 290 return B_NOT_SUPPORTED; 291 } 292 293 294 static status_t 295 xfs_close(fs_volume *_volume, fs_vnode *_node, void *_cookie) 296 { 297 return B_NOT_SUPPORTED; 298 } 299 300 301 static status_t 302 xfs_free_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie) 303 { 304 return B_NOT_SUPPORTED; 305 } 306 307 308 static status_t 309 xfs_access(fs_volume *_volume, fs_vnode *_node, int accessMode) 310 { 311 //TODO: pretend everything is accessible. We should actually checking 312 //for permission here. 313 return B_OK; 314 } 315 316 317 static status_t 318 xfs_read_link(fs_volume *_volume, fs_vnode *_node, char *buffer, 319 size_t *_bufferSize) 320 { 321 return B_NOT_SUPPORTED; 322 } 323 324 325 status_t 326 xfs_unlink(fs_volume *_volume, fs_vnode *_directory, const char *name) 327 { 328 return B_NOT_SUPPORTED; 329 } 330 331 332 // #pragma mark - Directory functions 333 334 335 static status_t 336 xfs_create_dir(fs_volume *_volume, fs_vnode *_directory, const char *name, 337 int mode) 338 { 339 return B_NOT_SUPPORTED; 340 } 341 342 343 static status_t 344 xfs_remove_dir(fs_volume *_volume, fs_vnode *_directory, const char *name) 345 { 346 return B_NOT_SUPPORTED; 347 } 348 349 350 static status_t 351 xfs_open_dir(fs_volume * /*_volume*/, fs_vnode *_node, void **_cookie) 352 { 353 Inode* inode = (Inode*)_node->private_node; 354 TRACE("XFS_OPEN_DIR: (%ld)\n", inode->ID()); 355 356 if (!inode->IsDirectory()) 357 return B_NOT_A_DIRECTORY; 358 359 DirectoryIterator* iterator = new(std::nothrow) DirectoryIterator(inode); 360 if (iterator == NULL) { 361 delete iterator; 362 return B_NO_MEMORY; 363 } 364 status_t status = iterator->Init(); 365 *_cookie = iterator; 366 return status; 367 } 368 369 370 static status_t 371 xfs_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie, 372 struct dirent *buffer, size_t bufferSize, uint32 *_num) 373 { 374 TRACE("XFS_READ_DIR\n"); 375 DirectoryIterator* iterator = (DirectoryIterator*)_cookie; 376 Volume* volume = (Volume*)_volume->private_volume; 377 378 uint32 maxCount = *_num; 379 uint32 count = 0; 380 381 while (count < maxCount && (bufferSize > sizeof(struct dirent))) { 382 size_t length = bufferSize - sizeof(struct dirent) + 1; 383 xfs_ino_t ino; 384 385 status_t status = iterator->GetNext(buffer->d_name, &length, &ino); 386 if (status == B_ENTRY_NOT_FOUND) 387 break; 388 if (status == B_BUFFER_OVERFLOW) { 389 if (count == 0) 390 return status; 391 break; 392 } 393 if (status != B_OK) 394 return status; 395 396 buffer->d_dev = volume->ID(); 397 buffer->d_ino = ino; 398 buffer->d_reclen = sizeof(struct dirent) + length; 399 bufferSize -= buffer->d_reclen; 400 buffer = (struct dirent*)((uint8*)buffer + buffer->d_reclen); 401 count++; 402 } 403 404 *_num = count; 405 TRACE("Count: (%d)\n", count); 406 return B_OK; 407 } 408 409 410 static status_t 411 xfs_rewind_dir(fs_volume * /*_volume*/, fs_vnode * /*node*/, void *_cookie) 412 { 413 return B_NOT_SUPPORTED; 414 } 415 416 417 static status_t 418 xfs_close_dir(fs_volume * /*_volume*/, fs_vnode * /*node*/, 419 void * /*_cookie*/) 420 { 421 return B_NOT_SUPPORTED; 422 } 423 424 425 static status_t 426 xfs_free_dir_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie) 427 { 428 return B_NOT_SUPPORTED; 429 } 430 431 432 static status_t 433 xfs_open_attr_dir(fs_volume *_volume, fs_vnode *_node, void **_cookie) 434 { 435 return B_NOT_SUPPORTED; 436 } 437 438 439 static status_t 440 xfs_close_attr_dir(fs_volume *_volume, fs_vnode *_node, void *cookie) 441 { 442 return B_NOT_SUPPORTED; 443 } 444 445 446 static status_t 447 xfs_free_attr_dir_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie) 448 { 449 return B_NOT_SUPPORTED; 450 } 451 452 453 static status_t 454 xfs_read_attr_dir(fs_volume *_volume, fs_vnode *_node, 455 void *_cookie, struct dirent *dirent, size_t bufferSize, uint32 *_num) 456 { 457 return B_NOT_SUPPORTED; 458 } 459 460 461 static status_t 462 xfs_rewind_attr_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie) 463 { 464 return B_NOT_SUPPORTED; 465 } 466 467 468 /* attribute operations */ 469 static status_t 470 xfs_create_attr(fs_volume *_volume, fs_vnode *_node, 471 const char *name, uint32 type, int openMode, void **_cookie) 472 { 473 return B_NOT_SUPPORTED; 474 } 475 476 477 static status_t 478 xfs_open_attr(fs_volume *_volume, fs_vnode *_node, const char *name, 479 int openMode, void **_cookie) 480 { 481 return B_NOT_SUPPORTED; 482 } 483 484 485 static status_t 486 xfs_close_attr(fs_volume *_volume, fs_vnode *_node, 487 void *cookie) 488 { 489 return B_NOT_SUPPORTED; 490 } 491 492 493 static status_t 494 xfs_free_attr_cookie(fs_volume *_volume, fs_vnode *_node, void *cookie) 495 { 496 return B_NOT_SUPPORTED; 497 } 498 499 500 static status_t 501 xfs_read_attr(fs_volume *_volume, fs_vnode *_node, void *_cookie, 502 off_t pos, void *buffer, size_t *_length) 503 { 504 return B_NOT_SUPPORTED; 505 } 506 507 508 static status_t 509 xfs_write_attr(fs_volume *_volume, fs_vnode *_node, void *cookie, 510 off_t pos, const void *buffer, size_t *length) 511 { 512 return B_NOT_SUPPORTED; 513 } 514 515 516 static status_t 517 xfs_read_attr_stat(fs_volume *_volume, fs_vnode *_node, 518 void *_cookie, struct stat *stat) 519 { 520 return B_NOT_SUPPORTED; 521 } 522 523 524 static status_t 525 xfs_write_attr_stat(fs_volume *_volume, fs_vnode *_node, 526 void *cookie, const struct stat *stat, int statMask) 527 { 528 return B_NOT_SUPPORTED; 529 } 530 531 532 static status_t 533 xfs_rename_attr(fs_volume *_volume, fs_vnode *fromVnode, 534 const char *fromName, fs_vnode *toVnode, const char *toName) 535 { 536 return B_NOT_SUPPORTED; 537 } 538 539 540 static status_t 541 xfs_remove_attr(fs_volume *_volume, fs_vnode *vnode, 542 const char *name) 543 { 544 return B_NOT_SUPPORTED; 545 } 546 547 548 static uint32 549 xfs_get_supported_operations(partition_data *partition, uint32 mask) 550 { 551 return B_NOT_SUPPORTED; 552 } 553 554 555 static status_t 556 xfs_initialize(int fd, partition_id partitionID, const char *name, 557 const char *parameterString, off_t partitionSize, disk_job_id job) 558 { 559 return B_NOT_SUPPORTED; 560 } 561 562 563 static status_t 564 xfs_uninitialize(int fd, partition_id partitionID, off_t partitionSize, 565 uint32 blockSize, disk_job_id job) 566 { 567 return B_NOT_SUPPORTED; 568 } 569 570 571 // #pragma mark - 572 573 574 static status_t 575 xfs_std_ops(int32 op, ...) 576 { 577 switch (op) 578 { 579 case B_MODULE_INIT: 580 #ifdef XFS_DEBUGGER_COMMANDS 581 // Perform nothing at the moment 582 // add_debugger_commands(); 583 #endif 584 return B_OK; 585 case B_MODULE_UNINIT: 586 #ifdef XFS_DEBUGGER_COMMANDS 587 // Perform nothing at the moment 588 // remove_debugger_commands(); 589 #endif 590 return B_OK; 591 592 default: 593 return B_ERROR; 594 } 595 } 596 597 598 fs_volume_ops gxfsVolumeOps = { 599 &xfs_unmount, 600 &xfs_read_fs_info, 601 NULL, // write_fs_info() 602 NULL, // fs_sync, 603 &xfs_get_vnode, 604 }; 605 606 607 fs_vnode_ops gxfsVnodeOps = { 608 /* vnode operations */ 609 &xfs_lookup, 610 NULL, // xfs_get_vnode_name- optional, and we can't do better 611 // than the fallback implementation, so leave as NULL. 612 &xfs_put_vnode, 613 NULL, // xfs_remove_vnode, 614 615 /* VM file access */ 616 &xfs_can_page, 617 &xfs_read_pages, 618 NULL, // xfs_write_pages, 619 620 &xfs_io, // io() 621 NULL, // cancel_io() 622 623 &xfs_get_file_map, 624 625 &xfs_ioctl, 626 NULL, 627 NULL, // fs_select 628 NULL, // fs_deselect 629 NULL, // fs_fsync, 630 631 &xfs_read_link, 632 NULL, // fs_create_symlink, 633 634 NULL, // fs_link, 635 &xfs_unlink, 636 NULL, // fs_rename, 637 638 &xfs_access, 639 &xfs_read_stat, 640 NULL, // fs_write_stat, 641 NULL, // fs_preallocate 642 643 /* file operations */ 644 NULL, // fs_create, 645 &xfs_open, 646 &xfs_close, 647 &xfs_free_cookie, 648 &xfs_read, 649 NULL, // fs_write, 650 651 /* directory operations */ 652 &xfs_create_dir, 653 &xfs_remove_dir, 654 &xfs_open_dir, 655 &xfs_close_dir, 656 &xfs_free_dir_cookie, 657 &xfs_read_dir, 658 &xfs_rewind_dir, 659 660 /* attribute directory operations */ 661 &xfs_open_attr_dir, 662 &xfs_close_attr_dir, 663 &xfs_free_attr_dir_cookie, 664 &xfs_read_attr_dir, 665 &xfs_rewind_attr_dir, 666 667 /* attribute operations */ 668 &xfs_create_attr, 669 &xfs_open_attr, 670 &xfs_close_attr, 671 &xfs_free_attr_cookie, 672 &xfs_read_attr, 673 &xfs_write_attr, 674 &xfs_read_attr_stat, 675 &xfs_write_attr_stat, 676 &xfs_rename_attr, 677 &xfs_remove_attr, 678 }; 679 680 681 static 682 file_system_module_info sxfsFileSystem = { 683 { 684 "file_systems/xfs" B_CURRENT_FS_API_VERSION, 685 0, 686 xfs_std_ops, 687 }, 688 689 "xfs", // short_name 690 "XFS File System", // pretty_name 691 692 // DDM flags 693 0 |B_DISK_SYSTEM_SUPPORTS_INITIALIZING |B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME 694 // | B_DISK_SYSTEM_SUPPORTS_WRITING 695 , 696 697 // scanning 698 xfs_identify_partition, 699 xfs_scan_partition, 700 xfs_free_identify_partition_cookie, 701 NULL, // free_partition_content_cookie() 702 703 &xfs_mount, 704 705 /* capability querying operations */ 706 &xfs_get_supported_operations, 707 708 NULL, // validate_resize 709 NULL, // validate_move 710 NULL, // validate_set_content_name 711 NULL, // validate_set_content_parameters 712 NULL, // validate_initialize, 713 714 /* shadow partition modification */ 715 NULL, // shadow_changed 716 717 /* writing */ 718 NULL, // defragment 719 NULL, // repair 720 NULL, // resize 721 NULL, // move 722 NULL, // set_content_name 723 NULL, // set_content_parameters 724 xfs_initialize, 725 xfs_uninitialize}; 726 727 module_info *modules[] = { 728 (module_info *)&sxfsFileSystem, 729 NULL, 730 }; 731