Radix cross Linux

The main Radix cross Linux repository contains the build scripts of packages, which have the most complete and common functionality for desktop machines

452 Commits   2 Branches   1 Tag
#!/bin/bash

program=`basename $0`
sbindir=`cd $(dirname ${BASH_SOURCE[0]}) >/dev/null 2>&1 && pwd`

# 14 = target device is not a partition
# 15 = target device is not found
EXITSTATUS=0

usage() {
  cat << EOF

Usage: $program [options] [partition]

options:
    -o, --output <list> - output columns
    -n, --no-header     - output columns without header line

  Available columns (for --output):

               DISK  device name of HW disk
               ROOT  device name of current ROOT partition
               UUID  filesystem UUID
              MAJOR  device major number
              MINOR  device minor number

optional argument:

     partition     - If 'partition' is present then we assume that the 'partition'
                     is a root FS partition. In this case the $program do not try
                     to find working root FS partition.

EOF
}

push_err() {
  local message=$1
  echo -n "$program: " 1>&2 ; echo "${message}" 1>&2
}

#
# returns root partition device (such as /dev/part_name)
#
root_part() {
  local dev=`findmnt --noheadings --raw / | tr -s ' ' | cut -f2 -d' '`
  if [ "$dev" != "" ] ; then
    echo "$dev"
    return 0
  fi
}

major_number() {
  local part=$1
  local name=`basename $part`

  local major=`ls -l /dev | grep -v ^l | grep ${name} | tr -s ' ' | sed 's/,//g' | cut -f5 -d' ' | sort -u | tr '\n' ',' | sed 's/,$//'`
  echo "${major}"
}

minor_number() {
  local part=$1
  local name=`basename $part`

  local minor=`ls -l /dev | grep -v ^l | grep ${name} | tr -s ' ' | sed 's/,//g' | cut -f6 -d' ' | sort -u | tr '\n' ',' | sed 's/,$//'`
  echo "${minor}"
}

#
# returns root partition disk (such as /dev/disk_name)
#
root_disk_by_part() {
  local part=$1
  local mjrs=`major_number $1`
  local disks="`lsblk -I ${mjrs} -l -o name,type | grep 'disk\|raid\|loop$' | cut -f1 -d' '`"
  disks="`echo -e "$disks" | sort -r`"
  for line in $disks ; do
    local found=`echo "$part" | grep "$line"`
    if [ "$found" != "" ] ; then
      echo "/dev/$line"
      break
    fi
  done
}

root_disk() {
  local part=$1
  local name=`basename $part`
  local mjrs=`major_number $1`
  echo "`lsblk -I ${mjrs} -l -o name,type`" | grep $name | while read -r line ; do
    local type=`echo "$line" | tr -s ' ' | cut -f2 -d' '`
    if [ "$type" = "part" ] ; then
      root_disk_by_part $part
      break
    fi
  done
}

#
# returns root partition UUID (by /dev/part_name)
#
root_uuid() {
  local part=`basename $1`
  local mjrs=`major_number $1`
  echo "`lsblk -I ${mjrs} -l -o name,uuid`" | while read -r line ; do
    local pname=`echo "$line" | tr -s ' ' | cut -f 1 -d ' '`
    local puuid=`echo "$line" | tr -s ' ' | cut -f 2 -d ' '`

    if [ `echo "$pname" | grep "$part"` ] ; then
      echo "$puuid"
      break
    fi
  done
}


check_root_partition_device() {
  local part=$1
  local base=`basename $part`
  local mjrs=`major_number $1`
  line="`lsblk -I ${mjrs} -l -o name,type | grep \"$base \" | head -1 | tr -s ' '`"
  if [ "$line" != "" ] ; then
    local name=`echo "$line" | tr -s ' ' | cut -f1 -d' '`
    local type=`echo "$line" | tr -s ' ' | cut -f2 -d' '`
    if [ "$base" = "$name" ] && [ "$type" != "part" ] ; then
      push_err "ERROR: The DEVICE ($part) is not a disk partition"
      EXITSTATUS=14
      exit $EXITSTATUS
    fi
  else
    push_err "ERROR: The DEVICE ($part) not found"
    EXITSTATUS=15
    exit $EXITSTATUS
  fi
}


