1 (** Diskimage library for reading disk images. *)
2 (* (C) Copyright 2007-2008 Richard W.M. Jones, Red Hat Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 let machine = open_machine "host" ["hda", "/dev/hda"] in
25 let machine = scan_machine machine in
26 (* do what you want with the scan results ... *)
32 {2 Machine/device model}
34 The "machine/device model" that we currently understand looks
40 \--- host partitions / disk image files
44 +--> guest partitions (eg. using MBR)
46 \-(1)->+--- filesystems (eg. ext3)
53 (1) Filesystems and PVs may also appear directly on guest
56 Partition schemes (eg. MBR) and filesystems register themselves
57 with this main module and they are queried first to get an idea
58 of the physical devices, partitions and filesystems potentially
59 available to the guest.
61 Volume management schemes (eg. LVM2) register themselves here
62 and are called later with "spare" physical devices and partitions
63 to see if they contain LVM data. If this results in additional
64 logical volumes then these are checked for filesystems.
66 Swap space is considered to be a dumb filesystem for the purposes
70 class virtual device :
72 method virtual name : string
73 (** Return some printable name for the device. *)
74 method virtual size : int64
75 (** Return the size of the device in bytes.
77 Note: For some types of devices, the device may have
78 "holes", alignment requirements, etc. so this method doesn't
79 imply that every byte from [0..size-1] is readable. *)
80 method close : unit -> unit
81 (** Close the device. This must be called to fully free up
82 any resources used by the device. *)
83 method virtual read : int64 -> int -> string
84 (** [read offset len] reads len bytes starting at offset. *)
85 method read_bitstring : int64 -> int -> Bitmatch.bitstring
86 (** [read_bitstring] is the same as [read] but returns
87 a pa_bitmatch-style bitstring. *)
90 A virtual (or physical!) device, encapsulating any translation
91 that has to be done to access the device. eg. For partitions
92 there is a simple offset, but for LVM you may need complicated
95 Note this very rare use of OOP in OCaml!
98 class block_device : string ->
102 method close : unit -> unit
103 method read : int64 -> int -> string
104 method read_bitstring : int64 -> int -> Bitmatch.bitstring
106 (** A concrete device which just direct-maps a file or /dev device. *)
108 class offset_device : string -> int64 -> int64 -> device ->
112 method close : unit -> unit
113 method read : int64 -> int -> string
114 method read_bitstring : int64 -> int -> Bitmatch.bitstring
116 (** A concrete device which maps a linear part of an underlying device.
118 [new offset_device name start size dev] creates a new
119 device which maps bytes from [start] to [start+size-1]
120 of the underlying device [dev] (ie. in this device they
121 appear as bytes [0] to [size-1]).
123 Useful for things like partitions.
126 val null_device : device
127 (** The null device. Any attempt to read generates an error. *)
130 m_name : string; (** Machine name. *)
131 m_disks : disk list; (** Machine disks. *)
133 (lv * filesystem) list; (** Machine LV filesystems. *)
135 (** A 'machine' is just a convenient holder for collections of disks. *)
138 d_name : string; (** Device name (eg "hda") *)
139 d_dev : device; (** Disk device. *)
140 d_content : disk_content; (** What's on it. *)
142 (** A single physical disk image. *)
145 [ `Filesystem of filesystem (** Contains a direct filesystem. *)
146 | `Partitions of partitions (** Contains partitions. *)
147 | `PhysicalVolume of pv (** Contains an LVM PV. *)
148 | `Unknown (** Not probed or unknown. *)
152 parts_plugin_id : parts_plugin_id; (** Partitioning scheme. *)
153 parts : partition list; (** Partitions. *)
156 part_status : partition_status; (** Bootable, etc. *)
157 part_type : int; (** Partition filesystem type. *)
158 part_dev : device; (** Partition device. *)
159 part_content : partition_content; (** What's on it. *)
161 (** Partitions as found on a disk image. *)
163 and partition_status = Bootable | Nonbootable | Malformed | NullEntry
164 and partition_content =
165 [ `Filesystem of filesystem (** Filesystem. *)
166 | `PhysicalVolume of pv (** Contains an LVM PV. *)
167 | `Unknown (** Not probed or unknown. *)
171 fs_plugin_id : fs_plugin_id; (** Filesystem type. *)
172 fs_block_size : int64; (** Block size (bytes). *)
173 fs_blocks_total : int64; (** Total blocks. *)
174 fs_is_swap : bool; (** If swap, following not valid. *)
175 fs_blocks_reserved : int64; (** Blocks reserved for super-user. *)
176 fs_blocks_avail : int64; (** Blocks free (available). *)
177 fs_blocks_used : int64; (** Blocks in use. *)
178 fs_inodes_total : int64; (** Total inodes. *)
179 fs_inodes_reserved : int64; (** Inodes reserved for super-user. *)
180 fs_inodes_avail : int64; (** Inodes free (available). *)
181 fs_inodes_used : int64; (** Inodes in use. *)
186 lvm_plugin_id : lvm_plugin_id; (** The LVM plug-in which detected
188 pv_uuid : string; (** UUID. *)
191 lv_dev : device; (** Logical volume device. *)
193 (** Physical and logical volumes as used by LVM plug-ins. *)
198 (** Opaque IDs used to refer to the plug-ins. *)
200 val name_of_parts : parts_plugin_id -> string
201 val name_of_filesystem : fs_plugin_id -> string
202 val name_of_lvm : lvm_plugin_id -> string
203 (** Convert plug-in IDs to printable strings. *)
205 (** {2 Scanning functions} *)
207 val open_machine : string -> (string * string) list -> machine
208 (** [open_machine m_name devs]
209 creates a {!machine} containing the devices listed.
211 [devs] is a list of pairs of [(name, path)] elements
212 where [name] is something like ["hda"] and [path]
213 is a path to a disk image or [/dev] device.
215 This function does not do any scanning, so all disk
216 contents are just set to [`Unknown] and there are no
217 LV filesystems in the returned structure.
220 val close_machine : machine -> unit
221 (** This is a convenience function which calls the [dev#close]
222 method on any open devices owned by the machine. This just
223 has the effect of closing any file descriptors which are
224 opened by these devices.
227 val scan_machine : machine -> machine
228 (** This does a complete scan of all devices owned by a machine,
229 identifying all partitions, filesystems, physical and logical
230 volumes that are known to this library.
232 Returns an updated {!machine} structure with the scan results.
238 (** If set to true, functions emit debugging information to stderr. *)