Hi all,
There now are updated snapshots available (BK repositories are also
updated) containing libntfs with fully virtualized io. Please read below
for details. Any comments would be greatly appreaciated!
>As part of the ntfsimage I'm writing, I want to be able to call some of
>the functions in libntfs that normally write to the disk, but without
>actually modifying the partition; instead, I want to be able to divert
>the `writes' to my own code to write the image. (See [1] below for more
>explanation of this.)
>At the moment, disk_io's ntfs_pread et al all read and write directly
>using vol->fd. Without writing a kernel device driver, that makes it
>difficult to virtualise. I expect there are other reasons you might want
>to virtualise libntfs's disk I/O.
>So I wrote the patch below. It is against linux-ntfs 1.7.1 and makes
>the following changes:
>* ntfs_volume contains a new member which if non-null points to
> a struct describing how to do disk I/O. I put the new member at the
> end to make it ABI-compatible. Regrettably this makes mkntfs break
> when old binaries are run agains the new library because mkntfs uses
> calloc directly to allocate an ntfs_volume rather than calling
> __ntfs_volume_allocate.
Since ABI compatibility cannot be maintained fully anyway, I went and
changed the library more fundamentally. Now no fds are passed anywhere and
instead we always pass the new "struct ntfs_device *". This is attached to
a volume via ntfs_volume->dev. You obtain an ntfs_device via
ntfs_device_alloc() (see libntfs/device.c) and release it via
ntfs_device_free() you then use ntfs_device_mount() and
ntfs_device_umount() (see libntfs/volume.c).
The old ntfs_mount() and ntfs_umount() are still available but now they
are simple wrappers for ntfs_device_mount() using the old device io
routines (i.e. traditional UNIX file/device io).
The ntfs_device structure contains the fields:
char *d_name - the name of the device
long d_state - device state bits (see include/device.h)
void *d_private - private data to the device, we ignore it, it
should only be touched by the utility who setup the ntfs_device and by the
ntfs_device_operations associated with the device.
struct ntfs_device_operations *d_ops - device operations defined
for the device. Note all operations are compulsory to be present. We do
NOT check if they are present before using them so if you leave any NULL
pointers the library will explode (this may change in the future and
ntfs_device_alloc() may test all ops for being != NULL). For an example
implementation of all operations see libntfs/disk_io.c (this is the
default UNIX style file/device io used by ntfs_mount() and ntfs_umount()).
The ntfs_device_operations structure defines all operations associated
with the device:
open, close, read, write, seek, pread, pwrite, sync, stat, and
ioctl.
This allows you to completely virtualise all low level device access.
See libntfs/volume.c::ntfs_mount() and ntfs_umount() as well as
libntfs/disk_io.c::ntfs_device_disk_io_*() for an example implementation.
So you can define your own io functions and then call:
dev = ntfs_device_alloc(name_of_device, 0, &your_device_ops,
NULL);
vol = ntfs_device_mount(dev, 0);
Now can use all library functions as usual (except we always pass vol->dev
where we used to pass vol->fd).
If you need to do low level io then call the appropriate device operations
like so:
vol->dev->d_ops->seek(vol->dev, ......);
Any comments about the implementations would be appreciated... We can
still change it! (-;
> Also, I assume that calloc() results in zero pointers; this is
> strictly speaking not a safe assumption according to C89. If you
> think this is a problem (ie if you don't already make this
> assumption somewhere) then __ntfs_volume_allocate should clear the
> new member.
It probably is assumed all over the place but one can fix them on a case
by case basis. There is now a function called ntfs_volume_alloc() which
will calloc() followed by explicit = NULL for all pointers in the
structure.
>* ntfs_*_pread erroneously declared their output buffer as
> const void* rather than just void*. This is fixed.
I don't think this is actually a problem as they define the pointer to be
fixed but not the contents. However, I made the change anyway.
Thanks for your work!
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/ & http://www-stu.christs.cam.ac.uk/~aia21/
|