#
# Optional argument:
#
ROOT_PARTITION=

#
# Parse options:
#
HEADER="yes"
OTPUTLIST="DISK,ROOT,UUID,MAJOR,MINOR"

while [ 0 ] ; do
  if [ "$1" = "-h" -o "$1" = "--help" ] ;  then
    usage
    exit 0
  elif [ "$1" = "-o" -o "$1" = "--output" ] ; then
    if [ "$2" != "" ] ; then
      OTPUTLIST="$2"
      shift 2
    else
      shift 1
    fi
  elif [ "$1" = "-n" -o "$1" = "--no-header" ] ; then
    HEADER="no"
    shift 1
  else
    ROOT_PARTITION="$1"
    break
  fi
done

#
# check optional partition (if present):
#
if [ "${ROOT_PARTITION}" != "" ] ; then
  if [ ! `echo ${ROOT_PARTITION} | grep "^/dev.*"` ] ; then
    push_err "ERROR: Wrong PARTITION device name: ${ROOT_PARTITION}"
    usage
    exit 1
  fi
  check_root_partition_device ${ROOT_PARTITION}
fi


################################################################
# main()
#

#
# root partition /dev/... :
#
if [ "${ROOT_PARTITION}" != "" ] ; then
  root_part=${ROOT_PARTITION}
else
  root_part=`root_part`
fi

#
# root phy disk /dev/... :
#
root_disk=`root_disk ${root_part}`

#
# root partition UUID :
#
root_uuid=`root_uuid ${root_part}`

#
# root partition device MAJOR number :
#
root_major=`major_number ${root_part}`

#
# root partition device MINOR number :
#
root_minor=`minor_number ${root_part}`


if [ "$OTPUTLIST" != "" ] ; then
  list=`echo $OTPUTLIST | sed 's/,/ /g' | tr '[:upper:]' '[:lower:]'`

  if [ "$HEADER" = "yes" ] ; then

    root_disk_len=${#root_disk}
    root_part_len=${#root_part}
    root_uuid_len=${#root_uuid}
    root_major_len=${#root_major}
    if [ ${root_major_len} -lt 5 ] ; then
      root_major_len=5
    fi
    root_minor_len=${#root_minor}
    if [ ${root_minor_len} -lt 5 ] ; then
      root_minor_len=5
    fi

    out=""
    for item in $list ; do
      if   [ "$item" = "disk"    ] ; then
        out="$out `printf '%-*s' ${root_disk_len} 'DISK'`"
      elif [ "$item" = "root"    ] ; then
        out="$out `printf '%-*s' ${root_part_len} 'ROOT'`"
      elif [ "$item" = "uuid"    ] ; then
        out="$out `printf '%-*s' ${root_uuid_len} 'UUID'`"
      elif [ "$item" = "major" ] ; then
        out="$out `printf '%-*s' ${root_major_len} 'MAJOR'`"
      elif [ "$item" = "minor" ] ; then
        out="$out `printf '%-*s' ${root_minor_len} 'MINOR'`"
      fi
    done
    out=`echo "$out" | sed 's/^[ \t]*//;s/[ \t]*$//'`
    echo "$out"
  else
    root_disk_len=${#root_disk}
    root_part_len=${#root_part}
    root_uuid_len=${#root_uuid}
    root_major_len=${#root_major}
    root_minor_len=${#root_minor}
  fi

  out=""
  for item in $list ; do
    if   [ "$item" = "disk"    ] ; then
      out="$out `printf '%-*s' ${root_disk_len} ${root_disk}`"
    elif [ "$item" = "root"    ] ; then
      out="$out `printf '%-*s' ${root_part_len} ${root_part}`"
    elif [ "$item" = "uuid"    ] ; then
      out="$out `printf '%-*s' ${root_uuid_len} ${root_uuid}`"
    elif [ "$item" = "major" ] ; then
      out="$out `printf '%-*s' ${root_major_len} ${root_major}`"
    elif [ "$item" = "minor" ] ; then
      out="$out `printf '%-*s' ${root_minor_len} ${root_minor}`"
    fi
  done
  out=`echo "$out" | sed 's/^[ \t]*//;s/[ \t]*$//'`
  echo "$out"
fi