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