+#----------------------------------------------------------------------
+# Searching for devices, partitions and LVs.
+
+# Convert "/dev/foo" into "foo". Returns $device.
+function strip_slash_dev {
+ device=$(echo "$1" | sed 's|^/dev/||')
+}
+
+# The 'lvs' utility returns devices like '/dev/sda2(0)'. I've no
+# idea what the number in parentheses is, but remove /dev/ and the
+# strange number.
+function device_of_lvs_device {
+ strip_slash_dev "$1"
+ device=$(echo "$device" | sed 's|(.*)$||')
+}
+
+# All functions in this section assume that physical block devices
+# (things corresponding to hard disks in the system) are called
+# hd[a-z]+ or sd[a-z]+
+
+# Get list of physical block devices. Sets variable $devices
+# to something like "sda sdb".
+function search_devices {
+ devices=$(cd /sys/block && /bin/ls -d [hs]d*)
+}
+
+# Get list of partitions from a physical block device. Sets
+# variable $partitions to something like "sda1 sda2 sda3".
+# See also: search_parts
+function get_partitions {
+ partitions=$(cd /sys/block/"$1" && /bin/ls -d "$1"*)
+}
+
+# Given a partition (eg. "sda1" or "VolGroup00/LogVol00") return
+# the physical block device which contains it. In the case where
+# we are given an LV, this is supposed to do the right thing and
+# go back through the layers until it gets to the physical block
+# device. Returns $device set to something like "sda".
+function block_device_of_part {
+ local part="$1" vg_name lv_name pv
+
+ if matches_regexp '^[hs]d[a-z]+[0-9]*$' "$part"; then
+ device=$(echo "$part" | sed 's|[0-9]*$||')
+ return 0
+ fi
+
+ # Not a partition name, so it's a LV name. Ask lvs to
+ # do the hard work.
+ lvs --noheadings -o vg_name,lv_name,devices > lvs
+ while read vg_name lv_name pv; do
+ if [ "$vg_name/$lv_name" = "$part" \
+ -o "mapper/$vg_name-$lv_name" = "$part" ]; then
+ device_of_lvs_device "$pv" ;# sets $device to (eg.) "sda1"
+ block_device_of_part "$device"
+ return 0
+ fi
+ done < lvs
+
+ # Help ... block device not found.
+ log block_device_of_part: block device cannot be resolved: $part
+ device="$part"
+}
+
+# search_parts $devices examines the list of devices and looks for
+# partitions or LVs on just those devices. Sets variable $parts to
+# something like "sda1 VolGroup00/LogVol00".
+function search_parts {
+ local vg_name lv_name pv pvs="" device partition partitions
+
+ parts=""
+
+ lvs --noheadings -o vg_name,lv_name,devices > lvs
+ while read vg_name lv_name pv; do
+ # Get just the partition name (eg. "sda2").
+ device_of_lvs_device "$pv"; pv="$device"
+ # Get just the block device name (eg. "sda").
+ block_device_of_part "$pv"
+
+ log search_parts: pv $pv device $device lv $vg_name/$lv_name
+
+ # A device in our list of devices to consider?
+ if word_in_list $device "$@"; then
+ log search_parts: adding $vg_name/$lv_name
+ parts="$parts $vg_name/$lv_name"
+ pvs="$pvs $pv"
+ fi
+ done < lvs
+
+ log search_parts: after lvs, parts $parts pvs $pvs
+
+ # Look for non-LVM partitions, but ignore any which are PVs
+ # as identified above.
+ for device in "$@"; do
+ get_partitions "$device"
+ for partition in $partitions; do
+ if ! word_in_list $partition $pvs; then
+ log search_parts: adding $partition
+ parts="$parts $partition"
+ fi
+ done
+ done
+
+ # $parts is returned.
+}