module Diskimage:Diskimage library for reading disk images.sig..end
let machine = open_machine "host" ["hda", "/dev/hda"] in
let machine = scan_machine machine in
(* do what you want with the scan results ... *)
close_machine machine
class virtual device :object..end
class block_device :string -> Int63.t ->object..end
class offset_device :string -> Int63.t -> Int63.t -> Int63.t -> device ->object..end
class blocksize_overlay :Int63.t -> device ->object..end
val null_device : deviceThe "machine/device model" that we currently understand looks like this:
machines
|
\--- host partitions / disk image files
||
guest block devices
|
+--> guest partitions (eg. using MBR)
| |
\-(1)->+--- filesystems (eg. ext3)
|
\--- PVs for LVM
|||
VGs and LVs
(1) Filesystems and PVs may also appear directly on guest block devices.
Partition schemes (eg. MBR) and filesystems register themselves with this main module and they are queried first to get an idea of the physical devices, partitions and filesystems potentially available to the guest.
Volume management schemes (eg. LVM2) register themselves here and are called later with "spare" physical devices and partitions to see if they contain LVM data. If this results in additional logical volumes then these are checked for filesystems.
Swap space is considered to be a dumb filesystem for the purposes
of this discussion.
type machine = {
|
m_name : |
(* | Machine name. | *) |
|
m_disks : |
(* | Machine disks. | *) |
|
m_lv_filesystems : |
(* | Machine LV filesystems. | *) |
type disk = {
|
d_name : |
(* | Device name (eg "hda") | *) |
|
d_dev : |
(* | Disk device. | *) |
|
d_content : |
(* | What's on it. | *) |
typedisk_content =[ `Filesystem of filesystem
| `Partitions of partitions
| `PhysicalVolume of pv
| `Unknown ]
type partitions = {
|
parts_cb : |
(* | Partitioning scheme. | *) |
|
parts_dev : |
(* | Partitions (whole) device. | *) |
|
parts : |
(* | Partitions. | *) |
type partition = {
|
part_status : |
(* | Bootable, etc. | *) |
|
part_type : |
(* | Partition filesystem type. | *) |
|
part_dev : |
(* | Partition device. | *) |
|
part_content : |
(* | What's on it. | *) |
type partition_status =
| |
Bootable |
| |
Nonbootable |
| |
Malformed |
| |
NullEntry |
typepartition_content =[ `Filesystem of filesystem
| `PhysicalVolume of pv
| `Unknown ]
type filesystem = {
|
fs_cb : |
(* | Filesystem type. | *) |
|
fs_dev : |
(* | Device containing the filesystem. | *) |
|
fs_blocksize : |
(* | Block size (bytes). | *) |
|
fs_blocks_total : |
(* | Total blocks. | *) |
|
fs_is_swap : |
(* | If swap, following not valid. | *) |
|
fs_blocks_reserved : |
(* | Blocks reserved for super-user. | *) |
|
fs_blocks_avail : |
(* | Blocks free (available). | *) |
|
fs_blocks_used : |
(* | Blocks in use. | *) |
|
fs_inodes_total : |
(* | Total inodes. | *) |
|
fs_inodes_reserved : |
(* | Inodes reserved for super-user. | *) |
|
fs_inodes_avail : |
(* | Inodes free (available). | *) |
|
fs_inodes_used : |
(* | Inodes in use. | *) |
type pv = {
|
pv_cb : |
(* | The LVM plug-in which detected this. | *) |
|
pv_dev : |
(* | Device covering whole PV. | *) |
|
pv_uuid : |
(* | UUID. | *) |
type lv = {
|
lv_dev : |
(* | Logical volume device. | *) |
type partitioner_callbacks
type filesystem_callbacks
type lvm_callbacks
val name_of_filesystem : filesystem -> stringname_of_filesystem fs returns a printable name for
the filesystem.val open_machine : string -> (string * string) list -> machineopen_machine m_name devs
creates a Diskimage.machine containing the devices listed.
devs is a list of pairs of (name, path) elements
where name is something like "hda" and path
is a path to a disk image or /dev device.
This function does not do any scanning, so all disk
contents are just set to `Unknown and there are no
LV filesystems in the returned structure.
val open_machine_from_devices : string -> (string * block_device) list -> machineDiskimage.open_machine except that instead
of passing a path you should pass a Diskimage.block_device object.val close_machine : machine -> unitdev#close
method on any open Diskimage.block_devices owned by the machine. This just
has the effect of closing any file descriptors which are
opened by these devices.val scan_machine : machine -> machineThis scans down to the level of the filesystem superblocks.
Returns an updated Diskimage.machine structure with the scan results.
type ownership
val create_ownership : machine -> ownershiptypeowner =[ `Filesystem of filesystem
| `Partitions of partitions
| `PhysicalVolume of pv ]
val get_owners_lookup : machine ->
ownership ->
block_device -> Int63.t -> (owner * Int63.t) listget_owners_lookup machine disk returns a specialized
function for looking up owners (filesystems, etc.)
which reside on block device disk.
disk must be a block device of the machine.
The specialized lookup function that is returned
can be called as lookup offset to look up the
owners of byte offset offset.
Returns a list of (owner, owner_offset) where owner
is the filesystem, etc., and owner_offset is the byte
offset relative to the owner.
It is common for there to be multiple owners: for example
in the case where a filesystem is created on a partition,
both the filesystem (`Filesystem fs) and
partition scheme (`Partitions parts) will be returned.
The specialized function is efficient. Diskimage.create_ownership
creates a tree structure which allows ownership to be determined
in just a few steps.
val offset_is_free : (owner * Int63.t) list -> booloffset_is_free owners tests if the offset is free (unused).
If an offset is free, then it may be discarded without
changing the semantics of the disk image. In normal cases
this extends to the end of the current block, but blocksize
will differ for each owner, so what this really means is
tricky in practice.
val debug : bool Pervasives.ref