int ntfsMountAll (ntfs_md **mounts, u32 flags) { const INTERFACE_ID *discs = ntfsGetDiscInterfaces(); const INTERFACE_ID *disc = NULL; ntfs_md mount_points[NTFS_MAX_MOUNTS]; sec_t *partitions = NULL; int mount_count = 0; int partition_count = 0; char name[128]; int i, j, k; // Initialise ntfs-3g ntfsInit(); // Find and mount all NTFS partitions on all known devices for (i = 0; discs[i].name != NULL && discs[i].interface != NULL; i++) { disc = &discs[i]; partition_count = ntfsFindPartitions(disc->interface, &partitions); if (partition_count > 0 && partitions) { for (j = 0, k = 0; j < partition_count; j++) { // Find the next unused mount name do { sprintf(name, "%s%i", NTFS_MOUNT_PREFIX, k++); if (k >= NTFS_MAX_MOUNTS) { ntfs_free(partitions); errno = EADDRNOTAVAIL; return -1; } } while (ntfsGetDevice(name, false)); // Mount the partition if (mount_count < NTFS_MAX_MOUNTS) { if (ntfsMount(name, disc->interface, partitions[j], CACHE_DEFAULT_PAGE_SIZE, CACHE_DEFAULT_PAGE_COUNT, flags)) { strcpy(mount_points[mount_count].name, name); mount_points[mount_count].interface = disc->interface; mount_points[mount_count].startSector = partitions[j]; mount_count++; } } } ntfs_free(partitions); } } // Return the mounts (if any) if (mount_count > 0 && mounts) { *mounts = (ntfs_md*)ntfs_alloc(sizeof(ntfs_md) * mount_count); if (*mounts) { memcpy(*mounts, &mount_points, sizeof(ntfs_md) * mount_count); return mount_count; } } return 0; }
s32 MountNTFS(u32 sector) { s32 ret; if (fs_ntfs_mount) return 0; //printf("mounting NTFS\n"); //Wpad_WaitButtons(); _FAT_mem_init(); ntfsInit(); // Call ntfs init here, to prevent locale resets // ntfsInit resets locale settings // which breaks unicode in console // so we change it back to C-UTF-8 setlocale(LC_CTYPE, "C-UTF-8"); setlocale(LC_MESSAGES, "C-UTF-8"); if (wbfsDev == WBFS_DEVICE_USB) { /* Initialize WBFS interface */ // if (!__io_wiiums.startup()) { ret = __io_usbstorage2.startup(); if (!ret) { return -1; } // } /* Mount device */ // if (!ntfsMount("NTFS", &__io_wiiums, sector, CACHE, SECTORS, NTFS_SHOW_HIDDEN_FILES | NTFS_RECOVER)) { ret = ntfsMount("NTFS", &__io_usbstorage2, sector, CACHE, SECTORS, NTFS_SHOW_HIDDEN_FILES | NTFS_READ_ONLY | NTFS_RECOVER); if (!ret) { return -2; } // } } else if (wbfsDev == WBFS_DEVICE_SDHC) { if (sdhc_mode_sd == 0) { ret = ntfsMount("NTFS", &__io_sdhc, 0, CACHE, SECTORS, NTFS_SHOW_HIDDEN_FILES | NTFS_READ_ONLY | NTFS_RECOVER); } else { ret = ntfsMount("NTFS", &__io_sdhc, 0, CACHE, SECTORS_SD, NTFS_SHOW_HIDDEN_FILES | NTFS_READ_ONLY | NTFS_RECOVER); } if (!ret) { return -5; } } fs_ntfs_mount = 1; fs_ntfs_sec = sector; //_FAT_startSector; return 0; }
int ntfsFindPartitions (const DISC_INTERFACE *interface, sec_t **partitions) { MASTER_BOOT_RECORD mbr; PARTITION_RECORD *partition = NULL; sec_t partition_starts[NTFS_MAX_PARTITIONS] = {0}; int partition_count = 0; sec_t part_lba = 0; int i; union { u8 buffer[BYTES_PER_SECTOR]; MASTER_BOOT_RECORD mbr; EXTENDED_BOOT_RECORD ebr; NTFS_BOOT_SECTOR boot; } sector; // Sanity check if (!interface) { errno = EINVAL; return -1; } if (!partitions) return 0; // Initialise ntfs-3g ntfsInit(); // Start the device and check that it is inserted if (!interface->startup()) { errno = EIO; return -1; } if (!interface->isInserted()) { return 0; } // Read the first sector on the device if (!interface->readSectors(0, 1, §or.buffer)) { errno = EIO; return -1; } // If this is the devices master boot record if (sector.mbr.signature == MBR_SIGNATURE) { memcpy(&mbr, §or, sizeof(MASTER_BOOT_RECORD)); ntfs_log_debug("Valid Master Boot Record found\n"); // Search the partition table for all NTFS partitions (max. 4 primary partitions) for (i = 0; i < 4; i++) { partition = &mbr.partitions[i]; part_lba = le32_to_cpu(mbr.partitions[i].lba_start); ntfs_log_debug("Partition %i: %s, sector %d, type 0x%x\n", i + 1, partition->status == PARTITION_STATUS_BOOTABLE ? "bootable (active)" : "non-bootable", part_lba, partition->type); // Figure out what type of partition this is switch (partition->type) { // Ignore empty partitions case PARTITION_TYPE_EMPTY: continue; // NTFS partition case PARTITION_TYPE_NTFS: { ntfs_log_debug("Partition %i: Claims to be NTFS\n", i + 1); // Read and validate the NTFS partition if (interface->readSectors(part_lba, 1, §or)) { if (sector.boot.oem_id == NTFS_OEM_ID) { ntfs_log_debug("Partition %i: Valid NTFS boot sector found\n", i + 1); if (partition_count < NTFS_MAX_PARTITIONS) { partition_starts[partition_count] = part_lba; partition_count++; } } else { ntfs_log_debug("Partition %i: Invalid NTFS boot sector, not actually NTFS\n", i + 1); } } break; } // DOS 3.3+ or Windows 95 extended partition case PARTITION_TYPE_DOS33_EXTENDED: case PARTITION_TYPE_WIN95_EXTENDED: { ntfs_log_debug("Partition %i: Claims to be Extended\n", i + 1); // Walk the extended partition chain, finding all NTFS partitions within it sec_t ebr_lba = part_lba; sec_t next_erb_lba = 0; do { // Read and validate the extended boot record if (interface->readSectors(ebr_lba + next_erb_lba, 1, §or)) { if (sector.ebr.signature == EBR_SIGNATURE) { ntfs_log_debug("Logical Partition @ %d: type 0x%x\n", ebr_lba + next_erb_lba, sector.ebr.partition.status == PARTITION_STATUS_BOOTABLE ? "bootable (active)" : "non-bootable", sector.ebr.partition.type); // Get the start sector of the current partition // and the next extended boot record in the chain part_lba = ebr_lba + next_erb_lba + le32_to_cpu(sector.ebr.partition.lba_start); next_erb_lba = le32_to_cpu(sector.ebr.next_ebr.lba_start); // Check if this partition has a valid NTFS boot record if (interface->readSectors(part_lba, 1, §or)) { if (sector.boot.oem_id == NTFS_OEM_ID) { ntfs_log_debug("Logical Partition @ %d: Valid NTFS boot sector found\n", part_lba); if(sector.ebr.partition.type != PARTITION_TYPE_NTFS) { ntfs_log_warning("Logical Partition @ %d: Is NTFS but type is 0x%x; 0x%x was expected\n", part_lba, sector.ebr.partition.type, PARTITION_TYPE_NTFS); } if (partition_count < NTFS_MAX_PARTITIONS) { partition_starts[partition_count] = part_lba; partition_count++; } } } } else { next_erb_lba = 0; } } } while (next_erb_lba); break; } // Unknown or unsupported partition type default: { // Check if this partition has a valid NTFS boot record anyway, // it might be misrepresented due to a lazy partition editor if (interface->readSectors(part_lba, 1, §or)) { if (sector.boot.oem_id == NTFS_OEM_ID) { ntfs_log_debug("Partition %i: Valid NTFS boot sector found\n", i + 1); if(partition->type != PARTITION_TYPE_NTFS) { ntfs_log_warning("Partition %i: Is NTFS but type is 0x%x; 0x%x was expected\n", i + 1, partition->type, PARTITION_TYPE_NTFS); } if (partition_count < NTFS_MAX_PARTITIONS) { partition_starts[partition_count] = part_lba; partition_count++; } } } break; } } } // Else it is assumed this device has no master boot record } else { ntfs_log_debug("No Master Boot Record was found!\n"); // As a last-ditched effort, search the first 64 sectors of the device for stray NTFS partitions for (i = 0; i < 64; i++) { if (interface->readSectors(i, 1, §or)) { if (sector.boot.oem_id == NTFS_OEM_ID) { ntfs_log_debug("Valid NTFS boot sector found at sector %d!\n", i); if (partition_count < NTFS_MAX_PARTITIONS) { partition_starts[partition_count] = i; partition_count++; } } } } } // Shutdown the device /*interface->shutdown();*/ // Return the found partitions (if any) if (partition_count > 0) { *partitions = (sec_t*)ntfs_alloc(sizeof(sec_t) * partition_count); if (*partitions) { memcpy(*partitions, &partition_starts, sizeof(sec_t) * partition_count); return partition_count; } } return 0; }
bool ntfsMount (const char *name, const DISC_INTERFACE *interface, sec_t startSector, u32 cachePageCount, u32 cachePageSize, u32 flags) { ntfs_vd *vd = NULL; gekko_fd *fd = NULL; // Sanity check if (!name || !interface) { errno = EINVAL; return -1; } // Initialise ntfs-3g ntfsInit(); // Check that the requested mount name is free if (ntfsGetDevice(name, false)) { errno = EADDRINUSE; return false; } // Check that we can at least read from this device if (!(interface->features & FEATURE_MEDIUM_CANREAD)) { errno = EPERM; return false; } // Allocate the volume descriptor vd = (ntfs_vd*)ntfs_alloc(sizeof(ntfs_vd)); if (!vd) { errno = ENOMEM; return false; } // Setup the volume descriptor vd->id = interface->ioType; vd->flags = 0; vd->uid = 0; vd->gid = 0; vd->fmask = 0; vd->dmask = 0; vd->atime = ((flags & NTFS_UPDATE_ACCESS_TIMES) ? ATIME_ENABLED : ATIME_DISABLED); vd->showHiddenFiles = (flags & NTFS_SHOW_HIDDEN_FILES); vd->showSystemFiles = (flags & NTFS_SHOW_SYSTEM_FILES); // Allocate the device driver descriptor fd = (gekko_fd*)ntfs_alloc(sizeof(gekko_fd)); if (!fd) { ntfs_free(vd); errno = ENOMEM; return false; } // Setup the device driver descriptor fd->interface = interface; fd->startSector = startSector; fd->sectorSize = 0; fd->sectorCount = 0; fd->cachePageCount = cachePageCount; fd->cachePageSize = cachePageSize; // Allocate the device driver vd->dev = ntfs_device_alloc(name, 0, &ntfs_device_gekko_io_ops, fd); if (!vd->dev) { ntfs_free(fd); ntfs_free(vd); return false; } // Build the mount flags if (flags & NTFS_READ_ONLY) vd->flags |= MS_RDONLY; else { if (!(interface->features & FEATURE_MEDIUM_CANWRITE)) vd->flags |= MS_RDONLY; if ((interface->features & FEATURE_MEDIUM_CANREAD) && (interface->features & FEATURE_MEDIUM_CANWRITE)) vd->flags |= MS_EXCLUSIVE; } if (flags & NTFS_RECOVER) vd->flags |= MS_RECOVER; if (flags & NTFS_IGNORE_HIBERFILE) vd->flags |= MS_IGNORE_HIBERFILE; if (vd->flags & MS_RDONLY) ntfs_log_debug("Mounting \"%s\" as read-only\n", name); // Mount the device vd->vol = ntfs_device_mount(vd->dev, vd->flags); if (!vd->vol) { switch(ntfs_volume_error(errno)) { case NTFS_VOLUME_NOT_NTFS: errno = EINVALPART; break; case NTFS_VOLUME_CORRUPT: errno = EINVALPART; break; case NTFS_VOLUME_HIBERNATED: errno = EHIBERNATED; break; case NTFS_VOLUME_UNCLEAN_UNMOUNT: errno = EDIRTY; break; default: errno = EINVAL; break; } ntfs_device_free(vd->dev); ntfs_free(vd); return false; } // Initialise the volume descriptor if (ntfsInitVolume(vd)) { ntfs_umount(vd->vol, true); ntfs_free(vd); return false; } // Add the device to the devoptab table if (ntfsAddDevice(name, vd)) { ntfsDeinitVolume(vd); ntfs_umount(vd->vol, true); ntfs_free(vd); return false; } return true; }
ntfs_vd *ntfsMount (const char *name, struct _NTFS_VOLUME *interface, sec_t startSector, u32 cachePageCount, u32 cachePageSize, u32 flags) { ntfs_vd *vd = NULL; struct _uefi_fd *fd = NULL; const devoptab_t *mnt; //Print(L"ntfsMount %a\n", name); //CpuBreakpoint(); // Sanity check if (!name || !interface) { //Print(L"ntfsMount EINVAL\n"); errno = EINVAL; return false; } // Initialise ntfs-3g ntfsInit(); mnt = ntfsGetDevice(name, false); // Check that the requested mount name is free if (mnt) { //Print(L"ntfsMount EADDRINUSE\n"); errno = 99; //EADDRINUSE; return (ntfs_vd*) mnt->deviceData; // previous mnt data! } // Allocate the volume descriptor vd = (ntfs_vd*)ntfs_alloc(sizeof(ntfs_vd)); if (!vd) { //Print(L"ntfsMount ENOMEM\n"); errno = ENOMEM; return false; } else { //Print(L"ntfsMount ntfs_vd!\n"); } // Setup the volume descriptor //Print(L"vd.id! [%x]\n", vd); vd->id = 0;//interface->ioType; //Print(L"vd.flags!\n"); vd->flags = 0; vd->uid = 0; vd->gid = 0; vd->fmask = 0; vd->dmask = 0; vd->atime = ((flags & NTFS_UPDATE_ACCESS_TIMES) ? ATIME_ENABLED : ATIME_DISABLED); vd->showHiddenFiles = (flags & NTFS_SHOW_HIDDEN_FILES); vd->showSystemFiles = (flags & NTFS_SHOW_SYSTEM_FILES); //Print(L"invoking ntfs_alloc!\n"); // Allocate the device driver descriptor fd = (struct _uefi_fd *)ntfs_alloc(sizeof(struct _uefi_fd)); if (!fd) { //Print(L"ntfsMount ENOMEM(2)\n"); ntfs_free(vd); errno = ENOMEM; return false; } else { //Print(L"ntfs_alloc uefi_fd\n"); } // Setup the device driver descriptor fd->interface = interface; fd->startSector = startSector; fd->sectorSize = 0x200; fd->sectorCount = 0x200; fd->cachePageCount = cachePageCount; fd->cachePageSize = cachePageSize; // Allocate the device driver vd->dev = ntfs_device_alloc(name, 0, &ntfs_device_uefi_io_ops, fd); if (!vd->dev) { //Print(L"ntfsMount ntfs_device_alloc failed\n"); ntfs_free(fd); ntfs_free(vd); return false; } //Print(L"ntfs_device_alloc success\n"); // Build the mount flags if (flags & NTFS_READ_ONLY) vd->flags |= NTFS_MNT_RDONLY; if (flags & NTFS_RECOVER) vd->flags |= NTFS_MNT_RECOVER; if (flags & NTFS_IGNORE_HIBERFILE) vd->flags |= NTFS_MNT_IGNORE_HIBERFILE; if (vd->flags & NTFS_MNT_RDONLY) ntfs_log_debug("Mounting \"%s\" as read-only\n", name); // Mount the device //Print(L"Invoking ntfs_device_mount\n"); vd->vol = ntfs_device_mount(vd->dev, vd->flags); if (!vd->vol) { switch(ntfs_volume_error(errno)) { case NTFS_VOLUME_NOT_NTFS: errno = EINVALPART; break; case NTFS_VOLUME_CORRUPT: errno = EINVALPART; break; case NTFS_VOLUME_HIBERNATED: errno = EHIBERNATED; break; case NTFS_VOLUME_UNCLEAN_UNMOUNT: errno = EDIRTY; break; default: errno = EINVAL; break; } ntfs_device_free(vd->dev); ntfs_free(vd); //Print(L"ntfsMount ntfs_device_mount FAILED (%x)\n", errno); return NULL; } if (flags & NTFS_IGNORE_CASE) ntfs_set_ignore_case(vd->vol); // Initialise the volume descriptor if (ntfsInitVolume(vd)) { ntfs_umount(vd->vol, true); ntfs_free(vd); //Print(L"ntfsMount ntfsInitVolume failed\n"); return NULL; } // Add the device to the devoptab table if (ntfsAddDevice(name, vd)) { //Print(L"ntfsMount ntfsAddDevice failed\n"); ntfsDeinitVolume(vd); ntfs_umount(vd->vol, true); ntfs_free(vd); return NULL; } //Print(L"ntfsMount done.\n"); return vd; }