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 inline int 717 open_mode_to_access(int openMode) 718 { 719 if ((openMode & O_RWMASK) == O_RDONLY) 720 return R_OK; 721 if ((openMode & O_RWMASK) == O_WRONLY) 722 return W_OK; 723 if ((openMode & O_RWMASK) == O_RDWR) 724 return R_OK | W_OK; 725 return 0; 726 } 727 728 729 static status_t 730 fs_generic_create(fs_volume* _volume, vnode* directory, const char* name, int mode, 731 ino_t* _inode) 732 { 733 volume* volume = (struct volume*)_volume->private_volume; 734 ASSERT_LOCKED_MUTEX(&volume->lock); 735 736 if ((directory->mode & S_IFDIR) == 0) 737 return B_BAD_TYPE; 738 739 ino_t inode = -1; 740 if (ntfs_fuse_create(&volume->lowntfs, directory->inode, name, mode & (S_IFMT | 07777), 741 0, (char*)NULL, &inode) != 0) 742 return errno; 743 744 vnode* node; 745 status_t status = fs_init_vnode(_volume, directory->inode, inode, &node, true); 746 if (status != B_OK) 747 return status; 748 749 entry_cache_add(_volume->id, directory->inode, name, inode); 750 notify_entry_created(_volume->id, directory->inode, name, inode); 751 *_inode = inode; 752 return B_OK; 753 } 754 755 756 static status_t 757 fs_create(fs_volume* _volume, fs_vnode* _directory, const char* name, 758 int openMode, int mode, void** _cookie, ino_t* _vnodeID) 759 { 760 CALLED(); 761 volume* volume = (struct volume*)_volume->private_volume; 762 MutexLocker lock(volume->lock); 763 vnode* directory = (vnode*)_directory->private_node; 764 765 if ((directory->mode & S_IFDIR) == 0) 766 return B_NOT_A_DIRECTORY; 767 768 status_t status = fs_access(_volume, _directory, W_OK); 769 if (status != B_OK) 770 return status; 771 772 #if 1 773 if ((openMode & O_NOCACHE) != 0) 774 return B_UNSUPPORTED; 775 #endif 776 777 status = fs_generic_create(_volume, directory, name, S_IFREG | (mode & 07777), _vnodeID); 778 if (status != B_OK) 779 return status; 780 781 file_cookie* cookie = new file_cookie; 782 if (cookie == NULL) 783 return B_NO_MEMORY; 784 ObjectDeleter<file_cookie> cookieDeleter(cookie); 785 786 cookie->open_mode = openMode; 787 788 cookieDeleter.Detach(); 789 *_cookie = cookie; 790 return B_OK; 791 } 792 793 794 static status_t 795 fs_open(fs_volume* _volume, fs_vnode* _node, int openMode, void** _cookie) 796 { 797 CALLED(); 798 volume* volume = (struct volume*)_volume->private_volume; 799 MutexLocker lock(volume->lock); 800 vnode* node = (vnode*)_node->private_node; 801 802 // opening a directory read-only is allowed (but no data can be read) 803 if ((node->mode & S_IFDIR) != 0 && (openMode & O_RWMASK) != 0) 804 return B_IS_A_DIRECTORY; 805 if ((openMode & O_DIRECTORY) != 0 && (node->mode & S_IFDIR) == 0) 806 return B_NOT_A_DIRECTORY; 807 808 status_t status = fs_access(_volume, _node, open_mode_to_access(openMode)); 809 if (status != B_OK) 810 return status; 811 812 ntfs_inode* ni = ntfs_inode_open(volume->ntfs, node->inode); 813 if (ni == NULL) 814 return errno; 815 NtfsInodeCloser niCloser(ni); 816 817 file_cookie* cookie = new file_cookie; 818 if (cookie == NULL) 819 return B_NO_MEMORY; 820 ObjectDeleter<file_cookie> cookieDeleter(cookie); 821 822 cookie->open_mode = openMode; 823 824 // We don't actually support uncached mode; it would require us to handle 825 // passing user buffers to libntfs, among other things. 826 #if 0 827 if ((openMode & O_NOCACHE) != 0 && node->file_cache != NULL) { 828 status_t status = file_cache_disable(node->file_cache); 829 if (status != B_OK) 830 return status; 831 } 832 #else 833 if ((openMode & O_NOCACHE) != 0) 834 return B_UNSUPPORTED; 835 #endif 836 837 if ((openMode & O_TRUNC) != 0) { 838 if ((openMode & O_RWMASK) == O_RDONLY) 839 return B_NOT_ALLOWED; 840 841 ntfs_attr* na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); 842 if (na == NULL) 843 return errno; 844 NtfsAttrCloser naCloser(na); 845 846 if (ntfs_attr_truncate(na, 0) != 0) 847 return errno; 848 node->size = na->data_size; 849 file_cache_set_size(node->file_cache, node->size); 850 } 851 852 cookieDeleter.Detach(); 853 *_cookie = cookie; 854 return B_OK; 855 } 856 857 858 static status_t 859 fs_read(fs_volume* _volume, fs_vnode* _node, void* _cookie, off_t pos, 860 void* buffer, size_t* length) 861 { 862 vnode* node = (vnode*)_node->private_node; 863 file_cookie* cookie = (file_cookie*)_cookie; 864 865 if ((node->mode & S_IFDIR) != 0) 866 return B_IS_A_DIRECTORY; 867 868 ASSERT((cookie->open_mode & O_RWMASK) == O_RDONLY || (cookie->open_mode & O_RDWR) != 0); 869 870 return file_cache_read(node->file_cache, cookie, pos, buffer, length); 871 } 872 873 874 static status_t 875 fs_write(fs_volume* _volume, fs_vnode* _node, void* _cookie, off_t pos, 876 const void* buffer, size_t* _length) 877 { 878 CALLED(); 879 volume* volume = (struct volume*)_volume->private_volume; 880 MutexLocker lock(volume->lock); 881 vnode* node = (vnode*)_node->private_node; 882 file_cookie* cookie = (file_cookie*)_cookie; 883 884 if ((node->mode & S_IFDIR) != 0) 885 return B_IS_A_DIRECTORY; 886 887 ASSERT((cookie->open_mode & O_WRONLY) != 0 || (cookie->open_mode & O_RDWR) != 0); 888 889 if (cookie->open_mode & O_APPEND) 890 pos = node->size; 891 if (pos < 0) 892 return B_BAD_VALUE; 893 894 if (pos + s64(*_length) > node->size) { 895 ntfs_inode* ni = ntfs_inode_open(volume->ntfs, node->inode); 896 if (ni == NULL) 897 return errno; 898 NtfsInodeCloser niCloser(ni); 899 900 ntfs_attr* na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); 901 if (na == NULL) 902 return errno; 903 NtfsAttrCloser naCloser(na); 904 905 if (ntfs_attr_truncate(na, pos + *_length) != 0) 906 return errno; 907 node->size = na->data_size; 908 file_cache_set_size(node->file_cache, node->size); 909 } 910 911 lock.Unlock(); 912 913 status_t status = file_cache_write(node->file_cache, cookie, pos, buffer, _length); 914 if (status != B_OK) 915 return status; 916 917 lock.Lock(); 918 919 // periodically notify if the file size has changed 920 if ((node->lowntfs_close_state & CLOSE_GHOST) == 0 921 && cookie->last_size != node->size 922 && system_time() > cookie->last_notification + INODE_NOTIFICATION_INTERVAL) { 923 notify_stat_changed(_volume->id, node->parent_inode, node->inode, 924 B_STAT_MODIFICATION_TIME | B_STAT_SIZE | B_STAT_INTERIM_UPDATE); 925 cookie->last_size = node->size; 926 cookie->last_notification = system_time(); 927 } 928 return status; 929 } 930 931 932 static status_t 933 fs_fsync(fs_volume* _volume, fs_vnode* _node) 934 { 935 CALLED(); 936 vnode* node = (vnode*)_node->private_node; 937 938 return file_cache_sync(node->file_cache); 939 } 940 941 942 static status_t 943 fs_close(fs_volume *_volume, fs_vnode *_node, void *_cookie) 944 { 945 CALLED(); 946 947 // Nothing to do. 948 return B_OK; 949 } 950 951 952 static status_t 953 fs_free_cookie(fs_volume* _volume, fs_vnode* _node, void* _cookie) 954 { 955 file_cookie* cookie = (file_cookie*)_cookie; 956 delete cookie; 957 return B_OK; 958 } 959 960 961 static status_t 962 fs_generic_unlink(fs_volume* _volume, fs_vnode* _directory, const char* name, RM_TYPES type) 963 { 964 volume* volume = (struct volume*)_volume->private_volume; 965 MutexLocker lock(volume->lock); 966 vnode* directory = (vnode*)_directory->private_node; 967 968 status_t status = fs_access(_volume, _directory, W_OK); 969 if (status != B_OK) 970 return status; 971 972 if (ntfs_fuse_rm(&volume->lowntfs, directory->inode, name, type) != 0) 973 return errno; 974 975 // remove_vnode() et al. will be called by put_close_state. 976 return B_OK; 977 } 978 979 980 static status_t 981 fs_unlink(fs_volume* _volume, fs_vnode* _directory, const char* name) 982 { 983 CALLED(); 984 return fs_generic_unlink(_volume, _directory, name, RM_LINK); 985 } 986 987 988 static status_t 989 fs_rename(fs_volume* _volume, fs_vnode* _oldDir, const char* oldName, 990 fs_vnode* _newDir, const char* newName) 991 { 992 CALLED(); 993 volume* volume = (struct volume*)_volume->private_volume; 994 MutexLocker lock(volume->lock); 995 996 vnode* old_directory = (vnode*)_oldDir->private_node; 997 vnode* new_directory = (vnode*)_newDir->private_node; 998 999 if (old_directory == new_directory && strcmp(oldName, newName) == 0) 1000 return B_OK; 1001 1002 status_t status = fs_access(_volume, _oldDir, W_OK); 1003 if (status == B_OK) 1004 status = fs_access(_volume, _newDir, W_OK); 1005 if (status != B_OK) 1006 return status; 1007 1008 // Prevent moving a directory into one of its own children. 1009 if (old_directory != new_directory) { 1010 u64 oldIno = ntfs_fuse_inode_lookup(&volume->lowntfs, old_directory->inode, oldName); 1011 if (oldIno == (u64)-1) 1012 return B_ENTRY_NOT_FOUND; 1013 1014 ino_t parent = new_directory->inode; 1015 const ino_t root = FILE_root; 1016 1017 while (true) { 1018 if (parent == oldIno) 1019 return B_BAD_VALUE; 1020 else if (parent == root || parent == old_directory->inode) 1021 break; 1022 1023 vnode* parentNode; 1024 if (get_vnode(_volume, parent, (void**)&parentNode) != B_OK) 1025 return B_ERROR; 1026 1027 parent = parentNode->parent_inode; 1028 put_vnode(_volume, parentNode->inode); 1029 } 1030 } 1031 1032 if (ntfs_fuse_rename(&volume->lowntfs, old_directory->inode, oldName, 1033 new_directory->inode, newName) != 0) 1034 return errno; 1035 1036 u64 ino = ntfs_fuse_inode_lookup(&volume->lowntfs, new_directory->inode, newName); 1037 if (ino == (u64)-1) 1038 return B_ENTRY_NOT_FOUND; 1039 1040 vnode* node; 1041 status = get_vnode(_volume, ino, (void**)&node); 1042 if (status != B_OK) 1043 return status; 1044 1045 free(node->name); 1046 node->name = strdup(newName); 1047 node->parent_inode = new_directory->inode; 1048 1049 if ((node->mode & S_IFDIR) != 0) 1050 entry_cache_add(_volume->id, ino, "..", new_directory->inode); 1051 1052 put_vnode(_volume, ino); 1053 1054 entry_cache_remove(_volume->id, old_directory->inode, oldName); 1055 entry_cache_add(_volume->id, new_directory->inode, newName, ino); 1056 notify_entry_moved(_volume->id, old_directory->inode, oldName, 1057 new_directory->inode, newName, ino); 1058 1059 return B_OK; 1060 } 1061 1062 1063 static status_t 1064 fs_access(fs_volume* _volume, fs_vnode* _node, int accessMode) 1065 { 1066 // CALLED(); 1067 volume* volume = (struct volume*)_volume->private_volume; 1068 vnode* node = (vnode*)_node->private_node; 1069 1070 if ((accessMode & W_OK) != 0 && (volume->fs_info_flags & B_FS_IS_READONLY) != 0) 1071 return B_READ_ONLY_DEVICE; 1072 1073 return check_access_permissions(accessMode, node->mode, node->gid, node->uid); 1074 } 1075 1076 1077 static status_t 1078 fs_read_link(fs_volume* _volume, fs_vnode* _node, char* buffer, size_t* bufferSize) 1079 { 1080 CALLED(); 1081 volume* volume = (struct volume*)_volume->private_volume; 1082 MutexLocker lock(volume->lock); 1083 vnode* node = (vnode*)_node->private_node; 1084 1085 if (ntfs_fuse_readlink(&volume->lowntfs, node->inode, buffer, bufferSize) != 0) 1086 return errno; 1087 return B_OK; 1088 } 1089 1090 1091 // #pragma mark - Directory functions 1092 1093 1094 static status_t 1095 fs_create_dir(fs_volume* _volume, fs_vnode* _directory, const char* name, int mode) 1096 { 1097 CALLED(); 1098 volume* volume = (struct volume*)_volume->private_volume; 1099 MutexLocker lock(volume->lock); 1100 vnode* directory = (vnode*)_directory->private_node; 1101 1102 status_t status = fs_access(_volume, _directory, W_OK); 1103 if (status != B_OK) 1104 return status; 1105 1106 ino_t inode = -1; 1107 status = fs_generic_create(_volume, directory, name, S_IFDIR | (mode & 07777), &inode); 1108 if (status != B_OK) 1109 return status; 1110 1111 return B_OK; 1112 } 1113 1114 1115 static status_t 1116 fs_remove_dir(fs_volume* _volume, fs_vnode* _directory, const char* name) 1117 { 1118 CALLED(); 1119 ino_t directory_inode = ((vnode*)_directory->private_node)->inode; 1120 status_t status = fs_generic_unlink(_volume, _directory, name, RM_DIR); 1121 if (status != B_OK) 1122 return status; 1123 1124 entry_cache_remove(_volume->id, directory_inode, ".."); 1125 return B_OK; 1126 } 1127 1128 1129 static status_t 1130 fs_open_dir(fs_volume* _volume, fs_vnode* _node, void** _cookie) 1131 { 1132 CALLED(); 1133 vnode* node = (vnode*)_node->private_node; 1134 1135 status_t status = fs_access(_volume, _node, R_OK); 1136 if (status != B_OK) 1137 return status; 1138 1139 if ((node->mode & S_IFDIR) == 0) 1140 return B_NOT_A_DIRECTORY; 1141 1142 directory_cookie* cookie = new directory_cookie; 1143 if (cookie == NULL) 1144 return B_NO_MEMORY; 1145 1146 cookie->first = cookie->current = NULL; 1147 *_cookie = (void*)cookie; 1148 return B_OK; 1149 } 1150 1151 1152 static int 1153 _ntfs_readdir_callback(void* _cookie, const ntfschar* ntfs_name, const int ntfs_name_len, 1154 const int name_type, const s64 pos, const MFT_REF mref, const unsigned dt_type) 1155 { 1156 if (name_type == FILE_NAME_DOS) 1157 return 0; 1158 1159 directory_cookie* cookie = (directory_cookie*)_cookie; 1160 1161 char* name = NULL; 1162 int name_len = ntfs_ucstombs(ntfs_name, ntfs_name_len, &name, 0); 1163 if (name_len <= 0 || name == NULL) 1164 return -1; 1165 MemoryDeleter nameDeleter(name); 1166 1167 directory_cookie::entry* entry = 1168 (directory_cookie::entry*)malloc(sizeof(directory_cookie::entry) + name_len); 1169 if (entry == NULL) 1170 return -1; 1171 entry->next = NULL; 1172 1173 entry->inode = MREF(mref); 1174 entry->name_length = name_len; 1175 memcpy(entry->name, name, name_len + 1); 1176 1177 if (cookie->first == NULL) { 1178 cookie->first = cookie->current = entry; 1179 } else { 1180 cookie->current->next = entry; 1181 cookie->current = entry; 1182 } 1183 1184 return 0; 1185 } 1186 1187 1188 static status_t 1189 fs_read_dir(fs_volume* _volume, fs_vnode* _node, void* _cookie, 1190 struct dirent* dirent, size_t bufferSize, uint32* _num) 1191 { 1192 CALLED(); 1193 directory_cookie* cookie = (directory_cookie*)_cookie; 1194 1195 // TODO: While lowntfs-3g seems to also read the entire directory at once into memory, 1196 // we could optimize things here by storing the data in the vnode, not the inode, and 1197 // only freeing it after some period of inactivity. 1198 1199 // See if we need to read the directory ourselves first. 1200 if (cookie->first == NULL) { 1201 volume* volume = (struct volume*)_volume->private_volume; 1202 MutexLocker lock(volume->lock); 1203 vnode* node = (vnode*)_node->private_node; 1204 1205 ntfs_inode* ni = ntfs_inode_open(volume->ntfs, node->inode); 1206 if (ni == NULL) 1207 return errno; 1208 NtfsInodeCloser niCloser(ni); 1209 1210 s64 pos = 0; 1211 if (ntfs_readdir(ni, &pos, cookie, _ntfs_readdir_callback) != 0) 1212 return errno; 1213 cookie->current = cookie->first; 1214 } 1215 if (cookie->first == NULL) 1216 return ENOENT; 1217 if (cookie->current == NULL) { 1218 *_num = 0; 1219 return B_OK; 1220 } 1221 1222 uint32 maxCount = *_num; 1223 uint32 count = 0; 1224 while (count < maxCount && bufferSize > sizeof(struct dirent)) { 1225 size_t length = bufferSize - offsetof(struct dirent, d_name); 1226 if (length < cookie->current->name_length) { 1227 // the remaining name buffer length is too small 1228 if (count == 0) 1229 return B_BUFFER_OVERFLOW; 1230 break; 1231 } 1232 length = cookie->current->name_length; 1233 1234 dirent->d_dev = _volume->id; 1235 dirent->d_ino = cookie->current->inode; 1236 strlcpy(dirent->d_name, cookie->current->name, length + 1); 1237 1238 dirent = next_dirent(dirent, length, bufferSize); 1239 count++; 1240 1241 cookie->current = cookie->current->next; 1242 if (cookie->current == NULL) 1243 break; 1244 } 1245 1246 *_num = count; 1247 return B_OK; 1248 } 1249 1250 1251 static status_t 1252 fs_rewind_dir(fs_volume* /*_volume*/, fs_vnode* /*node*/, void *_cookie) 1253 { 1254 CALLED(); 1255 directory_cookie* cookie = (directory_cookie*)_cookie; 1256 cookie->current = cookie->first; 1257 return B_OK; 1258 } 1259 1260 1261 static status_t 1262 fs_close_dir(fs_volume* /*_volume*/, fs_vnode* /*node*/, void* /*_cookie*/) 1263 { 1264 return B_OK; 1265 } 1266 1267 1268 static status_t 1269 fs_free_dir_cookie(fs_volume* _volume, fs_vnode* _node, void* _cookie) 1270 { 1271 CALLED(); 1272 directory_cookie* cookie = (directory_cookie*)_cookie; 1273 if (cookie == NULL) 1274 return B_OK; 1275 1276 // Free entries. 1277 cookie->current = cookie->first; 1278 while (cookie->current != NULL) { 1279 directory_cookie::entry* next = cookie->current->next; 1280 free(cookie->current); 1281 cookie->current = next; 1282 } 1283 1284 delete cookie; 1285 return B_OK; 1286 } 1287 1288 1289 fs_volume_ops gNtfsVolumeOps = { 1290 &fs_unmount, 1291 &fs_read_fs_info, 1292 &fs_write_fs_info, 1293 NULL, // fs_sync, 1294 &fs_get_vnode, 1295 }; 1296 1297 1298 fs_vnode_ops gNtfsVnodeOps = { 1299 /* vnode operations */ 1300 &fs_lookup, 1301 &fs_get_vnode_name, 1302 &fs_put_vnode, 1303 &fs_remove_vnode, 1304 1305 /* VM file access */ 1306 &fs_can_page, 1307 &fs_read_pages, 1308 &fs_write_pages, 1309 1310 NULL, // io 1311 NULL, // cancel_io 1312 1313 NULL, // get_file_map 1314 1315 &fs_ioctl, 1316 NULL, 1317 NULL, // fs_select 1318 NULL, // fs_deselect 1319 &fs_fsync, 1320 1321 &fs_read_link, 1322 NULL, // fs_create_symlink 1323 1324 NULL, // fs_link, 1325 &fs_unlink, 1326 &fs_rename, 1327 1328 &fs_access, 1329 &fs_read_stat, 1330 &fs_write_stat, 1331 NULL, // fs_preallocate 1332 1333 /* file operations */ 1334 &fs_create, 1335 &fs_open, 1336 &fs_close, 1337 &fs_free_cookie, 1338 &fs_read, 1339 &fs_write, 1340 1341 /* directory operations */ 1342 &fs_create_dir, 1343 &fs_remove_dir, 1344 &fs_open_dir, 1345 &fs_close_dir, 1346 &fs_free_dir_cookie, 1347 &fs_read_dir, 1348 &fs_rewind_dir, 1349 1350 /* attribute directory operations */ 1351 NULL, // fs_open_attr_dir, 1352 NULL, // fs_close_attr_dir, 1353 NULL, // fs_free_attr_dir_cookie, 1354 NULL, // fs_read_attr_dir, 1355 NULL, // fs_rewind_attr_dir, 1356 1357 /* attribute operations */ 1358 NULL, // fs_create_attr, 1359 NULL, // fs_open_attr, 1360 NULL, // fs_close_attr, 1361 NULL, // fs_free_attr_cookie, 1362 NULL, // fs_read_attr, 1363 NULL, // fs_write_attr, 1364 NULL, // fs_read_attr_stat, 1365 NULL, // fs_write_attr_stat, 1366 NULL, // fs_rename_attr, 1367 NULL, // fs_remove_attr, 1368 }; 1369 1370 1371 static file_system_module_info sNtfsFileSystem = { 1372 { 1373 "file_systems/ntfs" B_CURRENT_FS_API_VERSION, 1374 0, 1375 NULL, 1376 }, 1377 1378 "ntfs", // short_name 1379 "NT File System", // pretty_name 1380 1381 // DDM flags 1382 0 1383 | B_DISK_SYSTEM_IS_FILE_SYSTEM 1384 | B_DISK_SYSTEM_SUPPORTS_INITIALIZING 1385 | B_DISK_SYSTEM_SUPPORTS_WRITING 1386 , 1387 1388 // scanning 1389 fs_identify_partition, 1390 fs_scan_partition, 1391 fs_free_identify_partition_cookie, 1392 NULL, // free_partition_content_cookie() 1393 1394 &fs_mount, 1395 1396 // capability querying operations 1397 NULL, // get_supported_operations 1398 1399 NULL, // validate_resize 1400 NULL, // validate_move 1401 NULL, // validate_set_content_name 1402 NULL, // validate_set_content_parameters 1403 NULL, // validate_initialize, 1404 1405 /* shadow partition modification */ 1406 NULL, // shadow_changed 1407 1408 /* writing */ 1409 NULL, // defragment 1410 NULL, // repair 1411 NULL, // resize 1412 NULL, // move 1413 NULL, // set_content_name 1414 NULL, // set_content_parameters 1415 fs_initialize, 1416 NULL // uninitialize 1417 }; 1418 1419 1420 module_info *modules[] = { 1421 (module_info *)&sNtfsFileSystem, 1422 NULL, 1423 }; 1424