#!/bin/bash
# Author: Steven Shiau <steven _at_ nchc org tw>
# License: GPL

export LC_ALL=C
# part is like /dev/hda1
# wanted is one of start, end, size, type, filesystem or flags.
part="$1"
wanted="$2"

[ -z "$part" -o -z "$wanted" ] && exit 1
check_col_idx() {
  # DEV is like /dev/hda
  # wanted is like "start", "end", "file" (since it's "file system" in SuSE 10.0, and filesystem in Redhat/FC)
  # Example in FC5 with parted-1.7.1-15.fc5
  #[root@fc5101 tmp]# LC_ALL=C parted -s /dev/hda p
  #
  #Disk /dev/hda: 4295MB
  #Sector size (logical/physical): 512B/512B
  #Partition Table: msdos
  #
  #Number  Start   End     Size    Type     File system  Flags
  # 1      32.3kB  4285MB  4285MB  primary  ntfs         boot
  #
  # Different version of parted has different output format, that's why it's so complicated here.
  local DEV=$1
  local wanted=$2
  part_info_tmp=`mktemp /tmp/part_tmp.XXXXXX`
  LC_ALL=C parted -s $DEV p > $part_info_tmp 2>/dev/null
  # force to change the output temp file, no space in "File system"
  LC_ALL=C perl -pi -e "s/File system/Filesystem/g" $part_info_tmp
  # The seq is put in the order of possibility in clonezilla, i.e. filesystem is most used one, then size.
  for i in 6 4 5 3 2 1 7; do
    col="$(grep -i flags $part_info_tmp | awk -F" " "{print \$$i}")"
    if [ -n "$(echo $col | grep -i $wanted)" ]; then
      col_idx=$i
      break
    fi
  done
  [ -f "$part_info_tmp" ] && rm -f $part_info_tmp
  echo $col_idx
}

get_from_parted() {
  p="$(basename $part)"
  target_hd="/dev/${p:0:3}"
  part_index="${p:3}"
  
  part_info=`mktemp /tmp/part.XXXXXX`
  LC_ALL=C parted -s $target_hd p > $part_info 2>/dev/null
  
  case "$wanted" in
    start)
       start_idx="$(check_col_idx $target_hd start)"
       [ -z "$start_idx" ] && exit 1
       part_start=$(grep -E "^[[:space:]]*$part_index\>" $part_info | awk -F" " "{print \$$start_idx}")
       echo "$part_start"
       ;;
    end)
       end_idx="$(check_col_idx $target_hd end)"
       [ -z "$end_idx" ] && exit 1
       part_end=$(grep -E "^[[:space:]]*$part_index\>" $part_info | awk -F" " "{print \$$end_idx}")
       echo "$part_end"
       ;;
    size)
       size_idx="$(check_col_idx $target_hd size)"
       [ -z "$size_idx" ] && exit 1
       part_size=$(grep -E "^[[:space:]]*$part_index\>" $part_info | awk -F" " "{print \$$size_idx}")
       echo "$part_size"
       ;;
    type)
       type_idx="$(check_col_idx $target_hd type)"
       [ -z "$type_idx" ] && exit 1
       part_type=$(grep -E "^[[:space:]]*$part_index\>" $part_info | awk -F" " "{print \$$type_idx}")
       echo "$part_type"
       ;;
    filesystem|fs)
       filesystem_idx="$(check_col_idx $target_hd file)"
       [ -z "$filesystem_idx" ] && exit 1
       part_fs=$(grep -E "^[[:space:]]*$part_index\>" $part_info | awk -F" " "{print \$$filesystem_idx}")
       echo "$part_fs"
       ;;
    flags)
       flags_idx="$(check_col_idx $target_hd flags)"
       [ -z "$flags_idx" ] && exit 1
       part_flags=$(grep -E "^[[:space:]]*$part_index\>" $part_info | awk -F" " "{print \$$flags_idx}")
       echo "$part_flags"
       ;;
  esac
  
  [ -f "$part_info" ] && rm -f $part_info
} # end of get_from_parted

#
get_fs_from_blkid() {
  local part_="$1" 
  local blkinfo TYPE
  if type blkid &>/dev/null; then
    blkinfo="$(mktemp /tmp/blkinfo.XXXXXX)"
    # blikd output example:
    # /dev/sda1: LABEL="/boot" UUID="a9cb47b6-e3ff-4a26-80e2-3fa8d30702e8" SEC_TYPE="ext2" TYPE="ext3" 
    # /dev/VolGroup00/LogVol00: UUID="110bc035-6920-4732-b117-5124843b93b9" SEC_TYPE="ext2" TYPE="ext3" 
    # /dev/VolGroup00/LogVol01: TYPE="swap" UUID="af85b756-39fa-48f0-80e7-b2128d5c87ab"
    # We want to filter to filter them as: TYPE="ext3" only
    blkid $part_ | grep -o -E '\<TYPE="[^[:space:]]*"($|[[:space:]]+)' > $blkinfo
    TYPE=""
    . $blkinfo
    echo "$TYPE"
    [ -f "$blkinfo" ] && rm -f $blkinfo
  fi
}

# First priority is to use blkid to get filesystem, 2 reasons:
# (1) Since parted seems to have problem with ntfs in some case:
# LC_ALL=C parted -s /dev/hdb p
# Model: VMware Virtual IDE Hard Drive (ide)
# Disk /dev/hdb: 8590MB
# Sector size (logical/physical): 512B/512B
# Partition Table: msdos
# 
# Number  Start   End     Size    Type     File system  Flags
#  1      32.3kB  8579MB  8579MB  primary  ntfs         boot
# 
# [root@drblrhvmnet101 ~]# LC_ALL=C parted -s /dev/hdb1 p
# Error: Can't have a partition outside the disk!
#
# (2) Moreover, the method in get_from_parted does NOT work for LV in LVM... blkid can solve the problem. The weakness is blkid does not provide size info, but it's not so used very often in clonezilla, and normally size is not important when cloning.

case "$wanted" in
  filesystem|fs)
     fs="$(get_fs_from_blkid $part)"
     if [ -z "$fs" ]; then
       get_from_parted
     else
       echo "$fs"
     fi
     ;;
  *)
     get_from_parted
     ;;
esac
