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