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