/** * ntfs_device_unix_io_close - Close the device, releasing the lock * @dev: * * Description... * * Returns: */ static int ntfs_device_unix_io_close(struct ntfs_device *dev) { struct flock flk; if (!NDevOpen(dev)) { errno = EBADF; return -1; } if (NDevDirty(dev)) fsync(DEV_FD(dev)); /* Release exclusive (mandatory) lock on the whole device. */ memset(&flk, 0, sizeof(flk)); flk.l_type = F_UNLCK; flk.l_whence = SEEK_SET; flk.l_start = flk.l_len = 0LL; if (fcntl(DEV_FD(dev), F_SETLK, &flk)) ntfs_log_perror("ntfs_device_unix_io_close: Warning: Could not " "unlock %s", dev->d_name); /* Close the file descriptor and clear our open flag. */ if (close(DEV_FD(dev))) return -1; NDevClearOpen(dev); free(dev->d_private); dev->d_private = NULL; return 0; }
/** * ntfs_device_unix_io_close - Close the device, releasing the lock * @dev: * * Description... * * Returns: */ static int ntfs_device_unix_io_close(struct ntfs_device *dev) { struct flock flk; if (!NDevOpen(dev)) { errno = EBADF; ntfs_log_perror("Device %s is not open", dev->d_name); return -1; } if (NDevDirty(dev)) if (ntfs_fsync(DEV_FD(dev))) { ntfs_log_perror("Failed to fsync device %s", dev->d_name); return -1; } memset(&flk, 0, sizeof(flk)); flk.l_type = F_UNLCK; flk.l_whence = SEEK_SET; flk.l_start = flk.l_len = 0LL; if (fcntl(DEV_FD(dev), F_SETLK, &flk)) ntfs_log_perror("Could not unlock %s", dev->d_name); if (close(DEV_FD(dev))) { ntfs_log_perror("Failed to close device %s", dev->d_name); return -1; } NDevClearOpen(dev); free(dev->d_private); dev->d_private = NULL; return 0; }
/** * ntfs_device_unix_io_open - Open a device and lock it exclusively * @dev: * @flags: * * Description... * * Returns: */ static int ntfs_device_unix_io_open(struct ntfs_device *dev, int flags) { struct flock flk; struct stat sbuf; int err; if (NDevOpen(dev)) { errno = EBUSY; return -1; } if (stat(dev->d_name, &sbuf)) { ntfs_log_perror("Failed to access '%s'", dev->d_name); return -1; } if (S_ISBLK(sbuf.st_mode)) NDevSetBlock(dev); dev->d_private = ntfs_malloc(sizeof(int)); if (!dev->d_private) return -1; /* * Open file for exclusive access if mounting r/w. * Fuseblk takes care about block devices. */ if (!NDevBlock(dev) && (flags & O_RDWR) == O_RDWR) flags |= O_EXCL; *(int*)dev->d_private = open(dev->d_name, flags); if (*(int*)dev->d_private == -1) { err = errno; goto err_out; } if ((flags & O_RDWR) != O_RDWR) NDevSetReadOnly(dev); memset(&flk, 0, sizeof(flk)); if (NDevReadOnly(dev)) flk.l_type = F_RDLCK; else flk.l_type = F_WRLCK; flk.l_whence = SEEK_SET; flk.l_start = flk.l_len = 0LL; if (fcntl(DEV_FD(dev), F_SETLK, &flk)) { err = errno; ntfs_log_perror("Failed to %s lock '%s'", NDevReadOnly(dev) ? "read" : "write", dev->d_name); if (close(DEV_FD(dev))) ntfs_log_perror("Failed to close '%s'", dev->d_name); goto err_out; } NDevSetOpen(dev); return 0; err_out: free(dev->d_private); dev->d_private = NULL; errno = err; return -1; }
/** * ntfs_device_unix_io_pread - Perform a positioned read from the device * @dev: * @buf: * @count: * @offset: * * Description... * * Returns: */ static s64 ntfs_device_unix_io_pread(struct ntfs_device *dev, void *buf, s64 count, s64 offset) { s64 ret; if (lseek64(DEV_FD(dev), offset, SEEK_SET) != offset) { ntfs_log_perror("seek for pread fail"); } ret = read(DEV_FD(dev), buf, count); if (!ret) { ntfs_log_perror("read device fail, errno: %d", errno); } return ret; }
/** * ntfs_device_unix_io_open - Open a device and lock it exclusively * @dev: * @flags: * * Description... * * Returns: */ static int ntfs_device_unix_io_open(struct ntfs_device *dev, int flags) { struct flock flk; struct stat sbuf; int err; if (NDevOpen(dev)) { errno = EBUSY; return -1; } if (!(dev->d_private = ntfs_malloc(sizeof(int)))) return -1; *(int*)dev->d_private = open(dev->d_name, flags); if (*(int*)dev->d_private == -1) { err = errno; goto err_out; } /* Setup our read-only flag. */ if ((flags & O_RDWR) != O_RDWR) NDevSetReadOnly(dev); /* Acquire exclusive (mandatory) lock on the whole device. */ memset(&flk, 0, sizeof(flk)); if (NDevReadOnly(dev)) flk.l_type = F_RDLCK; else flk.l_type = F_WRLCK; flk.l_whence = SEEK_SET; flk.l_start = flk.l_len = 0LL; if (fcntl(DEV_FD(dev), F_SETLK, &flk)) { err = errno; ntfs_log_debug("ntfs_device_unix_io_open: Could not lock %s " "for %s\n", dev->d_name, NDevReadOnly(dev) ? "reading" : "writing"); if (close(DEV_FD(dev))) ntfs_log_perror("ntfs_device_unix_io_open: Warning: " "Could not close %s", dev->d_name); goto err_out; } /* Determine if device is a block device or not, ignoring errors. */ if (!fstat(DEV_FD(dev), &sbuf) && S_ISBLK(sbuf.st_mode)) NDevSetBlock(dev); /* Set our open flag. */ NDevSetOpen(dev); return 0; err_out: free(dev->d_private); dev->d_private = NULL; errno = err; return -1; }
/** * ntfs_device_unix_io_pwrite - Perform a positioned write to the device * @dev: * @buf: * @count: * @offset: * * Description... * * Returns: */ static s64 ntfs_device_unix_io_pwrite(struct ntfs_device *dev, const void *buf, s64 count, s64 offset) { if (NDevReadOnly(dev)) { errno = EROFS; return -1; } NDevSetDirty(dev); if (lseek64(DEV_FD(dev), offset, SEEK_SET) != offset) { ntfs_log_perror("seek for pwrite fail"); } return write(DEV_FD(dev), buf, count); }
/** * Set options. */ static errcode_t device_gekko_set_option(io_channel dev, const char *option, const char *arg) { unsigned long long tmp; char *end; gekko_fd *fd = DEV_FD(dev); if (!fd) { errno = EBADF; return -1; } EXT2_CHECK_MAGIC(dev, EXT2_ET_MAGIC_IO_CHANNEL); if (!strcmp(option, "offset")) { if (!arg) return EXT2_ET_INVALID_ARGUMENT; tmp = strtoull(arg, &end, 0); if (*end) return EXT2_ET_INVALID_ARGUMENT; fd->offset = tmp; if (fd->offset < 0) return EXT2_ET_INVALID_ARGUMENT; return 0; } return EXT2_ET_INVALID_ARGUMENT; }
static int ntfs_device_uefi_io_sync(struct ntfs_device *dev) { struct _uefi_fd *fd = DEV_FD(dev); ntfs_log_trace("dev %p\n", dev); // Check that the device can be written to if (NDevReadOnly(dev)) { errno = EROFS; return -1; } // Mark the device as clean NDevClearDirty(dev); NDevClearSync(dev); // Flush any sectors in the disc cache (if required) if (fd->cache) { /*if (!_NTFS_cache_flush(fd->cache)) { errno = EIO; return -1; }*/ ntfs_log_trace("ntfs_device_uefi_io_sync cache enabled?!?!"); } return 0; }
/** * ntfs_device_unix_io_pwrite - Perform a positioned write to the device * @dev: * @buf: * @count: * @offset: * * Description... * * Returns: */ static s64 ntfs_device_unix_io_pwrite(struct ntfs_device *dev, const void *buf, s64 count, s64 offset) { if (NDevReadOnly(dev)) { errno = EROFS; return -1; } NDevSetDirty(dev); return pwrite(DEV_FD(dev), buf, count, offset); }
static errcode_t device_gekko_io_stat(io_channel dev, io_stats *stats) { EXT2_CHECK_MAGIC(dev, EXT2_ET_MAGIC_IO_CHANNEL); gekko_fd *fd = DEV_FD(dev); if (stats) *stats = &fd->io_stats; return EXT2_ET_OK; }
/** * ntfs_device_unix_io_sync - Flush any buffered changes to the device * @dev: * * Description... * * Returns: */ static int ntfs_device_unix_io_sync(struct ntfs_device *dev) { if (!NDevReadOnly(dev) && NDevDirty(dev)) { int res = fsync(DEV_FD(dev)); if (!res) NDevClearDirty(dev); return res; } return 0; }
static int ntfs_device_uefi_io_close(struct ntfs_device *dev) { struct _uefi_fd *fd = DEV_FD(dev); ntfs_log_trace("dev %p\n", dev); //AsciiPrint("ntfs_device_uefi_io_close\n\r"); // Get the device driver descriptor if (!fd) { errno = EBADF; return -1; } // Check that the device is actually open if (!NDevOpen(dev)) { ntfs_log_perror("device is not open\n"); errno = EIO; return -1; } // Mark the device as closed NDevClearOpen(dev); NDevClearBlock(dev); // Flush the device (if dirty and not read-only) if (NDevDirty(dev) && !NDevReadOnly(dev)) { ntfs_log_debug("device is dirty, will now sync\n"); // ...? // Mark the device as clean NDevClearDirty(dev); } // Flush and destroy the cache (if required) if (fd->cache) { //_NTFS_cache_flush(fd->cache); //_NTFS_cache_destructor(fd->cache); } // Shutdown the device interface /*const DISC_INTERFACE* interface = fd->interface; if (interface) { interface->shutdown(); }*/ // Free the device driver private data ntfs_free(dev->d_private); dev->d_private = NULL; return 0; }
/** * ntfs_device_unix_io_sync - Flush any buffered changes to the device * @dev: * * Description... * * Returns: */ static int ntfs_device_unix_io_sync(struct ntfs_device *dev) { int res = 0; if (!NDevReadOnly(dev)) { res = ntfs_fsync(DEV_FD(dev)); if (res) ntfs_log_perror("Failed to sync device %s", dev->d_name); else NDevClearDirty(dev); } return res; }
static bool ntfs_device_uefi_io_readsectors(struct ntfs_device *dev, sec_t sector, sec_t numSectors, void* buffer) { // Get the device driver descriptor struct _uefi_fd *fd = DEV_FD(dev); EFI_DISK_IO_PROTOCOL *DiskIo = fd->interface->DiskIo; UINT64 _sectorStart, _bufferSize; //AsciiPrint("ntfs_device_uefi_io_readsectors(sector %x, numSectors %x)\n\r", (UINTN) sector, (UINTN) numSectors); ntfs_log_trace("ntfs_device_uefi_io_readsectors {%x,%d,%d}", dev, sector, numSectors); if (!fd) { errno = EBADF; return false; } // Read the sectors from disc (or cache, if enabled) if (fd->cache) { //return _NTFS_cache_readSectors(fd->cache, sector, numSectors, buffer); ntfs_log_trace("ntfs_device_uefi_io_readsectors cache enabled?!?!"); } else { while(numSectors > 0) { //AsciiPrint("DiskIo.ReadDisk sectors %x\n\r", (UINTN) numSectors ); _sectorStart = sector * fd->sectorSize; _bufferSize = fd->sectorSize; if (DiskIo->ReadDisk(DiskIo, fd->interface->MediaId, _sectorStart, _bufferSize, buffer) != EFI_SUCCESS) { /*AsciiPrint("DiskIo %x\n\r", DiskIo); AsciiPrint("MediaId %x\n\r", fd->interface->MediaId); AsciiPrint("sector %x%x\n\r", (UINTN) sector * fd->sectorSize); AsciiPrint("numSectors %x%x\n\r", (UINTN) fd->sectorSize); AsciiPrint("buffer %x\n\r", buffer); AsciiPrint("ntfs_device_uefi_io_readsectors [DISKIO!READDISK] FAILED!!!\n\r");*/ ntfs_log_trace("failed I/O!"); return false; } numSectors--; // decrease sector count sector++; // increase sector start buffer = CALC_OFFSET(void *, buffer, fd->sectorSize); // move ptr! } //ReadDisk(DiskIo, fd->Volume->MediaId, fd->startSector * fd->sectorSize, sizeof(NTFS_BOOT_SECTOR), boot) } return true; }
static bool ntfs_device_uefi_io_writesectors(struct ntfs_device *dev, sec_t sector, sec_t numSectors, const void* buffer) { // Get the device driver descriptor struct _uefi_fd *fd = DEV_FD(dev); UINT64 _sectorStart; UINT64 _bufferSize; EFI_DISK_IO_PROTOCOL *DiskIo = fd->interface->DiskIo; ntfs_log_trace("ntfs_device_uefi_io_writesectors\n\r"); if (!fd) { errno = EBADF; return false; } // Write the sectors to disc (or cache, if enabled) if (fd->cache) { //return _NTFS_cache_writeSectors(fd->cache, sector, numSectors, buffer); ntfs_log_perror("ntfs_device_uefi_io_writesectors cache enabled?!?!"); } else { while(numSectors > 0) { //AsciiPrint("DiskIo.ReadDisk sectors %x\n\r", (UINTN) numSectors ); _sectorStart = sector * fd->sectorSize; _bufferSize = fd->sectorSize; if (DiskIo->WriteDisk(DiskIo, fd->interface->MediaId, _sectorStart, _bufferSize, buffer) != EFI_SUCCESS) { //AsciiPrint("DiskIo %x\n\r", DiskIo); //AsciiPrint("MediaId %x\n\r", fd->interface->MediaId); //AsciiPrint("sector %x%x\n\r", (UINTN) sector * fd->sectorSize); //AsciiPrint("numSectors %x%x\n\r", (UINTN) fd->sectorSize); //AsciiPrint("buffer %x\n\r", buffer); //AsciiPrint("ntfs_device_uefi_io_writesectors [DISKIO!WRITEDISK] FAILED!!!\n\r"); return false; } numSectors--; // decrease sector count sector++; // increase sector start buffer = CALC_OFFSET(void *, buffer, fd->sectorSize); // move ptr! } } //return fd->interface->writeSectors(sector, numSectors, buffer); return true; }
/** * Read function wrap for I/O manager */ static errcode_t device_gekko_io_read64(io_channel dev, unsigned long long block, int count, void *buf) { gekko_fd *fd = DEV_FD(dev); s64 size = (count < 0) ? -count : count * dev->block_size; fd->io_stats.bytes_read += size; ext2_loff_t location = ((ext2_loff_t) block * dev->block_size) + fd->offset; s64 read = device_gekko_io_readbytes(dev, location, size, buf); if(read != size) return EXT2_ET_SHORT_READ; else if(read < 0) return EXT2_ET_BLOCK_BITMAP_READ; return EXT2_ET_OK; }
static bool device_gekko_io_readsectors(io_channel dev, sec_t sector, sec_t numSectors, void* buffer) { // Get the device driver descriptor gekko_fd *fd = DEV_FD(dev); if (!fd) { errno = EBADF; return false; } // Read the sectors from disc (or cache, if enabled) if (fd->cache) return _EXT2_cache_readSectors(fd->cache, sector, numSectors, buffer); else return fd->interface->readSectors(sector, numSectors, buffer); return false; }
/** * Write function wrap for I/O manager */ static errcode_t device_gekko_io_write64(io_channel dev, unsigned long long block, int count, const void *buf) { gekko_fd *fd = DEV_FD(dev); s64 size = (count < 0) ? -count : count * dev->block_size; fd->io_stats.bytes_written += size; ext2_loff_t location = ((ext2_loff_t) block * dev->block_size) + fd->offset; s64 writen = device_gekko_io_writebytes(dev, location, size, buf); if(writen != size) return EXT2_ET_SHORT_WRITE; else if(writen < 0) return EXT2_ET_BLOCK_BITMAP_WRITE; return EXT2_ET_OK; }
static bool device_gekko_io_writesectors(io_channel dev, sec_t sector, sec_t numSectors, const void* buffer) { // Get the device driver descriptor gekko_fd *fd = DEV_FD(dev); if (!fd) { errno = EBADF; return false; } // Write the sectors to disc (or cache, if enabled) if (fd->cache) return cache_writeSectors(fd->cache, sector, numSectors, buffer); else return fd->interface->writeSectors(sector, numSectors, buffer); return false; }
static errcode_t device_gekko_io_sync(io_channel dev) { gekko_fd *fd = DEV_FD(dev); ext2_log_trace("dev %p\n", dev); // Check that the device can be written to if(!(dev->flags & EXT2_FLAG_RW)) return -1; // Flush any sectors in the disc cache (if required) if (fd->cache) { if (!_EXT2_cache_flush(fd->cache)) { errno = EIO; return EXT2_ET_BLOCK_BITMAP_WRITE; } } return EXT2_ET_OK; }
/** * Flush data out and close volume */ static errcode_t device_gekko_io_close(io_channel dev) { // Get the device driver descriptor gekko_fd *fd = DEV_FD(dev); if (!fd) { errno = EBADF; return -1; } if(!(dev->flags & EXT2_FLAG_RW)) return 0; // Flush and destroy the cache (if required) if (fd->cache) { _EXT2_cache_flush(fd->cache); _EXT2_cache_destructor(fd->cache); } return 0; }
static s64 ntfs_device_uefi_io_seek(struct ntfs_device *dev, s64 offset, int whence) { struct _uefi_fd *fd = DEV_FD(dev); ntfs_log_trace("dev %p, offset %li, whence %i\n", dev, offset, whence); //AsciiPrint("ntfs_device_uefi_io_seek\n\r"); // Get the device driver descriptor if (!fd) { errno = EBADF; return -1; } // Set the current position on the device (in bytes) switch(whence) { case SEEK_SET: fd->pos = MIN(MAX(offset, 0), fd->len); break; case SEEK_CUR: fd->pos = MIN(MAX(fd->pos + offset, 0), fd->len); break; case SEEK_END: fd->pos = MIN(MAX(fd->len + offset, 0), fd->len); break; } return 0; }
static int ntfs_device_uefi_io_stat(struct ntfs_device *dev, struct stat *buf) { // Get the device driver descriptor struct _uefi_fd *fd = DEV_FD(dev); mode_t mode; ntfs_log_trace("dev %p, buf %p\n", dev, buf); if (!fd) { errno = EBADF; return -1; } // Short circuit cases were we don't actually have to do anything if (!buf) return 0; // Build the device mode mode = (S_IFBLK) | (S_IRUSR | S_IRGRP | S_IROTH) | ((!NDevReadOnly(dev)) ? (S_IWUSR | S_IWGRP | S_IWOTH) : 0); // Zero out the stat buffer memset(buf, 0, sizeof(struct stat)); // Build the device stats buf->st_dev = 0;//fd->interface->ioType; buf->st_ino = fd->ino; buf->st_mode = mode; buf->st_rdev = 0; //fd->interface->ioType; buf->st_blksize = fd->sectorSize; buf->st_blocks = fd->sectorCount; return 0; }
int ntfs_file_to_sectors(struct _reent *r, const char *path, uint32_t *sec_out, uint32_t *size_out, int max, int phys) { ntfs_file_state fileStruct; ntfs_file_state* file = &fileStruct; uint32_t s_count = 0; //size_t len; off64_t len; // Get the volume descriptor for this path file->vd = ntfsGetVolume(path); if (!file->vd) { r->_errno = ENODEV; return -1; } // Lock ntfsLock(file->vd); // Try and find the file and (if found) ensure that it is not a directory file->ni = ntfsOpenEntry(file->vd, path); if (file->ni && (file->ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) { ntfsCloseEntry(file->vd, file->ni); ntfsUnlock(file->vd); r->_errno = EISDIR; return -1; } // Sanity check, the file should be open by now if (!file->ni) { ntfsUnlock(file->vd); r->_errno = ENOENT; return -1; } // Open the files data attribute file->data_na = ntfs_attr_open(file->ni, AT_DATA, AT_UNNAMED, 0); if(!file->data_na) { ntfsCloseEntry(file->vd, file->ni); ntfsUnlock(file->vd); return -1; } // Determine if this files data is compressed and/or encrypted file->compressed = NAttrCompressed(file->data_na) || (file->ni->flags & FILE_ATTR_COMPRESSED); file->encrypted = NAttrEncrypted(file->data_na) || (file->ni->flags & FILE_ATTR_ENCRYPTED); // We cannot read/write encrypted files if (file->encrypted) { ntfs_attr_close(file->data_na); ntfsCloseEntry(file->vd, file->ni); ntfsUnlock(file->vd); r->_errno = EACCES; return -1; } // Set the files current position and length file->pos = 0; len = file->len = file->data_na->data_size; struct ntfs_device *dev = file->vd->dev; gekko_fd *fd = DEV_FD(dev); while (len && s_count < max) { //size_t ret = ntfs_attr_to_sectors(file->data_na, file->pos, len, sec_out, size_out, max, &s_count, (u32) fd->sectorSize); off64_t ret = ntfs_attr_to_sectors(file->data_na, file->pos, len, sec_out, size_out, max, &s_count, (u32) fd->sectorSize); if (ret <= 0 || ret > len) { ntfsUnlock(file->vd); r->_errno = errno; return -1; } len -= ret; file->pos += ret; } if (phys) { uint32_t i; for (i = 0; i < s_count; i++) { sec_out[i] += fd->startSector; } } ntfs_attr_close(file->data_na); ntfsCloseEntry(file->vd, file->ni); // Unlock ntfsUnlock(file->vd); return s_count; }
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 int ntfs_device_uefi_io_ioctl(struct ntfs_device *dev, int request, void *argp) { struct _uefi_fd *fd = DEV_FD(dev); ntfs_log_trace("dev %p, request %i, argp %p\n", dev, request, argp); // Get the device driver descriptor if (!fd) { errno = EBADF; return -1; } // Figure out which i/o control was requested switch (request) { // Get block device size (sectors) #if defined(BLKGETSIZE) case BLKGETSIZE: { *(u32*)argp = fd->sectorCount; return 0; } #endif // Get block device size (bytes) #if defined(BLKGETSIZE64) case BLKGETSIZE64: { *(u64*)argp = (fd->sectorCount * fd->sectorSize); return 0; } #endif // Get hard drive geometry #if defined(HDIO_GETGEO) case HDIO_GETGEO: { struct hd_geometry *geo = (struct hd_geometry*)argp; geo->sectors = 0; geo->heads = 0; geo->cylinders = 0; geo->start = fd->hiddenSectors; return -1; } #endif // Get block device sector size (bytes) #if defined(BLKSSZGET) case BLKSSZGET: { *(int*)argp = fd->sectorSize; return 0; } #endif // Set block device block size (bytes) #if defined(BLKBSZSET) case BLKBSZSET: { int sectorSize = *(int*)argp; fd->sectorSize = sectorSize; return 0; } #endif // Unimplemented ioctrl default: { ntfs_log_perror("Unimplemented ioctrl %i\n", request); errno = EOPNOTSUPP; return -1; } } 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; }
static s64 ntfs_device_uefi_io_write(struct ntfs_device *dev, const void *buf, s64 count) { //AsciiPrint("ntfs_device_uefi_io_write\n\r"); return ntfs_device_uefi_io_writebytes(dev, DEV_FD(dev)->pos, count, buf); }
static s64 ntfs_device_uefi_io_read(struct ntfs_device *dev, void *buf, s64 count) { //AsciiPrint("ntfs_device_uefi_io_read\n\r"); return ntfs_device_uefi_io_readbytes(dev, DEV_FD(dev)->pos, count, buf); }