/** * 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); }
/** * 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); }
/** * ntfs_pwrite - positioned write to disk * @dev: device to write to * @pos: position in file descriptor to write to * @count: number of bytes to write * @b: data buffer to write to disk * * This function will write @count bytes from data buffer @b to the device @dev * at position @pos. * * On success, return the number of successfully written bytes. If this number * is lower than @count this means that the write has been interrupted in * flight or that an error was encountered during the write so that the write * is partial. 0 means nothing was written (also return 0 when @count is 0). * * On error and nothing has been written, return -1 with errno set * appropriately to the return code of either seek, write, or set * to EINVAL in case of invalid arguments. */ s64 ntfs_pwrite(struct ntfs_device *dev, const s64 pos, s64 count, const void *b) { s64 written, total, ret = -1; struct ntfs_device_operations *dops; ntfs_log_trace("pos %lld, count %lld\n",(long long)pos,(long long)count); if (!b || count < 0 || pos < 0) { errno = EINVAL; goto out; } if (!count) return 0; if (NDevReadOnly(dev)) { errno = EROFS; goto out; } dops = dev->d_ops; NDevSetDirty(dev); for (total = 0; count; count -= written, total += written) { written = dops->pwrite(dev, (const char*)b + total, count, pos + total); /* If everything ok, continue. */ if (written > 0) continue; /* * If nothing written or error return number of bytes written. */ if (!written || total) break; /* Nothing written and error, return error status. */ total = written; break; } if (NDevSync(dev) && total && dops->sync(dev)) { total--; /* on sync error, return partially written */ } ret = total; out: return ret; }
/** * ntfs_pwrite - positioned write to disk * @dev: device to write to * @pos: position in file descriptor to write to * @count: number of bytes to write * @b: data buffer to write to disk * * This function will write @count bytes from data buffer @b to the device @dev * at position @pos. * * On success, return the number of successfully written bytes. If this number * is lower than @count this means that the write has been interrupted in * flight or that an error was encountered during the write so that the write * is partial. 0 means nothing was written (also return 0 when @count is 0). * * On error and nothing has been written, return -1 with errno set * appropriately to the return code of either seek, write, or set * to EINVAL in case of invalid arguments. */ s64 ntfs_pwrite(struct ntfs_device *dev, const s64 pos, s64 count, const void *b) { s64 written, total; struct ntfs_device_operations *dops; ntfs_log_trace("Entering for pos 0x%llx, count 0x%llx.\n", pos, count); if (!b || count < 0 || pos < 0) { errno = EINVAL; return -1; } if (!count) return 0; if (NDevReadOnly(dev)) { errno = EROFS; return -1; } dops = dev->d_ops; /* Locate to position. */ if (dops->seek(dev, pos, SEEK_SET) == (off_t)-1) { ntfs_log_perror("ntfs_pwrite: seek to 0x%llx returned error", pos); return -1; } NDevSetDirty(dev); /* Write the data. */ for (total = 0; count; count -= written, total += written) { written = dops->write(dev, (const char*)b + total, count); /* If everything ok, continue. */ if (written > 0) continue; /* * If nothing written or error return number of bytes written. */ if (!written || total) break; /* Nothing written and error, return error status. */ return written; } /* Finally, return the number of bytes written. */ return total; }
/** * ntfs_device_uefi_io_pread - Perform a positioned read from the device * @dev: * @buf: * @count: * @offset: * * Description... * * Returns: */ static s64 ntfs_device_uefi_io_pread(struct ntfs_device *dev, void *buf, s64 count, s64 offset) { EFI_DISK_IO_PROTOCOL *DiskIo; NTFS_VOLUME *Volume; Volume = (NTFS_VOLUME *) dev->d_private; if (NDevReadOnly(dev)) { errno = EROFS; return -1; } NDevSetDirty(dev); DiskIo = Volume->DiskIo; DiskIo->ReadDisk (DiskIo, Volume->MediaId, offset, count, buf); return 0; }
/** * ntfs_device_uefi_io_write - Write to the device, at the current location * @dev: * @buf: * @count: * * Description... * * Returns: */ static s64 ntfs_device_uefi_io_write(struct ntfs_device *dev, const void *buf, s64 count) { EFI_DISK_IO_PROTOCOL *DiskIo; NTFS_VOLUME *Volume; Volume = (NTFS_VOLUME *) dev->d_private; if (NDevReadOnly(dev)) { errno = EROFS; return -1; } NDevSetDirty(dev); DiskIo = Volume->DiskIo; DiskIo->WriteDisk (DiskIo, Volume->MediaId, 0, count, buf); return 0; //write(DEV_FD(dev), buf, count); }
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; }
/** * ntfs_pwrite - positioned write to disk * @dev: device to write to * @pos: position in file descriptor to write to * @count: number of bytes to write * @b: data buffer to write to disk * * This function will write @count bytes from data buffer @b to the device @dev * at position @pos. * * On success, return the number of successfully written bytes. If this number * is lower than @count this means that the write has been interrupted in * flight or that an error was encountered during the write so that the write * is partial. 0 means nothing was written (also return 0 when @count is 0). * * On error and nothing has been written, return -1 with errno set * appropriately to the return code of either seek, write, or set * to EINVAL in case of invalid arguments. */ s64 ntfs_pwrite(struct ntfs_device *dev, const s64 pos, s64 count, const void *b) { s64 written, total; struct ntfs_device_operations *dops; s64 (*_pwrite)(struct ntfs_device *, const void *, s64, s64); ntfs_log_trace("Entering for pos 0x%llx, count 0x%llx.\n", pos, count); if (!b || count < 0 || pos < 0) { errno = EINVAL; return -1; } if (!count) return 0; if (NDevReadOnly(dev)) { errno = EROFS; return -1; } dops = dev->d_ops; _pwrite = dops->pwrite; if (!_pwrite) _pwrite = fake_pwrite; seek: /* * Locate to position if pwrite is to be emulated by seek() + write(). */ if (_pwrite == fake_pwrite && dops->seek(dev, pos, SEEK_SET) == (off_t)-1) { ntfs_log_perror("ntfs_pwrite: seek to 0x%llx returned error", pos); return -1; } NDevSetDirty(dev); /* Write the data. */ for (total = 0; count; count -= written, total += written) { written = _pwrite(dev, (const char*)b + total, count, pos + total); /* If everything ok, continue. */ if (written > 0) continue; /* * If nothing written or error return number of bytes written. */ if (!written || total) break; /* * If pwrite is not supported by the OS, fall back to emulating * it by seek() + write() and set the device pwrite() pointer * to NULL so we automatically use seek() + write() from now * on. */ if (errno == ENOSYS && _pwrite != fake_pwrite) { _pwrite = fake_pwrite; dops->pwrite = NULL; goto seek; } /* Nothing written and error, return error status. */ return written; } /* Finally, return the number of bytes written. */ return total; }