Add int63 type.
[virt-df.git] / lib / diskimage.mli
1 (** Diskimage library for reading disk images. *)
2 (* (C) Copyright 2007-2008 Richard W.M. Jones, Red Hat Inc.
3    http://libvirt.org/
4
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.
9
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.
14
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.
18  *)
19
20 (**
21    {2 Examples}
22
23 {[
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 ... *)
27   close_machine machine
28 ]}
29 *)
30
31 (** {2 Device class and specialized subclasses} *)
32
33 class virtual device :
34   object
35     method virtual name : string
36       (** Return some printable name for the device. *)
37     method virtual size : int64
38       (** Return the size of the device in bytes.
39
40           Note: For some types of devices, the device may have
41           "holes", alignment requirements, etc. so this method doesn't
42           imply that every byte from [0..size-1] is readable. *)
43     method read : int64 -> int -> string
44       (** [read offset len] reads len bytes starting at offset.
45
46           Note: A default implementation is provided for [read],
47           but it is fairly inefficient because it uses {!mapblock} to
48           map each block in the request. *)
49     method read_bitstring : int64 -> int -> Bitmatch.bitstring
50       (** [read_bitstring] is the same as [read] but returns
51           a pa_bitmatch-style bitstring. *)
52     method virtual blocksize : int
53       (** [blocksize] returns the natural block size of the device. *)
54     method virtual mapblock : int64 -> (device * int64) list
55       (** [mapblock] describes how a block in this device is
56           mapped down to any underlying device(s).
57
58           Returns [[]] (empty list) if there is no underlying
59           device for this block.  Otherwise returns a list of
60           [(device, byte-offset)] locations where this block is mapped.
61
62           Normally the returned list has length 1, but in cases
63           such as mirroring you can have the same block mapped
64           to several underlying devices. *)
65   end
66   (**
67      A virtual (or physical!) device, encapsulating any translation
68      that has to be done to access the device.  eg. For partitions
69      there is a simple offset, but for LVM you may need complicated
70      table lookups.
71     
72      Note this very rare use of OOP in OCaml!
73   *)
74
75 class block_device : string -> int ->
76   object
77     method name : string
78     method size : int64
79     method read : int64 -> int -> string
80     method read_bitstring : int64 -> int -> Bitmatch.bitstring
81     method blocksize : int
82     method mapblock : int64 -> (device * int64) list
83     method close : unit -> unit
84       (** Close the device, freeing up the file descriptor. *)
85   end
86     (** A concrete device which just direct-maps a file or /dev device.
87
88         Create the device with [new block_device filename blocksize]
89         where [filename] is the path to the file or device and
90         [blocksize] is the blocksize of the device. *)
91
92 class offset_device : string -> int64 -> int64 -> int -> device ->
93   object
94     method name : string
95     method size : int64
96     method read : int64 -> int -> string
97     method read_bitstring : int64 -> int -> Bitmatch.bitstring
98     method blocksize : int
99     method mapblock : int64 -> (device * int64) list
100   end
101     (** A concrete device which maps a linear part of an underlying device.
102
103         [new offset_device name start size blocksize dev] creates a new
104         device which maps bytes from [start] to [start+size-1]
105         of the underlying device [dev] (ie. in this device they
106         appear as bytes [0] to [size-1]).
107
108         Useful for things like partitions.
109     *)
110
111 class blocksize_overlay : int -> device ->
112   object
113     method name : string
114     method size : int64
115     method read : int64 -> int -> string
116     method read_bitstring : int64 -> int -> Bitmatch.bitstring
117     method blocksize : int
118     method mapblock : int64 -> (device * int64) list
119   end
120     (** Change the blocksize of an existing device. *)
121
122 val null_device : device
123     (** The null device.  Any attempt to read generates an error. *)
124
125 (**
126    {2 Structures used to describe machines, disks, partitions and filesystems}
127
128    {3 Machine/device model}
129
130    The "machine/device model" that we currently understand looks
131    like this:
132
133 {v
134 machines
135   |
136   \--- host partitions / disk image files
137          ||
138        guest block devices
139          |
140          +--> guest partitions (eg. using MBR)
141          |      |
142          \-(1)->+--- filesystems (eg. ext3)
143                 |
144                 \--- PVs for LVM
145                        |||
146                      VGs and LVs
147 v}
148
149    (1) Filesystems and PVs may also appear directly on guest
150    block devices.
151
152    Partition schemes (eg. MBR) and filesystems register themselves
153    with this main module and they are queried first to get an idea
154    of the physical devices, partitions and filesystems potentially
155    available to the guest.
156
157    Volume management schemes (eg. LVM2) register themselves here
158    and are called later with "spare" physical devices and partitions
159    to see if they contain LVM data.  If this results in additional
160    logical volumes then these are checked for filesystems.
161
162    Swap space is considered to be a dumb filesystem for the purposes
163    of this discussion.
164 *)
165
166 type machine = {
167   m_name : string;                      (** Machine name. *)
168   m_disks : disk list;                  (** Machine disks. *)
169   m_lv_filesystems :
170     (lv * filesystem) list;             (** Machine LV filesystems. *)
171 }
172     (** A 'machine' is just a convenient holder for collections of disks. *)
173
174 and disk = {
175   d_name : string;                      (** Device name (eg "hda") *)
176   d_dev : block_device;                 (** Disk device. *)
177   d_content : disk_content;             (** What's on it. *)
178 }
179     (** A single physical disk image. *)
180
181 and disk_content =
182     [ `Filesystem of filesystem         (** Contains a direct filesystem. *)
183     | `Partitions of partitions         (** Contains partitions. *)
184     | `PhysicalVolume of pv             (** Contains an LVM PV. *)
185     | `Unknown                          (** Not probed or unknown. *)
186     ]
187
188 and partitions = {
189   parts_plugin_id : parts_plugin_id;    (** Partitioning scheme. *)
190   parts : partition list;               (** Partitions. *)
191 }
192 and partition = {
193   part_status : partition_status;       (** Bootable, etc. *)
194   part_type : int;                      (** Partition filesystem type. *)
195   part_dev : device;                    (** Partition device. *)
196   part_content : partition_content;     (** What's on it. *)
197 }
198     (** Partitions as found on a disk image. *)
199
200 and partition_status = Bootable | Nonbootable | Malformed | NullEntry
201 and partition_content =
202     [ `Filesystem of filesystem         (** Filesystem. *)
203     | `PhysicalVolume of pv             (** Contains an LVM PV. *)
204     | `Unknown                          (** Not probed or unknown. *)
205     ]
206
207 and filesystem = {
208   fs_plugin_id : fs_plugin_id;          (** Filesystem type. *)
209   fs_dev : device;                      (** Device containing the filesystem. *)
210   fs_blocksize : int;                   (** Block size (bytes). *)
211   fs_blocks_total : int64;              (** Total blocks. *)
212   fs_is_swap : bool;                    (** If swap, following not valid. *)
213   fs_blocks_reserved : int64;           (** Blocks reserved for super-user. *)
214   fs_blocks_avail : int64;              (** Blocks free (available). *)
215   fs_blocks_used : int64;               (** Blocks in use. *)
216   fs_inodes_total : int64;              (** Total inodes. *)
217   fs_inodes_reserved : int64;           (** Inodes reserved for super-user. *)
218   fs_inodes_avail : int64;              (** Inodes free (available). *)
219   fs_inodes_used : int64;               (** Inodes in use. *)
220 }
221     (** A filesystem, with superblock contents. *)
222
223 and pv = {
224   lvm_plugin_id : lvm_plugin_id;        (** The LVM plug-in which detected
225                                             this. *)
226   pv_uuid : string;                     (** UUID. *)
227 }
228 and lv = {
229   lv_dev : device;                      (** Logical volume device. *)
230 }
231     (** Physical and logical volumes as used by LVM plug-ins. *)
232
233 and parts_plugin_id
234 and fs_plugin_id
235 and lvm_plugin_id
236   (** Opaque IDs used to refer to the plug-ins. *)
237
238 val name_of_parts : parts_plugin_id -> string
239 val name_of_filesystem : fs_plugin_id -> string
240 val name_of_lvm : lvm_plugin_id -> string
241   (** Convert plug-in IDs to printable strings. *)
242
243 (** {2 Scanning functions} *)
244
245 val open_machine : string -> (string * string) list -> machine
246   (** [open_machine m_name devs]
247       creates a {!machine} containing the devices listed.
248
249       [devs] is a list of pairs of [(name, path)] elements
250       where [name] is something like ["hda"] and [path]
251       is a path to a disk image or [/dev] device.
252
253       This function does not do any scanning, so all disk
254       contents are just set to [`Unknown] and there are no
255       LV filesystems in the returned structure.
256   *)
257
258 val close_machine : machine -> unit
259   (** This is a convenience function which calls the [dev#close]
260       method on any open {!block_device}s owned by the machine.  This just
261       has the effect of closing any file descriptors which are
262       opened by these devices.
263   *)
264
265 val scan_machine : machine -> machine
266   (** This does a complete scan of all devices owned by a machine,
267       identifying all partitions, filesystems, physical and logical
268       volumes that are known to this library.
269
270       This scans down to the level of the filesystem superblocks.
271
272       Returns an updated {!machine} structure with the scan results.
273   *)
274
275 (** {2 Debugging} *)
276
277 val debug : bool ref
278   (** If set to true, functions emit debugging information to stderr. *)