+(* eg. HD "a" => "hda", or CCISS (0,1) => "cciss/c0d1" *)
+let short_dev_of_block_device = function
+ | HD n -> sprintf "hd%s" n
+ | SD n -> sprintf "sd%s" n
+ | CCISS (c, d) -> sprintf "cciss/c%dd%d" c d
+
+(* Returns the full /dev/ path to a block device. *)
+let dev_of_block_device dev = "/dev/" ^ short_dev_of_block_device dev
+
+(* Returns path to partition or LV without /dev/,
+ * eg. "hda1" or "VolGroup/LogVol"
+ *)
+let short_dev_of_partition = function
+ | Part (dev, partnum) -> short_dev_of_block_device dev ^ partnum
+ | LV (vg, lv) -> sprintf "%s/%s" vg lv
+
+(* Returns the full /dev/ path to a partition or LV. *)
+let dev_of_partition part = "/dev/" ^ short_dev_of_partition part
+
+(* A PV is loosely defined here as either a device or a partition -
+ * basically anything that could be a PV.
+ *)
+type pv = PVDev of block_device | PVPart of partition
+
+let string_of_pv = function
+ | PVDev dev -> dev_of_block_device dev
+ | PVPart p -> dev_of_partition p
+
+(* Take a device name optionally beginning with /dev/ and work
+ * out if it looks like either a device or partition that we
+ * know how to deal with. If not, returns None.
+ *
+ * For the sake of simplifying some code later on, the device
+ * name may also be followed by "(\d+)" which is just ignored.
+ *)
+let pv_of_dev =
+ let hdp = Pcre.regexp "^/dev/hd([a-z]+)(\\d+)(\\(\\d+\\))?$" in
+ let hd = Pcre.regexp "^/dev/hd([a-z]+)(\\(\\d\\))?$" in
+ let sdp = Pcre.regexp "^/dev/sd([a-z]+)(\\d+)(\\(\\d+\\))?$" in
+ let sd = Pcre.regexp "^/dev/sd([a-z]+)(\\(\\d+\\))?$" in
+ let ccissp = Pcre.regexp "^/dev/cciss/c(\\d+)d(\\d+)(p\\d+)(\\(\\d+\\))?$" in
+ let cciss = Pcre.regexp "^/dev/cciss/c(\\d+)d(\\d+)(\\(\\d+\\))?$" in
+ let lv = Pcre.regexp "^/dev/(\\w+)/(\\w+)$" in
+
+ fun name ->
+ try
+ let subs = Pcre.exec ~rex:hdp name in
+ Some (PVPart (Part (HD (Pcre.get_substring subs 1),
+ Pcre.get_substring subs 2)))
+ with Not_found ->
+ try
+ let subs = Pcre.exec ~rex:hd name in
+ Some (PVDev (HD (Pcre.get_substring subs 1)))
+ with Not_found ->
+ try
+ let subs = Pcre.exec ~rex:sdp name in
+ Some (PVPart (Part (SD (Pcre.get_substring subs 1),
+ Pcre.get_substring subs 2)))
+ with Not_found ->
+ try
+ let subs = Pcre.exec ~rex:sd name in
+ Some (PVDev (SD (Pcre.get_substring subs 1)))
+ with Not_found ->
+ try
+ let subs = Pcre.exec ~rex:ccissp name in
+ let c = int_of_string (Pcre.get_substring subs 1) in
+ let d = int_of_string (Pcre.get_substring subs 2) in
+ Some (PVPart (Part (CCISS (c, d), Pcre.get_substring subs 3)))
+ with Not_found ->
+ try
+ let subs = Pcre.exec ~rex:cciss name in
+ let c = int_of_string (Pcre.get_substring subs 1) in
+ let d = int_of_string (Pcre.get_substring subs 2) in
+ Some (PVDev (CCISS (c, d)))
+ with Not_found ->
+ try
+ let subs = Pcre.exec ~rex:lv name in
+ let vg = Pcre.get_substring subs 1 in
+ let lv = Pcre.get_substring subs 2 in
+ Some (PVPart (LV (vg, lv)))
+ with Not_found ->
+ None