NTFS_CACHE* _NTFS_cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t startOfPartition, sec_t endOfPartition, sec_t sectorSize) { NTFS_CACHE* cache; unsigned int i; NTFS_CACHE_ENTRY* cacheEntries; if(numberOfPages==0 || sectorsPerPage==0) return NULL; if (numberOfPages < 4) { numberOfPages = 4; } if (sectorsPerPage < 32) { sectorsPerPage = 32; } cache = (NTFS_CACHE*) ntfs_alloc (sizeof(NTFS_CACHE)); if (cache == NULL) { return NULL; } cache->disc = discInterface; cache->startOfPartition = startOfPartition; cache->endOfPartition = endOfPartition; cache->numberOfPages = numberOfPages; cache->sectorsPerPage = sectorsPerPage; cache->sectorSize = sectorSize; cacheEntries = (NTFS_CACHE_ENTRY*) ntfs_alloc ( sizeof(NTFS_CACHE_ENTRY) * numberOfPages); if (cacheEntries == NULL) { ntfs_free (cache); return NULL; } for (i = 0; i < numberOfPages; i++) { cacheEntries[i].sector = CACHE_FREE; cacheEntries[i].count = 0; cacheEntries[i].last_access = 0; cacheEntries[i].dirty = false; cacheEntries[i].cache = (uint8_t*) ntfs_align ( sectorsPerPage * cache->sectorSize ); } cache->cacheEntries = cacheEntries; return cache; }
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; }
int ntfsAddDevice (const char *name, void *deviceData) { const devoptab_t *devoptab_ntfs = ntfsGetDevOpTab(); devoptab_t *dev = NULL; char *devname = NULL; int i; // Sanity check if (!name || !deviceData || !devoptab_ntfs) { errno = EINVAL; return -1; } // Allocate a devoptab for this device dev = (devoptab_t *) ntfs_alloc(sizeof(devoptab_t) + strlen(name) + 1); if (!dev) { errno = ENOMEM; return false; } // Use the space allocated at the end of the devoptab for storing the device name devname = (char*)(dev + 1); strcpy(devname, name); // Setup the devoptab memcpy(dev, devoptab_ntfs, sizeof(devoptab_t)); dev->name = devname; dev->deviceData = deviceData; // Add the device to the devoptab table (if there is a free slot) for (i = 0; i < STD_MAX; i++) { if(strcmp(devoptab_list[i]->name ,"stdnull")==0){ devoptab_list[i] = dev; return 0; } } // If we reach here then there are no free slots in the devoptab table for this device errno = EADDRNOTAVAIL; return -1; }
/** * PRIVATE: Callback for directory walking */ int ntfs_readdir_filler (DIR_ITER *dirState, const ntfschar *name, const int name_len, const int name_type, const s64 pos, const MFT_REF mref, const unsigned dt_type) { ntfs_dir_state *dir = STATE(dirState); ntfs_dir_entry *entry = NULL; char *entry_name = NULL; // Sanity check if (!dir || !dir->vd) { errno = EINVAL; return -1; } // Ignore DOS file names if (name_type == FILE_NAME_DOS) { return 0; } // Preliminary check that this entry can be enumerated (as described by the volume descriptor) if (MREF(mref) == FILE_root || MREF(mref) >= FILE_first_user || dir->vd->showSystemFiles) { // Convert the entry name to our current local if (ntfsUnicodeToLocal(name, name_len, &entry_name, 0) < 0) { ntfs_free(entry); return -1; } // If this is not the parent or self directory reference if ((strcmp(entry_name, ".") != 0) && (strcmp(entry_name, "..") != 0)) { // Open the entry ntfs_inode *ni = ntfs_pathname_to_inode(dir->vd->vol, dir->ni, entry_name); if (!ni) { ntfs_free(entry); return -1; } // Double check that this entry can be emuerated (as described by the volume descriptor) if (((ni->flags & FILE_ATTR_HIDDEN) && !dir->vd->showHiddenFiles) || ((ni->flags & FILE_ATTR_SYSTEM) && !dir->vd->showSystemFiles)) { ntfs_inode_close(ni); return 0; } // Close the entry ntfs_inode_close(ni); } // Allocate a new directory entry entry = ntfs_alloc(sizeof(ntfs_dir_entry)); if (!entry) return -1; // Setup the entry entry->name = entry_name; entry->next = NULL; // Link the entry to the directory if (!dir->first) { dir->first = entry; } else { ntfs_dir_entry *last = dir->first; while (last->next) last = last->next; last->next = entry; } } return 0; }
static int ntfs_device_uefi_io_open(struct ntfs_device *dev, int flags) { NTFS_BOOT_SECTOR *boot; EFI_DISK_IO_PROTOCOL *DiskIo; NTFS_VOLUME *Volume; struct _uefi_fd *fd = DEV_FD(dev); Volume = fd->interface; ntfs_log_trace("dev %p, flags %i\n", dev, flags); // Get the device driver descriptor if (!fd) { errno = EBADF; return -1; } // Get the device interface DiskIo = Volume->DiskIo; if (!DiskIo) { errno = ENODEV; return -1; } // Start the device interface and ensure that it is inserted //if (!interface->startup()) { // ntfs_log_perror("device failed to start\n"); // errno = EIO; // return -1; // } //if (!interface->isInserted()) { // ntfs_log_perror("device media is not inserted\n"); // errno = EIO; // return -1; //} // Check that the device isn't already open (used by another volume?) if (NDevOpen(dev)) { //AsciiPrint("ntfs_device_uefi_io_open...BUSY\n\r"); ntfs_log_perror("device is busy (already open)\n"); errno = EBUSY; return -1; } // Check that there is a valid NTFS boot sector at the start of the device boot = (NTFS_BOOT_SECTOR *) ntfs_alloc(MAX_SECTOR_SIZE); if(boot == NULL) { //AsciiPrint("ntfs_device_uefi_io_open...ENOMEM\n\r"); errno = ENOMEM; return -1; } if (DiskIo->ReadDisk(DiskIo, Volume->MediaId, 0, sizeof(NTFS_BOOT_SECTOR), boot) != EFI_SUCCESS) { //AsciiPrint("DiskIo ptr %x\n\r", DiskIo); //AsciiPrint("interface ptr %x\n\r", fd->interface); //AsciiPrint("DiskIo->ReadDisk(%x,%x,%x)\n\r", fd->interface->MediaId, fd->startSector * fd->sectorSize, sizeof(NTFS_BOOT_SECTOR)); //AsciiPrint("Sector size: %x\n\r", fd->sectorSize); //AsciiPrint("ntfs_device_uefi_io_open...read failure boot sector\n\r"); ntfs_log_perror("read failure @ sector %x\n", fd->startSector); errno = EIO; ntfs_free(boot); return -1; } if (!ntfs_boot_sector_is_ntfs(boot)) { //AsciiPrint("ntfs_device_uefi_io_open...EINVALIDPART\n\r"); errno = EINVALPART; ntfs_free(boot); return -1; } // Parse the boot sector fd->hiddenSectors = le32_to_cpu(boot->bpb.hidden_sectors); fd->sectorSize = le16_to_cpu(boot->bpb.bytes_per_sector); fd->sectorCount = sle64_to_cpu(boot->number_of_sectors); fd->pos = 0; fd->len = (fd->sectorCount * fd->sectorSize); fd->ino = le64_to_cpu(boot->volume_serial_number); // Free memory for boot sector ntfs_free(boot); // Mark the device as read-only (if required) if (flags & O_RDONLY) { NDevSetReadOnly(dev); } // cache disabled! fd->cache = NULL; //_NTFS_cache_constructor(fd->cachePageCount, fd->cachePageSize, interface, fd->startSector + fd->sectorCount, fd->sectorSize); // Mark the device as open NDevSetBlock(dev); NDevSetOpen(dev); //AsciiPrint("ntfs_device_uefi_io_open...success\n\r"); return 0; }
static s64 ntfs_device_uefi_io_writebytes(struct ntfs_device *dev, s64 offset, s64 count, const void *buf) { struct _uefi_fd *fd = DEV_FD(dev); sec_t sec_start; sec_t sec_count; u32 buffer_offset; u8 *buffer; ntfs_log_trace("dev %p, offset %l, count %l\n", dev, offset, count); // Get the device driver descriptor if (!fd) { errno = EBADF; return -1; } // Get the device interface //const DISC_INTERFACE* interface = fd->interface; //if (!interface) { // errno = ENODEV; // return -1; //} // Check that the device can be written to if (NDevReadOnly(dev)) { errno = EROFS; return -1; } if(count < 0 || offset < 0) { errno = EROFS; return -1; } if(count == 0) return 0; sec_start = (sec_t) fd->startSector; sec_count = 1; buffer_offset = (u32) (offset % fd->sectorSize); buffer = NULL; // Determine the range of sectors required for this write if (offset > 0) { sec_start += (sec_t) offset / fd->sectorSize; } if ((buffer_offset+count) > fd->sectorSize) { sec_count = (sec_t) ((buffer_offset+count) / fd->sectorSize); if (((buffer_offset+count) % fd->sectorSize) != 0) sec_count++; } // If this write happens to be on the sector boundaries then do the write straight to disc if((buffer_offset == 0) && (count % fd->sectorSize == 0)) { // Write to the device ntfs_log_trace("direct write to sector %d (%d sector(s) long)\n", sec_start, sec_count); if (!ntfs_device_uefi_io_writesectors(dev, sec_start, sec_count, buf)) { ntfs_log_perror("direct write failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count); errno = EIO; return -1; } // Else write from a buffer aligned to the sector boundaries } else { // Allocate a buffer to hold the write data buffer = (u8 *) ntfs_alloc(sec_count * fd->sectorSize); if (!buffer) { errno = ENOMEM; return -1; } // Read the first and last sectors of the buffer from disc (if required) // NOTE: This is done because the data does not line up with the sector boundaries, // we just read in the buffer edges where the data overlaps with the rest of the disc if(buffer_offset != 0) { if (!ntfs_device_uefi_io_readsectors(dev, sec_start, 1, buffer)) { ntfs_log_perror("read failure @ sector %d\n", sec_start); ntfs_free(buffer); errno = EIO; return -1; } } if((buffer_offset+count) % fd->sectorSize != 0) { if (!ntfs_device_uefi_io_readsectors(dev, sec_start + sec_count - 1, 1, buffer + ((sec_count-1) * fd->sectorSize))) { ntfs_log_perror("read failure @ sector %d\n", sec_start + sec_count - 1); ntfs_free(buffer); errno = EIO; return -1; } } // Copy the data into the write buffer memcpy(buffer + buffer_offset, buf, count); // Write to the device ntfs_log_trace("buffered write to sector %d (%d sector(s) long)\n", sec_start, sec_count); if (!ntfs_device_uefi_io_writesectors(dev, sec_start, sec_count, buffer)) { ntfs_log_perror("buffered write failure @ sector %d\n", sec_start); ntfs_free(buffer); errno = EIO; return -1; } // Free the buffer ntfs_free(buffer); } // Mark the device as dirty (if we actually wrote anything) NDevSetDirty(dev); return count; }
static s64 ntfs_device_uefi_io_readbytes(struct ntfs_device *dev, s64 offset, s64 count, void *buf) { struct _uefi_fd *fd = DEV_FD(dev); sec_t sec_start = (sec_t) fd->startSector; sec_t sec_count = 1; u32 buffer_offset = (u32) (offset % fd->sectorSize); u8 *buffer = NULL; //const DISC_INTERFACE* interface; ntfs_log_trace("dev %p, offset %li, count %li\n", dev, offset, count); // Get the device driver descriptor if (!fd) { //AsciiPrint("ntfs_device_uefi_io_readbytes EBADF\n\r"); ntfs_log_perror("EBADF"); errno = EBADF; return -1; } //// Get the device interface //interface = fd->interface; //if (!interface) { // errno = ENODEV; // return -1; //} if(offset < 0) { //AsciiPrint("ntfs_device_uefi_io_readbytes EROFS\n\r"); errno = EROFS; ntfs_log_perror("EROFS"); return -1; } if(!count) return 0; // Determine the range of sectors required for this read if (offset > 0) { sec_start += (sec_t) offset / fd->sectorSize; } if (buffer_offset+count > fd->sectorSize) { sec_count = (sec_t) (buffer_offset+count) / fd->sectorSize; if (((buffer_offset+count) % fd->sectorSize) != 0) sec_count++; } // If this read happens to be on the sector boundaries then do the read straight into the destination buffer if((buffer_offset == 0) && (count % fd->sectorSize == 0)) { // Read from the device ntfs_log_trace("direct read from sector %d (%d sector(s) long)\n", sec_start, sec_count); if (!ntfs_device_uefi_io_readsectors(dev, sec_start, sec_count, buf)) { ntfs_log_perror("direct read failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count); //AsciiPrint("ntfs_device_uefi_io_readbytes EIO\n\r"); errno = EIO; return -1; } // Else read into a buffer and copy over only what was requested } else { // Allocate a buffer to hold the read data buffer = (u8*)ntfs_alloc(sec_count * fd->sectorSize); if (!buffer) { errno = ENOMEM; return -1; } // Read from the device ntfs_log_trace("buffered read from sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_log_trace("count: %d sec_count:%d fd->sectorSize: %d )\n", (u32)count, (u32)sec_count,(u32)fd->sectorSize); if (!ntfs_device_uefi_io_readsectors(dev, sec_start, sec_count, buffer)) { //AsciiPrint("ntfs_device_uefi_io_readbytes buffered read failure\n\r"); ntfs_log_perror("buffered read failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_free(buffer); errno = EIO; return -1; } // Copy what was requested to the destination buffer memcpy(buf, buffer + buffer_offset, count); ntfs_free(buffer); } //ntfs_log_perror("Read %d sectors", count); return count; }
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; }