5 kx #!/bin/bash
5 kx
5 kx program=`basename $0`
5 kx sbindir=`cd $(dirname ${BASH_SOURCE[0]}) >/dev/null 2>&1 && pwd`
5 kx
5 kx # 14 = target device is not a partition
5 kx # 15 = target device is not found
5 kx EXITSTATUS=0
5 kx
5 kx usage() {
5 kx cat << EOF
5 kx
5 kx Usage: $program [options] [partition]
5 kx
5 kx options:
5 kx -o, --output <list> - output columns
5 kx -n, --no-header - output columns without header line
5 kx
5 kx Available columns (for --output):
5 kx
5 kx DISK device name of HW disk
5 kx ROOT device name of current ROOT partition
5 kx UUID filesystem UUID
5 kx MAJOR device major number
5 kx MINOR device minor number
5 kx
5 kx optional argument:
5 kx
5 kx partition - If 'partition' is present then we assume that the 'partition'
5 kx is a root FS partition. In this case the $program do not try
5 kx to find working root FS partition.
5 kx
5 kx EOF
5 kx }
5 kx
5 kx push_err() {
5 kx local message=$1
5 kx echo -n "$program: " 1>&2 ; echo "${message}" 1>&2
5 kx }
5 kx
5 kx #
5 kx # returns root partition device (such as /dev/part_name)
5 kx #
5 kx root_part() {
5 kx local dev=`findmnt --noheadings --raw / | tr -s ' ' | cut -f2 -d' '`
5 kx if [ "$dev" != "" ] ; then
5 kx echo "$dev"
5 kx return 0
5 kx fi
5 kx }
5 kx
5 kx major_number() {
5 kx local part=$1
5 kx local name=`basename $part`
5 kx
5 kx local major=`ls -l /dev | grep -v ^l | grep ${name} | tr -s ' ' | sed 's/,//g' | cut -f5 -d' ' | sort -u | tr '\n' ',' | sed 's/,$//'`
5 kx echo "${major}"
5 kx }
5 kx
5 kx minor_number() {
5 kx local part=$1
5 kx local name=`basename $part`
5 kx
5 kx local minor=`ls -l /dev | grep -v ^l | grep ${name} | tr -s ' ' | sed 's/,//g' | cut -f6 -d' ' | sort -u | tr '\n' ',' | sed 's/,$//'`
5 kx echo "${minor}"
5 kx }
5 kx
5 kx #
5 kx # returns root partition disk (such as /dev/disk_name)
5 kx #
5 kx root_disk_by_part() {
5 kx local part=$1
5 kx local mjrs=`major_number $1`
5 kx local disks="`lsblk -I ${mjrs} -l -o name,type | grep 'disk\|raid\|loop$' | cut -f1 -d' '`"
5 kx disks="`echo -e "$disks" | sort -r`"
5 kx for line in $disks ; do
5 kx local found=`echo "$part" | grep "$line"`
5 kx if [ "$found" != "" ] ; then
5 kx echo "/dev/$line"
5 kx break
5 kx fi
5 kx done
5 kx }
5 kx
5 kx root_disk() {
5 kx local part=$1
5 kx local name=`basename $part`
5 kx local mjrs=`major_number $1`
5 kx echo "`lsblk -I ${mjrs} -l -o name,type`" | grep $name | while read -r line ; do
5 kx local type=`echo "$line" | tr -s ' ' | cut -f2 -d' '`
5 kx if [ "$type" = "part" ] ; then
5 kx root_disk_by_part $part
5 kx break
5 kx fi
5 kx done
5 kx }
5 kx
5 kx #
5 kx # returns root partition UUID (by /dev/part_name)
5 kx #
5 kx root_uuid() {
5 kx local part=`basename $1`
5 kx local mjrs=`major_number $1`
5 kx echo "`lsblk -I ${mjrs} -l -o name,uuid`" | while read -r line ; do
5 kx local pname=`echo "$line" | tr -s ' ' | cut -f 1 -d ' '`
5 kx local puuid=`echo "$line" | tr -s ' ' | cut -f 2 -d ' '`
5 kx
5 kx if [ `echo "$pname" | grep "$part"` ] ; then
5 kx echo "$puuid"
5 kx break
5 kx fi
5 kx done
5 kx }
5 kx
5 kx
5 kx check_root_partition_device() {
5 kx local part=$1
5 kx local base=`basename $part`
5 kx local mjrs=`major_number $1`
5 kx line="`lsblk -I ${mjrs} -l -o name,type | grep \"$base \" | head -1 | tr -s ' '`"
5 kx if [ "$line" != "" ] ; then
5 kx local name=`echo "$line" | tr -s ' ' | cut -f1 -d' '`
5 kx local type=`echo "$line" | tr -s ' ' | cut -f2 -d' '`
5 kx if [ "$base" = "$name" ] && [ "$type" != "part" ] ; then
5 kx push_err "ERROR: The DEVICE ($part) is not a disk partition"
5 kx EXITSTATUS=14
5 kx exit $EXITSTATUS
5 kx fi
5 kx else
5 kx push_err "ERROR: The DEVICE ($part) not found"
5 kx EXITSTATUS=15
5 kx exit $EXITSTATUS
5 kx fi
5 kx }
5 kx
5 kx
5 kx #
5 kx # Optional argument:
5 kx #
5 kx ROOT_PARTITION=
5 kx
5 kx #
5 kx # Parse options:
5 kx #
5 kx HEADER="yes"
5 kx OTPUTLIST="DISK,ROOT,UUID,MAJOR,MINOR"
5 kx
5 kx while [ 0 ] ; do
5 kx if [ "$1" = "-h" -o "$1" = "--help" ] ; then
5 kx usage
5 kx exit 0
5 kx elif [ "$1" = "-o" -o "$1" = "--output" ] ; then
5 kx if [ "$2" != "" ] ; then
5 kx OTPUTLIST="$2"
5 kx shift 2
5 kx else
5 kx shift 1
5 kx fi
5 kx elif [ "$1" = "-n" -o "$1" = "--no-header" ] ; then
5 kx HEADER="no"
5 kx shift 1
5 kx else
5 kx ROOT_PARTITION="$1"
5 kx break
5 kx fi
5 kx done
5 kx
5 kx #
5 kx # check optional partition (if present):
5 kx #
5 kx if [ "${ROOT_PARTITION}" != "" ] ; then
5 kx if [ ! `echo ${ROOT_PARTITION} | grep "^/dev.*"` ] ; then
5 kx push_err "ERROR: Wrong PARTITION device name: ${ROOT_PARTITION}"
5 kx usage
5 kx exit 1
5 kx fi
5 kx check_root_partition_device ${ROOT_PARTITION}
5 kx fi
5 kx
5 kx
5 kx ################################################################
5 kx # main()
5 kx #
5 kx
5 kx #
5 kx # root partition /dev/... :
5 kx #
5 kx if [ "${ROOT_PARTITION}" != "" ] ; then
5 kx root_part=${ROOT_PARTITION}
5 kx else
5 kx root_part=`root_part`
5 kx fi
5 kx
5 kx #
5 kx # root phy disk /dev/... :
5 kx #
5 kx root_disk=`root_disk ${root_part}`
5 kx
5 kx #
5 kx # root partition UUID :
5 kx #
5 kx root_uuid=`root_uuid ${root_part}`
5 kx
5 kx #
5 kx # root partition device MAJOR number :
5 kx #
5 kx root_major=`major_number ${root_part}`
5 kx
5 kx #
5 kx # root partition device MINOR number :
5 kx #
5 kx root_minor=`minor_number ${root_part}`
5 kx
5 kx
5 kx if [ "$OTPUTLIST" != "" ] ; then
5 kx list=`echo $OTPUTLIST | sed 's/,/ /g' | tr '[:upper:]' '[:lower:]'`
5 kx
5 kx if [ "$HEADER" = "yes" ] ; then
5 kx
5 kx root_disk_len=${#root_disk}
5 kx root_part_len=${#root_part}
5 kx root_uuid_len=${#root_uuid}
5 kx root_major_len=${#root_major}
5 kx if [ ${root_major_len} -lt 5 ] ; then
5 kx root_major_len=5
5 kx fi
5 kx root_minor_len=${#root_minor}
5 kx if [ ${root_minor_len} -lt 5 ] ; then
5 kx root_minor_len=5
5 kx fi
5 kx
5 kx out=""
5 kx for item in $list ; do
5 kx if [ "$item" = "disk" ] ; then
5 kx out="$out `printf '%-*s' ${root_disk_len} 'DISK'`"
5 kx elif [ "$item" = "root" ] ; then
5 kx out="$out `printf '%-*s' ${root_part_len} 'ROOT'`"
5 kx elif [ "$item" = "uuid" ] ; then
5 kx out="$out `printf '%-*s' ${root_uuid_len} 'UUID'`"
5 kx elif [ "$item" = "major" ] ; then
5 kx out="$out `printf '%-*s' ${root_major_len} 'MAJOR'`"
5 kx elif [ "$item" = "minor" ] ; then
5 kx out="$out `printf '%-*s' ${root_minor_len} 'MINOR'`"
5 kx fi
5 kx done
5 kx out=`echo "$out" | sed 's/^[ \t]*//;s/[ \t]*$//'`
5 kx echo "$out"
5 kx else
5 kx root_disk_len=${#root_disk}
5 kx root_part_len=${#root_part}
5 kx root_uuid_len=${#root_uuid}
5 kx root_major_len=${#root_major}
5 kx root_minor_len=${#root_minor}
5 kx fi
5 kx
5 kx out=""
5 kx for item in $list ; do
5 kx if [ "$item" = "disk" ] ; then
5 kx out="$out `printf '%-*s' ${root_disk_len} ${root_disk}`"
5 kx elif [ "$item" = "root" ] ; then
5 kx out="$out `printf '%-*s' ${root_part_len} ${root_part}`"
5 kx elif [ "$item" = "uuid" ] ; then
5 kx out="$out `printf '%-*s' ${root_uuid_len} ${root_uuid}`"
5 kx elif [ "$item" = "major" ] ; then
5 kx out="$out `printf '%-*s' ${root_major_len} ${root_major}`"
5 kx elif [ "$item" = "minor" ] ; then
5 kx out="$out `printf '%-*s' ${root_minor_len} ${root_minor}`"
5 kx fi
5 kx done
5 kx out=`echo "$out" | sed 's/^[ \t]*//;s/[ \t]*$//'`
5 kx echo "$out"
5 kx fi