示例#1
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);
}
/**
 * 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);
}
示例#3
0
文件: device.c 项目: DonCN/haiku
/**
 * 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;
}
示例#4
0
/**
 * 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;
}
示例#5
0
/**
 * 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;
}
示例#6
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);
}
示例#7
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;
}
示例#8
0
/**
 * 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;
}