1 /* 2 * Copyright 2021, Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Augustin Cavalier <waddlesplash> 7 */ 8 9 #include <dirent.h> 10 #include <unistd.h> 11 #include <util/kernel_cpp.h> 12 #include <string.h> 13 14 #include <AutoDeleter.h> 15 #include <fs_cache.h> 16 #include <fs_info.h> 17 #include <vfs.h> 18 #include <NodeMonitor.h> 19 #include <file_systems/DeviceOpener.h> 20 #include <file_systems/fs_ops_support.h> 21 #include <util/AutoLock.h> 22 23 #include "ntfs.h" 24 25 extern "C" { 26 #include "libntfs/bootsect.h" 27 #include "libntfs/dir.h" 28 #include "utils/utils.h" 29 } 30 31 //#define TRACE_NTFS 32 #ifdef TRACE_NTFS 33 # define TRACE(X...) dprintf("ntfs: " X) 34 #else 35 # define TRACE(X...) ; 36 #endif 37 #define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__) 38 #define ERROR(X...) dprintf("ntfs: error: " X) 39 40 41 struct identify_cookie { 42 NTFS_BOOT_SECTOR boot; 43 }; 44 45 extern "C" int mkntfs_main(const char* devpath, const char* label); 46 47 typedef CObjectDeleter<ntfs_inode, int, ntfs_inode_close> NtfsInodeCloser; 48 typedef CObjectDeleter<ntfs_attr, void, ntfs_attr_close> NtfsAttrCloser; 49 static status_t fs_access(fs_volume* _volume, fs_vnode* _node, int accessMode); 50 51 52 // #pragma mark - Scanning 53 54 55 static float 56 fs_identify_partition(int fd, partition_data* partition, void** _cookie) 57 { 58 CALLED(); 59 60 NTFS_BOOT_SECTOR boot; 61 if (read_pos(fd, 0, (void*)&boot, 512) != 512) { 62 ERROR("identify_partition: failed to read boot sector\n"); 63 return -1; 64 } 65 66 if (!ntfs_boot_sector_is_ntfs(&boot)) { 67 ERROR("identify_partition: boot signature doesn't match\n"); 68 return -1; 69 } 70 71 identify_cookie* cookie = new identify_cookie; 72 if (cookie == NULL) { 73 ERROR("identify_partition: cookie allocation failed\n"); 74 return -1; 75 } 76 77 memcpy(&cookie->boot, &boot, sizeof(boot)); 78 *_cookie = cookie; 79 80 // This value overrides the Intel partition identifier. 81 return 0.82f; 82 } 83 84 85 static status_t 86 fs_scan_partition(int fd, partition_data* partition, void* _cookie) 87 { 88 CALLED(); 89 90 identify_cookie *cookie = (identify_cookie*)_cookie; 91 partition->status = B_PARTITION_VALID; 92 partition->flags |= B_PARTITION_FILE_SYSTEM; 93 partition->content_size = sle64_to_cpu(cookie->boot.number_of_sectors) 94 * le16_to_cpu(cookie->boot.bpb.bytes_per_sector); 95 partition->block_size = le16_to_cpu(cookie->boot.bpb.bytes_per_sector); 96 97 // get volume name 98 ntfs_volume* ntVolume; 99 char path[B_PATH_NAME_LENGTH]; 100 if (ioctl(fd, B_GET_PATH_FOR_DEVICE, path) != 0) { 101 ntVolume = utils_mount_volume(path, NTFS_MNT_RDONLY | NTFS_MNT_RECOVER); 102 if (ntVolume == NULL) 103 return errno ? errno : B_ERROR; 104 105 if (ntVolume->vol_name != NULL && ntVolume->vol_name[0] != '\0') 106 partition->content_name = strdup(ntVolume->vol_name); 107 else 108 partition->content_name = strdup(""); 109 ntfs_umount(ntVolume, true); 110 } 111 112 return partition->content_name != NULL ? B_OK : B_NO_MEMORY; 113 } 114 115 116 static void 117 fs_free_identify_partition_cookie(partition_data* partition, void* _cookie) 118 { 119 CALLED(); 120 121 delete (identify_cookie*)_cookie; 122 } 123 124 125 // #pragma mark - 126 127 128 static status_t 129 fs_initialize(int fd, partition_id partitionID, const char* name, 130 const char* parameterString, off_t partitionSize, disk_job_id job) 131 { 132 TRACE("fs_initialize: '%s', %s\n", name, parameterString); 133 134 update_disk_device_job_progress(job, 0); 135 136 char path[B_PATH_NAME_LENGTH]; 137 if (ioctl(fd, B_GET_PATH_FOR_DEVICE, path) == 0) 138 return B_BAD_VALUE; 139 140 status_t result = mkntfs_main(path, name); 141 if (result != 0) 142 return result; 143 144 result = scan_partition(partitionID); 145 if (result != B_OK) 146 return result; 147 148 update_disk_device_job_progress(job, 1); 149 return B_OK; 150 } 151 152 153 static status_t 154 fs_mount(fs_volume* _volume, const char* device, uint32 flags, 155 const char* args, ino_t* _rootID) 156 { 157 CALLED(); 158 159 volume* volume = new struct volume; 160 vnode* root = new vnode; 161 if (volume == NULL || root == NULL) 162 return B_NO_MEMORY; 163 ObjectDeleter<struct volume> volumeDeleter(volume); 164 165 mutex_init(&volume->lock, "NTFS volume lock"); 166 volume->fs_info_flags = B_FS_IS_PERSISTENT; 167 168 unsigned long ntfsFlags = NTFS_MNT_RECOVER | NTFS_MNT_MAY_RDONLY; 169 if ((flags & B_MOUNT_READ_ONLY) != 0 || DeviceOpener(device, O_RDWR).IsReadOnly()) 170 ntfsFlags |= NTFS_MNT_RDONLY; 171 172 // mount 173 volume->ntfs = utils_mount_volume(device, ntfsFlags); 174 if (volume->ntfs == NULL) 175 return errno; 176 177 if (NVolReadOnly(volume->ntfs)) { 178 if ((ntfsFlags & NTFS_MNT_RDONLY) == 0) 179 ERROR("volume is hibernated, mounted as read-only\n"); 180 volume->fs_info_flags |= B_FS_IS_READONLY; 181 } 182 183 if (ntfs_volume_get_free_space(volume->ntfs) != 0) { 184 ntfs_umount(volume->ntfs, true); 185 return B_ERROR; 186 } 187 188 const bool showSystem = false, showHidden = true, hideDot = false; 189 if (ntfs_set_shown_files(volume->ntfs, showSystem, showHidden, hideDot) != 0) { 190 ntfs_umount(volume->ntfs, true); 191 return B_ERROR; 192 } 193 194 // Fetch mount path, used when reading NTFS symlinks. 195 dev_t deviceID; 196 ino_t nodeID; 197 status_t status = vfs_get_mount_point(_volume->id, &deviceID, &nodeID); 198 char* mountpoint; 199 if (status == B_OK) { 200 mountpoint = (char*)malloc(PATH_MAX); 201 status = vfs_entry_ref_to_path(deviceID, nodeID, NULL, true, 202 mountpoint, PATH_MAX); 203 if (status == B_OK) { 204 char* reallocated = (char*)realloc(mountpoint, strlen(mountpoint) + 1); 205 if (reallocated != NULL) 206 mountpoint = reallocated; 207 } else { 208 free(mountpoint); 209 mountpoint = NULL; 210 } 211 } 212 if (status != B_OK) 213 mountpoint = strdup(""); 214 215 // TODO: uid/gid mapping and real permissions 216 217 // construct lowntfs_context 218 volume->lowntfs.haiku_fs_volume = _volume; 219 volume->lowntfs.current_close_state_vnode = NULL; 220 221 volume->lowntfs.vol = volume->ntfs; 222 volume->ntfs->abs_mnt_point = volume->lowntfs.abs_mnt_point = mountpoint; 223 volume->lowntfs.dmask = 0; 224 volume->lowntfs.fmask = S_IXUSR | S_IXGRP | S_IXOTH; 225 volume->lowntfs.dmtime = 0; 226 volume->lowntfs.special_files = NTFS_FILES_INTERIX; 227 volume->lowntfs.posix_nlink = 0; 228 volume->lowntfs.inherit = 0; 229 volume->lowntfs.windows_names = 1; 230 volume->lowntfs.latest_ghost = 0; 231 232 *_rootID = root->inode = FILE_root; 233 root->parent_inode = (u64)-1; 234 root->mode = S_IFDIR | ACCESSPERMS; 235 root->uid = root->gid = 0; 236 root->size = 0; 237 238 status = publish_vnode(_volume, root->inode, root, &gNtfsVnodeOps, S_IFDIR, 0); 239 if (status != B_OK) { 240 ntfs_umount(volume->ntfs, true); 241 return status; 242 } 243 244 volumeDeleter.Detach(); 245 246 _volume->private_volume = volume; 247 _volume->ops = &gNtfsVolumeOps; 248 return B_OK; 249 } 250 251 252 static status_t 253 fs_unmount(fs_volume* _volume) 254 { 255 CALLED(); 256 volume* volume = (struct volume*)_volume->private_volume; 257 258 if (ntfs_umount(volume->ntfs, false) < 0) 259 return errno; 260 261 delete volume; 262 _volume->private_volume = NULL; 263 264 return B_OK; 265 } 266 267 268 static status_t 269 fs_read_fs_info(fs_volume* _volume, struct fs_info* info) 270 { 271 CALLED(); 272 volume* volume = (struct volume*)_volume->private_volume; 273 MutexLocker lock(volume->lock); 274 275 info->flags = volume->fs_info_flags; 276 info->block_size = volume->ntfs->cluster_size; 277 info->total_blocks = volume->ntfs->nr_clusters; 278 info->free_blocks = volume->ntfs->free_clusters; 279 280 info->io_size = 65536; 281 282 strlcpy(info->volume_name, volume->ntfs->vol_name, sizeof(info->volume_name)); 283 strlcpy(info->fsh_name, "NTFS", sizeof(info->fsh_name)); 284 285 return B_OK; 286 } 287 288 289 static status_t 290 fs_write_fs_info(fs_volume* _volume, const struct fs_info* info, uint32 mask) 291 { 292 CALLED(); 293 volume* volume = (struct volume*)_volume->private_volume; 294 MutexLocker lock(volume->lock); 295 296 if ((volume->fs_info_flags & B_FS_IS_READONLY) != 0) 297 return B_READ_ONLY_DEVICE; 298 299 status_t status = B_OK; 300 301 if ((mask & FS_WRITE_FSINFO_NAME) != 0) { 302 ntfschar* label = NULL; 303 int label_len = ntfs_mbstoucs(info->volume_name, &label); 304 if (label_len <= 0 || label == NULL) 305 return -1; 306 MemoryDeleter nameDeleter(label); 307 308 if (ntfs_volume_rename(volume->ntfs, label, label_len) != 0) 309 status = errno; 310 } 311 312 return status; 313 } 314 315 316 // #pragma mark - 317 318 319 static status_t 320 fs_init_vnode(fs_volume* _volume, ino_t parent, ino_t nid, vnode** _vnode, bool publish = false) 321 { 322 volume* volume = (struct volume*)_volume->private_volume; 323 ASSERT_LOCKED_MUTEX(&volume->lock); 324 325 ntfs_inode* ni = ntfs_inode_open(volume->ntfs, nid); 326 if (ni == NULL) 327 return ENOENT; 328 NtfsInodeCloser niCloser(ni); 329 330 vnode* node = new vnode; 331 if (node == NULL) 332 return B_NO_MEMORY; 333 ObjectDeleter<vnode> vnodeDeleter(node); 334 335 struct stat statbuf; 336 if (ntfs_fuse_getstat(&volume->lowntfs, NULL, ni, &statbuf) != 0) 337 return errno; 338 339 node->inode = nid; 340 node->parent_inode = parent; 341 node->uid = statbuf.st_uid; 342 node->gid = statbuf.st_gid; 343 node->mode = statbuf.st_mode; 344 node->size = statbuf.st_size; 345 346 // cache the node's name 347 char path[B_FILE_NAME_LENGTH]; 348 if (utils_inode_get_name(ni, path, sizeof(path)) == 0) 349 return B_NO_MEMORY; 350 node->name = strdup(strrchr(path, '/') + 1); 351 352 if (publish) { 353 status_t status = publish_vnode(_volume, node->inode, node, &gNtfsVnodeOps, node->mode, 0); 354 if (status != B_OK) 355 return status; 356 } 357 358 if ((node->mode & S_IFDIR) == 0) { 359 node->file_cache = file_cache_create(_volume->id, nid, node->size); 360 if (node->file_cache == NULL) 361 return B_NO_INIT; 362 } 363 364 vnodeDeleter.Detach(); 365 *_vnode = node; 366 return B_OK; 367 } 368 369 370 static status_t 371 fs_get_vnode(fs_volume* _volume, ino_t nid, fs_vnode* _node, int* _type, 372 uint32* _flags, bool reenter) 373 { 374 TRACE("get_vnode %" B_PRIdINO "\n", nid); 375 volume* volume = (struct volume*)_volume->private_volume; 376 MutexLocker lock(reenter ? NULL : &volume->lock); 377 378 vnode* vnode; 379 status_t status = fs_init_vnode(_volume, -1 /* set by fs_lookup */, nid, &vnode); 380 if (status != B_OK) 381 return status; 382 383 _node->private_node = vnode; 384 _node->ops = &gNtfsVnodeOps; 385 *_type = vnode->mode; 386 *_flags = 0; 387 388 return B_OK; 389 } 390 391 392 static status_t 393 fs_put_vnode(fs_volume* _volume, fs_vnode* _node, bool reenter) 394 { 395 CALLED(); 396 volume* volume = (struct volume*)_volume->private_volume; 397 MutexLocker lock(reenter ? NULL : &volume->lock); 398 vnode* node = (vnode*)_node->private_node; 399 400 file_cache_delete(node->file_cache); 401 delete node; 402 return B_OK; 403 } 404 405 406 static status_t 407 fs_remove_vnode(fs_volume* _volume, fs_vnode* _node, bool reenter) 408 { 409 CALLED(); 410 volume* volume = (struct volume*)_volume->private_volume; 411 MutexLocker lock(reenter ? NULL : &volume->lock); 412 vnode* node = (vnode*)_node->private_node; 413 414 if (ntfs_fuse_release(&volume->lowntfs, node->parent_inode, node->inode, 415 node->lowntfs_close_state, node->lowntfs_ghost) != 0) 416 return errno; 417 418 file_cache_delete(node->file_cache); 419 delete node; 420 return B_OK; 421 } 422 423 424 int* 425 ntfs_haiku_get_close_state(struct lowntfs_context *ctx, u64 ino) 426 { 427 if (ctx->current_close_state_vnode != NULL) 428 panic("NTFS current_close_state_vnode should be NULL!"); 429 430 vnode* node = NULL; 431 if (get_vnode((fs_volume*)ctx->haiku_fs_volume, ino, (void**)&node) != B_OK) 432 return NULL; 433 ctx->current_close_state_vnode = node; 434 return &node->lowntfs_close_state; 435 } 436 437 438 void 439 ntfs_haiku_put_close_state(struct lowntfs_context *ctx, u64 ino, u64 ghost) 440 { 441 vnode* node = (vnode*)ctx->current_close_state_vnode; 442 if (node == NULL) 443 return; 444 445 node->lowntfs_ghost = ghost; 446 if ((node->lowntfs_close_state & CLOSE_GHOST) != 0) { 447 fs_volume* _volume = (fs_volume*)ctx->haiku_fs_volume; 448 entry_cache_remove(_volume->id, node->parent_inode, node->name); 449 notify_entry_removed(_volume->id, node->parent_inode, node->name, node->inode); 450 remove_vnode(_volume, node->inode); 451 } 452 453 ctx->current_close_state_vnode = NULL; 454 put_vnode((fs_volume*)ctx->haiku_fs_volume, node->inode); 455 } 456 457 458 static bool 459 fs_can_page(fs_volume* _volume, fs_vnode* _node, void* _cookie) 460 { 461 return true; 462 } 463 464 465 static status_t 466 fs_read_pages(fs_volume* _volume, fs_vnode* _node, void* _cookie, 467 off_t pos, const iovec* vecs, size_t count, size_t* _numBytes) 468 { 469 volume* volume = (struct volume*)_volume->private_volume; 470 MutexLocker lock(volume->lock); 471 vnode* node = (vnode*)_node->private_node; 472 473 TRACE("read_pages inode: %" B_PRIdINO", pos: %" B_PRIdOFF "; vecs: %p; " 474 "count: %" B_PRIuSIZE "; numBytes: %" B_PRIuSIZE "\n", node->inode, pos, 475 vecs, count, *_numBytes); 476 477 ntfs_inode* ni = ntfs_inode_open(volume->ntfs, node->inode); 478 if (ni == NULL) 479 return B_FILE_ERROR; 480 NtfsInodeCloser niCloser(ni); 481 482 if (pos < 0 || pos >= ni->data_size) 483 return B_BAD_VALUE; 484 485 size_t bytesLeft = min_c(*_numBytes, size_t(ni->data_size - pos)); 486 *_numBytes = 0; 487 for (size_t i = 0; i < count && bytesLeft > 0; i++) { 488 const size_t ioSize = min_c(bytesLeft, vecs[i].iov_len); 489 const int read = ntfs_fuse_read(ni, pos, (char*)vecs[i].iov_base, ioSize); 490 if (read < 0) 491 return errno; 492 493 pos += read; 494 *_numBytes += read; 495 bytesLeft -= read; 496 497 if (size_t(read) != ioSize) 498 return errno; 499 } 500 501 return B_OK; 502 } 503 504 505 static status_t 506 fs_write_pages(fs_volume* _volume, fs_vnode* _node, void* _cookie, 507 off_t pos, const iovec* vecs, size_t count, size_t* _numBytes) 508 { 509 volume* volume = (struct volume*)_volume->private_volume; 510 MutexLocker lock(volume->lock); 511 vnode* node = (vnode*)_node->private_node; 512 513 TRACE("write_pages inode: %" B_PRIdINO", pos: %" B_PRIdOFF "; vecs: %p; " 514 "count: %" B_PRIuSIZE "; numBytes: %" B_PRIuSIZE "\n", node->inode, pos, 515 vecs, count, *_numBytes); 516 517 ntfs_inode* ni = ntfs_inode_open(volume->ntfs, node->inode); 518 if (ni == NULL) 519 return B_FILE_ERROR; 520 NtfsInodeCloser niCloser(ni); 521 522 if (pos < 0 || pos >= ni->data_size) 523 return B_BAD_VALUE; 524 525 size_t bytesLeft = min_c(*_numBytes, size_t(ni->data_size - pos)); 526 *_numBytes = 0; 527 for (size_t i = 0; i < count && bytesLeft > 0; i++) { 528 const size_t ioSize = min_c(bytesLeft, vecs[i].iov_len); 529 const int written = ntfs_fuse_write(&volume->lowntfs, ni, (char*)vecs[i].iov_base, ioSize, pos); 530 if (written < 0) 531 return errno; 532 533 pos += written; 534 *_numBytes += written; 535 bytesLeft -= written; 536 537 if (size_t(written) != ioSize) 538 return errno; 539 } 540 541 return B_OK; 542 } 543 544 545 // #pragma mark - 546 547 548 static status_t 549 fs_lookup(fs_volume* _volume, fs_vnode* _directory, const char* name, 550 ino_t* _vnodeID) 551 { 552 TRACE("fs_lookup: name address: %p (%s)\n", name, name); 553 volume* volume = (struct volume*)_volume->private_volume; 554 MutexLocker lock(volume->lock); 555 vnode* directory = (vnode*)_directory->private_node; 556 557 status_t result; 558 if (strcmp(name, ".") == 0) { 559 *_vnodeID = directory->inode; 560 } else if (strcmp(name, "..") == 0) { 561 if (directory->inode == FILE_root) 562 return ENOENT; 563 *_vnodeID = directory->parent_inode; 564 } else { 565 u64 inode = ntfs_fuse_inode_lookup(&volume->lowntfs, directory->inode, name); 566 if (inode == (u64)-1) 567 return errno; 568 *_vnodeID = inode; 569 } 570 571 result = entry_cache_add(_volume->id, directory->inode, name, *_vnodeID); 572 if (result != B_OK) 573 return result; 574 575 vnode* node = NULL; 576 result = get_vnode(_volume, *_vnodeID, (void**)&node); 577 if (result != B_OK) 578 return result; 579 580 if (node->parent_inode == (u64)-1) 581 node->parent_inode = directory->inode; 582 583 TRACE("fs_lookup: ID %" B_PRIdINO "\n", *_vnodeID); 584 return B_OK; 585 } 586 587 588 static status_t 589 fs_get_vnode_name(fs_volume* _volume, fs_vnode* _node, char* buffer, size_t bufferSize) 590 { 591 // CALLED(); 592 vnode* node = (vnode*)_node->private_node; 593 594 if (strlcpy(buffer, node->name, bufferSize) >= bufferSize) 595 return B_BUFFER_OVERFLOW; 596 return B_OK; 597 } 598 599 600 static status_t 601 fs_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 cmd, 602 void* buffer, size_t bufferLength) 603 { 604 // TODO? 605 return B_DEV_INVALID_IOCTL; 606 } 607 608 609 static status_t 610 fs_read_stat(fs_volume* _volume, fs_vnode* _node, struct stat* stat) 611 { 612 CALLED(); 613 volume* volume = (struct volume*)_volume->private_volume; 614 MutexLocker lock(volume->lock); 615 vnode* node = (vnode*)_node->private_node; 616 617 ntfs_inode* ni = ntfs_inode_open(volume->ntfs, node->inode); 618 if (ni == NULL) 619 return errno; 620 NtfsInodeCloser niCloser(ni); 621 622 if (ntfs_fuse_getstat(&volume->lowntfs, NULL, ni, stat) != 0) 623 return errno; 624 return B_OK; 625 } 626 627 628 static status_t 629 fs_write_stat(fs_volume* _volume, fs_vnode* _node, const struct stat* stat, uint32 mask) 630 { 631 CALLED(); 632 volume* volume = (struct volume*)_volume->private_volume; 633 MutexLocker lock(volume->lock); 634 vnode* node = (vnode*)_node->private_node; 635 636 if ((volume->fs_info_flags & B_FS_IS_READONLY) != 0) 637 return B_READ_ONLY_DEVICE; 638 639 ntfs_inode* ni = ntfs_inode_open(volume->ntfs, node->inode); 640 if (ni == NULL) 641 return B_FILE_ERROR; 642 NtfsInodeCloser niCloser(ni); 643 644 bool updateTime = false; 645 const uid_t euid = geteuid(); 646 647 const bool isOwnerOrRoot = (euid == 0 || euid == (uid_t)node->uid); 648 const bool hasWriteAccess = fs_access(_volume, _node, W_OK); 649 650 if ((mask & B_STAT_SIZE) != 0 && node->size != stat->st_size) { 651 if ((node->mode & S_IFDIR) != 0) 652 return B_IS_A_DIRECTORY; 653 if (!hasWriteAccess) 654 return B_NOT_ALLOWED; 655 656 ntfs_attr* na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); 657 if (na == NULL) 658 return errno; 659 NtfsAttrCloser naCloser(na); 660 661 if (ntfs_attr_truncate(na, stat->st_size) != 0) 662 return errno; 663 node->size = na->data_size; 664 file_cache_set_size(node->file_cache, node->size); 665 666 updateTime = true; 667 } 668 669 if ((mask & B_STAT_UID) != 0) { 670 // only root should be allowed 671 if (euid != 0) 672 return B_NOT_ALLOWED; 673 674 // We don't support this (yet.) 675 if (node->uid != stat->st_uid) 676 return B_UNSUPPORTED; 677 } 678 679 if ((mask & B_STAT_GID) != 0) { 680 // only the user or root can do that 681 if (!isOwnerOrRoot) 682 return B_NOT_ALLOWED; 683 684 // We don't support this (yet.) 685 if (node->gid != stat->st_gid) 686 return B_UNSUPPORTED; 687 } 688 689 if ((mask & B_STAT_MODE) != 0) { 690 // only the user or root can do that 691 if (!isOwnerOrRoot) 692 return B_NOT_ALLOWED; 693 694 // We don't support this (yet.) 695 if (node->mode != stat->st_mode) 696 return B_UNSUPPORTED; 697 } 698 699 if ((mask & B_STAT_CREATION_TIME) != 0) { 700 // the user or root can do that or any user with write access 701 if (!isOwnerOrRoot && !hasWriteAccess) 702 return B_NOT_ALLOWED; 703 704 ni->creation_time = timespec2ntfs(stat->st_crtim); 705 } 706 707 if ((mask & B_STAT_MODIFICATION_TIME) != 0) { 708 // the user or root can do that or any user with write access 709 if (!isOwnerOrRoot && !hasWriteAccess) 710 return B_NOT_ALLOWED; 711 712 ni->last_data_change_time = timespec2ntfs(stat->st_mtim); 713 } 714 715 if ((mask & B_STAT_CHANGE_TIME) != 0 || updateTime) { 716 // the user or root can do that or any user with write access 717 if (!isOwnerOrRoot && !hasWriteAccess) 718 return B_NOT_ALLOWED; 719 720 ni->last_mft_change_time = timespec2ntfs(stat->st_ctim); 721 } 722 723 if ((mask & B_STAT_ACCESS_TIME) != 0) { 724 // the user or root can do that or any user with write access 725 if (!isOwnerOrRoot && !hasWriteAccess) 726 return B_NOT_ALLOWED; 727 728 ni->last_access_time = timespec2ntfs(stat->st_atim); 729 } 730 731 ntfs_inode_mark_dirty(ni); 732 733 notify_stat_changed(_volume->id, node->parent_inode, node->inode, mask); 734 return B_OK; 735 } 736 737 738 static status_t 739 fs_generic_create(fs_volume* _volume, vnode* directory, const char* name, int mode, 740 ino_t* _inode) 741 { 742 volume* volume = (struct volume*)_volume->private_volume; 743 ASSERT_LOCKED_MUTEX(&volume->lock); 744 745 if ((directory->mode & S_IFDIR) == 0) 746 return B_BAD_TYPE; 747 748 ino_t inode = -1; 749 if (ntfs_fuse_create(&volume->lowntfs, directory->inode, name, mode & (S_IFMT | 07777), 750 0, (char*)NULL, &inode) != 0) 751 return errno; 752 753 vnode* node; 754 status_t status = fs_init_vnode(_volume, directory->inode, inode, &node, true); 755 if (status != B_OK) 756 return status; 757 758 entry_cache_add(_volume->id, directory->inode, name, inode); 759 notify_entry_created(_volume->id, directory->inode, name, inode); 760 *_inode = inode; 761 return B_OK; 762 } 763 764 765 static status_t 766 fs_create(fs_volume* _volume, fs_vnode* _directory, const char* name, 767 int openMode, int mode, void** _cookie, ino_t* _vnodeID) 768 { 769 CALLED(); 770 volume* volume = (struct volume*)_volume->private_volume; 771 MutexLocker lock(volume->lock); 772 vnode* directory = (vnode*)_directory->private_node; 773 774 if ((directory->mode & S_IFDIR) == 0) 775 return B_NOT_A_DIRECTORY; 776 777 status_t status = fs_access(_volume, _directory, W_OK); 778 if (status != B_OK) 779 return status; 780 781 #if 1 782 if ((openMode & O_NOCACHE) != 0) 783 return B_UNSUPPORTED; 784 #endif 785 786 status = fs_generic_create(_volume, directory, name, S_IFREG | (mode & 07777), _vnodeID); 787 if (status != B_OK) 788 return status; 789 790 file_cookie* cookie = new file_cookie; 791 if (cookie == NULL) 792 return B_NO_MEMORY; 793 ObjectDeleter<file_cookie> cookieDeleter(cookie); 794 795 cookie->open_mode = openMode; 796 797 cookieDeleter.Detach(); 798 *_cookie = cookie; 799 return B_OK; 800 } 801 802 803 static status_t 804 fs_open(fs_volume* _volume, fs_vnode* _node, int openMode, void** _cookie) 805 { 806 CALLED(); 807 volume* volume = (struct volume*)_volume->private_volume; 808 MutexLocker lock(volume->lock); 809 vnode* node = (vnode*)_node->private_node; 810 811 // opening a directory read-only is allowed (but no data can be read) 812 if ((node->mode & S_IFDIR) != 0 && (openMode & O_RWMASK) != 0) 813 return B_IS_A_DIRECTORY; 814 if ((openMode & O_DIRECTORY) != 0 && (node->mode & S_IFDIR) == 0) 815 return B_NOT_A_DIRECTORY; 816 817 status_t status = fs_access(_volume, _node, open_mode_to_access(openMode)); 818 if (status != B_OK) 819 return status; 820 821 ntfs_inode* ni = ntfs_inode_open(volume->ntfs, node->inode); 822 if (ni == NULL) 823 return errno; 824 NtfsInodeCloser niCloser(ni); 825 826 file_cookie* cookie = new file_cookie; 827 if (cookie == NULL) 828 return B_NO_MEMORY; 829 ObjectDeleter<file_cookie> cookieDeleter(cookie); 830 831 cookie->open_mode = openMode; 832 833 // We don't actually support uncached mode; it would require us to handle 834 // passing user buffers to libntfs, among other things. 835 #if 0 836 if ((openMode & O_NOCACHE) != 0 && node->file_cache != NULL) { 837 status_t status = file_cache_disable(node->file_cache); 838 if (status != B_OK) 839 return status; 840 } 841 #else 842 if ((openMode & O_NOCACHE) != 0) 843 return B_UNSUPPORTED; 844 #endif 845 846 if ((openMode & O_TRUNC) != 0) { 847 if ((openMode & O_RWMASK) == O_RDONLY) 848 return B_NOT_ALLOWED; 849 850 ntfs_attr* na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); 851 if (na == NULL) 852 return errno; 853 NtfsAttrCloser naCloser(na); 854 855 if (ntfs_attr_truncate(na, 0) != 0) 856 return errno; 857 node->size = na->data_size; 858 file_cache_set_size(node->file_cache, node->size); 859 } 860 861 cookieDeleter.Detach(); 862 *_cookie = cookie; 863 return B_OK; 864 } 865 866 867 static status_t 868 fs_read(fs_volume* _volume, fs_vnode* _node, void* _cookie, off_t pos, 869 void* buffer, size_t* length) 870 { 871 vnode* node = (vnode*)_node->private_node; 872 file_cookie* cookie = (file_cookie*)_cookie; 873 874 if ((node->mode & S_IFDIR) != 0) 875 return B_IS_A_DIRECTORY; 876 877 ASSERT((cookie->open_mode & O_RWMASK) == O_RDONLY || (cookie->open_mode & O_RDWR) != 0); 878 879 return file_cache_read(node->file_cache, cookie, pos, buffer, length); 880 } 881 882 883 static status_t 884 fs_write(fs_volume* _volume, fs_vnode* _node, void* _cookie, off_t pos, 885 const void* buffer, size_t* _length) 886 { 887 CALLED(); 888 volume* volume = (struct volume*)_volume->private_volume; 889 MutexLocker lock(volume->lock); 890 vnode* node = (vnode*)_node->private_node; 891 file_cookie* cookie = (file_cookie*)_cookie; 892 893 if ((node->mode & S_IFDIR) != 0) 894 return B_IS_A_DIRECTORY; 895 896 ASSERT((cookie->open_mode & O_WRONLY) != 0 || (cookie->open_mode & O_RDWR) != 0); 897 898 if (cookie->open_mode & O_APPEND) 899 pos = node->size; 900 if (pos < 0) 901 return B_BAD_VALUE; 902 903 if (pos + s64(*_length) > node->size) { 904 ntfs_inode* ni = ntfs_inode_open(volume->ntfs, node->inode); 905 if (ni == NULL) 906 return errno; 907 NtfsInodeCloser niCloser(ni); 908 909 ntfs_attr* na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); 910 if (na == NULL) 911 return errno; 912 NtfsAttrCloser naCloser(na); 913 914 if (ntfs_attr_truncate(na, pos + *_length) != 0) 915 return errno; 916 node->size = na->data_size; 917 file_cache_set_size(node->file_cache, node->size); 918 } 919 920 lock.Unlock(); 921 922 status_t status = file_cache_write(node->file_cache, cookie, pos, buffer, _length); 923 if (status != B_OK) 924 return status; 925 926 lock.Lock(); 927 928 // periodically notify if the file size has changed 929 if ((node->lowntfs_close_state & CLOSE_GHOST) == 0 930 && cookie->last_size != node->size 931 && system_time() > cookie->last_notification + INODE_NOTIFICATION_INTERVAL) { 932 notify_stat_changed(_volume->id, node->parent_inode, node->inode, 933 B_STAT_MODIFICATION_TIME | B_STAT_SIZE | B_STAT_INTERIM_UPDATE); 934 cookie->last_size = node->size; 935 cookie->last_notification = system_time(); 936 } 937 return status; 938 } 939 940 941 static status_t 942 fs_fsync(fs_volume* _volume, fs_vnode* _node) 943 { 944 CALLED(); 945 vnode* node = (vnode*)_node->private_node; 946 947 return file_cache_sync(node->file_cache); 948 } 949 950 951 static status_t 952 fs_close(fs_volume *_volume, fs_vnode *_node, void *_cookie) 953 { 954 CALLED(); 955 956 // Nothing to do. 957 return B_OK; 958 } 959 960 961 static status_t 962 fs_free_cookie(fs_volume* _volume, fs_vnode* _node, void* _cookie) 963 { 964 file_cookie* cookie = (file_cookie*)_cookie; 965 delete cookie; 966 return B_OK; 967 } 968 969 970 static status_t 971 fs_generic_unlink(fs_volume* _volume, fs_vnode* _directory, const char* name, RM_TYPES type) 972 { 973 volume* volume = (struct volume*)_volume->private_volume; 974 MutexLocker lock(volume->lock); 975 vnode* directory = (vnode*)_directory->private_node; 976 977 status_t status = fs_access(_volume, _directory, W_OK); 978 if (status != B_OK) 979 return status; 980 981 if (ntfs_fuse_rm(&volume->lowntfs, directory->inode, name, type) != 0) 982 return errno; 983 984 // remove_vnode() et al. will be called by put_close_state. 985 return B_OK; 986 } 987 988 989 static status_t 990 fs_unlink(fs_volume* _volume, fs_vnode* _directory, const char* name) 991 { 992 CALLED(); 993 return fs_generic_unlink(_volume, _directory, name, RM_LINK); 994 } 995 996 997 static status_t 998 fs_rename(fs_volume* _volume, fs_vnode* _oldDir, const char* oldName, 999 fs_vnode* _newDir, const char* newName) 1000 { 1001 CALLED(); 1002 volume* volume = (struct volume*)_volume->private_volume; 1003 MutexLocker lock(volume->lock); 1004 1005 vnode* old_directory = (vnode*)_oldDir->private_node; 1006 vnode* new_directory = (vnode*)_newDir->private_node; 1007 1008 if (old_directory == new_directory && strcmp(oldName, newName) == 0) 1009 return B_OK; 1010 1011 status_t status = fs_access(_volume, _oldDir, W_OK); 1012 if (status == B_OK) 1013 status = fs_access(_volume, _newDir, W_OK); 1014 if (status != B_OK) 1015 return status; 1016 1017 // Prevent moving a directory into one of its own children. 1018 if (old_directory != new_directory) { 1019 u64 oldIno = ntfs_fuse_inode_lookup(&volume->lowntfs, old_directory->inode, oldName); 1020 if (oldIno == (u64)-1) 1021 return B_ENTRY_NOT_FOUND; 1022 1023 ino_t parent = new_directory->inode; 1024 const ino_t root = FILE_root; 1025 1026 while (true) { 1027 if (parent == oldIno) 1028 return B_BAD_VALUE; 1029 else if (parent == root || parent == old_directory->inode) 1030 break; 1031 1032 vnode* parentNode; 1033 if (get_vnode(_volume, parent, (void**)&parentNode) != B_OK) 1034 return B_ERROR; 1035 1036 parent = parentNode->parent_inode; 1037 put_vnode(_volume, parentNode->inode); 1038 } 1039 } 1040 1041 if (ntfs_fuse_rename(&volume->lowntfs, old_directory->inode, oldName, 1042 new_directory->inode, newName) != 0) 1043 return errno; 1044 1045 u64 ino = ntfs_fuse_inode_lookup(&volume->lowntfs, new_directory->inode, newName); 1046 if (ino == (u64)-1) 1047 return B_ENTRY_NOT_FOUND; 1048 1049 vnode* node; 1050 status = get_vnode(_volume, ino, (void**)&node); 1051 if (status != B_OK) 1052 return status; 1053 1054 free(node->name); 1055 node->name = strdup(newName); 1056 node->parent_inode = new_directory->inode; 1057 1058 if ((node->mode & S_IFDIR) != 0) 1059 entry_cache_add(_volume->id, ino, "..", new_directory->inode); 1060 1061 put_vnode(_volume, ino); 1062 1063 entry_cache_remove(_volume->id, old_directory->inode, oldName); 1064 entry_cache_add(_volume->id, new_directory->inode, newName, ino); 1065 notify_entry_moved(_volume->id, old_directory->inode, oldName, 1066 new_directory->inode, newName, ino); 1067 1068 return B_OK; 1069 } 1070 1071 1072 static status_t 1073 fs_access(fs_volume* _volume, fs_vnode* _node, int accessMode) 1074 { 1075 // CALLED(); 1076 volume* volume = (struct volume*)_volume->private_volume; 1077 vnode* node = (vnode*)_node->private_node; 1078 1079 if ((accessMode & W_OK) != 0 && (volume->fs_info_flags & B_FS_IS_READONLY) != 0) 1080 return B_READ_ONLY_DEVICE; 1081 1082 return check_access_permissions(accessMode, node->mode, node->gid, node->uid); 1083 } 1084 1085 1086 static status_t 1087 fs_read_link(fs_volume* _volume, fs_vnode* _node, char* buffer, size_t* bufferSize) 1088 { 1089 CALLED(); 1090 volume* volume = (struct volume*)_volume->private_volume; 1091 MutexLocker lock(volume->lock); 1092 vnode* node = (vnode*)_node->private_node; 1093 1094 if (ntfs_fuse_readlink(&volume->lowntfs, node->inode, buffer, bufferSize) != 0) 1095 return errno; 1096 return B_OK; 1097 } 1098 1099 1100 // #pragma mark - Directory functions 1101 1102 1103 static status_t 1104 fs_create_dir(fs_volume* _volume, fs_vnode* _directory, const char* name, int mode) 1105 { 1106 CALLED(); 1107 volume* volume = (struct volume*)_volume->private_volume; 1108 MutexLocker lock(volume->lock); 1109 vnode* directory = (vnode*)_directory->private_node; 1110 1111 status_t status = fs_access(_volume, _directory, W_OK); 1112 if (status != B_OK) 1113 return status; 1114 1115 ino_t inode = -1; 1116 status = fs_generic_create(_volume, directory, name, S_IFDIR | (mode & 07777), &inode); 1117 if (status != B_OK) 1118 return status; 1119 1120 return B_OK; 1121 } 1122 1123 1124 static status_t 1125 fs_remove_dir(fs_volume* _volume, fs_vnode* _directory, const char* name) 1126 { 1127 CALLED(); 1128 ino_t directory_inode = ((vnode*)_directory->private_node)->inode; 1129 status_t status = fs_generic_unlink(_volume, _directory, name, RM_DIR); 1130 if (status != B_OK) 1131 return status; 1132 1133 entry_cache_remove(_volume->id, directory_inode, ".."); 1134 return B_OK; 1135 } 1136 1137 1138 static status_t 1139 fs_open_dir(fs_volume* _volume, fs_vnode* _node, void** _cookie) 1140 { 1141 CALLED(); 1142 vnode* node = (vnode*)_node->private_node; 1143 1144 status_t status = fs_access(_volume, _node, R_OK); 1145 if (status != B_OK) 1146 return status; 1147 1148 if ((node->mode & S_IFDIR) == 0) 1149 return B_NOT_A_DIRECTORY; 1150 1151 directory_cookie* cookie = new directory_cookie; 1152 if (cookie == NULL) 1153 return B_NO_MEMORY; 1154 1155 cookie->first = cookie->current = NULL; 1156 *_cookie = (void*)cookie; 1157 return B_OK; 1158 } 1159 1160 1161 static int 1162 _ntfs_readdir_callback(void* _cookie, const ntfschar* ntfs_name, const int ntfs_name_len, 1163 const int name_type, const s64 pos, const MFT_REF mref, const unsigned dt_type) 1164 { 1165 if (name_type == FILE_NAME_DOS) 1166 return 0; 1167 1168 directory_cookie* cookie = (directory_cookie*)_cookie; 1169 1170 char* name = NULL; 1171 int name_len = ntfs_ucstombs(ntfs_name, ntfs_name_len, &name, 0); 1172 if (name_len <= 0 || name == NULL) 1173 return -1; 1174 MemoryDeleter nameDeleter(name); 1175 1176 directory_cookie::entry* entry = 1177 (directory_cookie::entry*)malloc(sizeof(directory_cookie::entry) + name_len); 1178 if (entry == NULL) 1179 return -1; 1180 entry->next = NULL; 1181 1182 entry->inode = MREF(mref); 1183 entry->name_length = name_len; 1184 memcpy(entry->name, name, name_len + 1); 1185 1186 if (cookie->first == NULL) { 1187 cookie->first = cookie->current = entry; 1188 } else { 1189 cookie->current->next = entry; 1190 cookie->current = entry; 1191 } 1192 1193 return 0; 1194 } 1195 1196 1197 static status_t 1198 fs_read_dir(fs_volume* _volume, fs_vnode* _node, void* _cookie, 1199 struct dirent* dirent, size_t bufferSize, uint32* _num) 1200 { 1201 CALLED(); 1202 directory_cookie* cookie = (directory_cookie*)_cookie; 1203 1204 // TODO: While lowntfs-3g seems to also read the entire directory at once into memory, 1205 // we could optimize things here by storing the data in the vnode, not the inode, and 1206 // only freeing it after some period of inactivity. 1207 1208 // See if we need to read the directory ourselves first. 1209 if (cookie->first == NULL) { 1210 volume* volume = (struct volume*)_volume->private_volume; 1211 MutexLocker lock(volume->lock); 1212 vnode* node = (vnode*)_node->private_node; 1213 1214 ntfs_inode* ni = ntfs_inode_open(volume->ntfs, node->inode); 1215 if (ni == NULL) 1216 return errno; 1217 NtfsInodeCloser niCloser(ni); 1218 1219 s64 pos = 0; 1220 if (ntfs_readdir(ni, &pos, cookie, _ntfs_readdir_callback) != 0) 1221 return errno; 1222 cookie->current = cookie->first; 1223 } 1224 if (cookie->first == NULL) 1225 return ENOENT; 1226 if (cookie->current == NULL) { 1227 *_num = 0; 1228 return B_OK; 1229 } 1230 1231 uint32 maxCount = *_num; 1232 uint32 count = 0; 1233 while (count < maxCount && bufferSize > sizeof(struct dirent)) { 1234 size_t length = bufferSize - offsetof(struct dirent, d_name); 1235 if (length < (cookie->current->name_length + 1)) { 1236 // the remaining name buffer length is too small 1237 if (count == 0) 1238 return B_BUFFER_OVERFLOW; 1239 break; 1240 } 1241 length = cookie->current->name_length; 1242 1243 dirent->d_dev = _volume->id; 1244 dirent->d_ino = cookie->current->inode; 1245 strlcpy(dirent->d_name, cookie->current->name, length + 1); 1246 1247 dirent = next_dirent(dirent, length, bufferSize); 1248 count++; 1249 1250 cookie->current = cookie->current->next; 1251 if (cookie->current == NULL) 1252 break; 1253 } 1254 1255 *_num = count; 1256 return B_OK; 1257 } 1258 1259 1260 static status_t 1261 fs_rewind_dir(fs_volume* /*_volume*/, fs_vnode* /*node*/, void *_cookie) 1262 { 1263 CALLED(); 1264 directory_cookie* cookie = (directory_cookie*)_cookie; 1265 cookie->current = cookie->first; 1266 return B_OK; 1267 } 1268 1269 1270 static status_t 1271 fs_close_dir(fs_volume* /*_volume*/, fs_vnode* /*node*/, void* /*_cookie*/) 1272 { 1273 return B_OK; 1274 } 1275 1276 1277 static status_t 1278 fs_free_dir_cookie(fs_volume* _volume, fs_vnode* _node, void* _cookie) 1279 { 1280 CALLED(); 1281 directory_cookie* cookie = (directory_cookie*)_cookie; 1282 if (cookie == NULL) 1283 return B_OK; 1284 1285 // Free entries. 1286 cookie->current = cookie->first; 1287 while (cookie->current != NULL) { 1288 directory_cookie::entry* next = cookie->current->next; 1289 free(cookie->current); 1290 cookie->current = next; 1291 } 1292 1293 delete cookie; 1294 return B_OK; 1295 } 1296 1297 1298 fs_volume_ops gNtfsVolumeOps = { 1299 &fs_unmount, 1300 &fs_read_fs_info, 1301 &fs_write_fs_info, 1302 NULL, // fs_sync, 1303 &fs_get_vnode, 1304 }; 1305 1306 1307 fs_vnode_ops gNtfsVnodeOps = { 1308 /* vnode operations */ 1309 &fs_lookup, 1310 &fs_get_vnode_name, 1311 &fs_put_vnode, 1312 &fs_remove_vnode, 1313 1314 /* VM file access */ 1315 &fs_can_page, 1316 &fs_read_pages, 1317 &fs_write_pages, 1318 1319 NULL, // io 1320 NULL, // cancel_io 1321 1322 NULL, // get_file_map 1323 1324 &fs_ioctl, 1325 NULL, 1326 NULL, // fs_select 1327 NULL, // fs_deselect 1328 &fs_fsync, 1329 1330 &fs_read_link, 1331 NULL, // fs_create_symlink 1332 1333 NULL, // fs_link, 1334 &fs_unlink, 1335 &fs_rename, 1336 1337 &fs_access, 1338 &fs_read_stat, 1339 &fs_write_stat, 1340 NULL, // fs_preallocate 1341 1342 /* file operations */ 1343 &fs_create, 1344 &fs_open, 1345 &fs_close, 1346 &fs_free_cookie, 1347 &fs_read, 1348 &fs_write, 1349 1350 /* directory operations */ 1351 &fs_create_dir, 1352 &fs_remove_dir, 1353 &fs_open_dir, 1354 &fs_close_dir, 1355 &fs_free_dir_cookie, 1356 &fs_read_dir, 1357 &fs_rewind_dir, 1358 1359 /* attribute directory operations */ 1360 NULL, // fs_open_attr_dir, 1361 NULL, // fs_close_attr_dir, 1362 NULL, // fs_free_attr_dir_cookie, 1363 NULL, // fs_read_attr_dir, 1364 NULL, // fs_rewind_attr_dir, 1365 1366 /* attribute operations */ 1367 NULL, // fs_create_attr, 1368 NULL, // fs_open_attr, 1369 NULL, // fs_close_attr, 1370 NULL, // fs_free_attr_cookie, 1371 NULL, // fs_read_attr, 1372 NULL, // fs_write_attr, 1373 NULL, // fs_read_attr_stat, 1374 NULL, // fs_write_attr_stat, 1375 NULL, // fs_rename_attr, 1376 NULL, // fs_remove_attr, 1377 }; 1378 1379 1380 static file_system_module_info sNtfsFileSystem = { 1381 { 1382 "file_systems/ntfs" B_CURRENT_FS_API_VERSION, 1383 0, 1384 NULL, 1385 }, 1386 1387 "ntfs", // short_name 1388 "NT File System", // pretty_name 1389 1390 // DDM flags 1391 0 1392 | B_DISK_SYSTEM_IS_FILE_SYSTEM 1393 | B_DISK_SYSTEM_SUPPORTS_INITIALIZING 1394 | B_DISK_SYSTEM_SUPPORTS_WRITING 1395 , 1396 1397 // scanning 1398 fs_identify_partition, 1399 fs_scan_partition, 1400 fs_free_identify_partition_cookie, 1401 NULL, // free_partition_content_cookie() 1402 1403 &fs_mount, 1404 1405 // capability querying operations 1406 NULL, // get_supported_operations 1407 1408 NULL, // validate_resize 1409 NULL, // validate_move 1410 NULL, // validate_set_content_name 1411 NULL, // validate_set_content_parameters 1412 NULL, // validate_initialize, 1413 1414 /* shadow partition modification */ 1415 NULL, // shadow_changed 1416 1417 /* writing */ 1418 NULL, // defragment 1419 NULL, // repair 1420 NULL, // resize 1421 NULL, // move 1422 NULL, // set_content_name 1423 NULL, // set_content_parameters 1424 fs_initialize, 1425 NULL // uninitialize 1426 }; 1427 1428 1429 module_info *modules[] = { 1430 (module_info *)&sNtfsFileSystem, 1431 NULL, 1432 }; 1433