#!/bin/sh


ifplugstatus_tool=/usr/sbin/ifplugstatus
ethtool_tool=/usr/sbin/ethtool
ip_tool=/sbin/ip

### network devices

netdev_list()
{
    find /sys/class/net/ -type l -printf '%f\n'
}

netdev_is_eth()
{
    local f="/sys/class/net/$1/type"
    [ -s "$f" ] && [ "$(cat "$f")" = "1" ]
}

netdev_is_virtual()
{
    [ -d "/sys/devices/virtual/net/$1" ]
}

netdev_is_real()
{
    [ ! -d "/sys/devices/virtual/net/$1" ]
}

netdev_is_bridge()
{
    [ -d "/sys/class/net/$1/bridge" ]
}

netdev_is_wireless()
{
    [ -h "/sys/class/net/$1/phy80211" ] || [ -d "/sys/class/net/$1/wireless" ]
}

netdev_is_plugged()
{
    [ ! -x "$ifplugstatus_tool" ] || "$ifplugstatus_tool" "$1" >/dev/null 2>/dev/null
    [ "$?" = "2" ]
}

netdev_is_up()
{
    [ ! -x "$ip_tool" ] ||
	[ -n "$( "$ip_tool" link show up dev "$1" 2>/dev/null)" ]
}

netdev_read_mac()
{
    local f="/sys/class/net/$1/address"
    [ ! -s "$f" ] || cat "$f"
}

netdev_read_businfo()
{
    [ ! -x "$ethtool_tool" ] || "$ethtool_tool" -i "$1" 2>/dev/null|
	sed -nr 's,^bus-info:[[:space:]]([^[:space:]]+),\1,p'
}

netdev_list_brif()
{
    ! netdev_is_bridge "$1" ||
    [ ! -d "/sys/class/net/$1/brif" ] ||
	find "/sys/class/net/$1/brif" -type l -printf '%f\n'
}

netdev_find_bridge()
{
    for i in $(netdev_list); do
	netdev_is_bridge "$i" || continue
	[ ! -h "/sys/class/net/$i/brif/$1" ] || echo "$i"
    done
}

netdev_read_info()
{
    /sbin/service haldaemon status >/dev/null 2>/dev/null || return 0

    local iface_udi="$(hal-find-by-property --key=net.interface --string="$1"|head -n1)" #ignore duplicates
    [ -n "$iface_udi" ] || return 0

    local device_udi="$(hal-get-property --udi="$iface_udi" --key=net.originating_device)"
    [ -n "$device_udi" ] || return 0

    local device_subsystem="$(hal-get-property --udi="$device_udi" --key=info.subsystem)"

    case "$device_subsystem" in
	pci)
	    printf '%s\n' \
		"$(hal-get-property --udi="$device_udi" --key=pci.product)"
	;;
	usb)
	    printf '%s\n' \
		"$(hal-get-property --udi="$device_udi" --key=usb.vendor)"
	;;
	pcmcia)
	    printf '%s\n' \
		"$(hal-get-property --udi="$device_udi" --key=info.product)"
	;;
    esac
}

#############

blockdev_list()
{
    find /sys/class/block/ -mindepth 1 -xtype d  -printf '%f\n'
}

blockdev_is_virtual()
{
    [ -d "/sys/devices/virtual/block/$1" ]
}

blockdev_is_removable()
{
    local f="/sys/class/block/$1/removable"
    [ -s "$f" ] && [ "$(cat "$f")" = "1" ]
}

blockdev_read_size()
{
    local f="/sys/class/block/$1/size"
    [ ! -s "$f" ] || cat "$f"
}

partition_list()
{
    for dev in $(blockdev_list); do
      find "/sys/class/block/$dev/" \
        -mindepth 1 -type d -name "$dev*" -printf '%f\n'
    done
}

# convert bytes to human readable form:
# 1 b, 12 b, 123 b, 1.23 Kb, 12.3 Kb, 123 Kb 1.23 Mb etc.
# for localized output use
# SIZE_DEC_PT=$(LC_NUMERIC="$in_language" locale decimal_point)
# SIZE_b="`_ "b"`"
# SIZE_kb="`_ "kb"`"
# SIZE_Mb="`_ "Mb"`"
# SIZE_Gb="`_ "Gb"`"
# SIZE_Tb="`_ "Tb"`"
human_readable_size(){
  local size=$1
  local frac=0
  local byte="${SIZE_b:-b}"
  local units=$byte
  local div=1024
  local u
  for u in "${SIZE_kb:-kb}" "${SIZE_Mb:-Mb}" "${SIZE_Gb:-Gb}" "${SIZE_Tb:-Tb}"; do
    if [ $(($size < 1000)) = 1 ]; then break; fi
    frac=$((($size % $div)*1000/$div))  # we want frac in the range 0..999
    size=$(($size / $div))
    units=$u
  done
  if      [ "$(($size > 99))" = 1 ]; then frac=$(($frac/100))
  else if [ "$(($size > 9))" = 1 ]; then frac=$(printf "%02d" $(($frac/10)))
  fi; fi;

  # add zeroes
  frac=$(printf "%02d" $((frac/10)))

  [ "$units" = "$byte" ] && frac="" || frac="${SIZE_DEC_PT:-.}$frac"
  echo "$size$frac $units"
}

## blockdev_find_symlink $dev $type
##   convert device name from /dev/$dev to /dev/disk/by-$type/* if possible
##   default type is "id"
blockdev_get_symlink(){
  local dev="${1:-}"
  [ -n "$dev" ] || return 0

  local type="${2:-id}"
  [ -n "$type" ] || return 0

  local ret=
  local i
  for i in $(/sbin/udevadm info --name="$dev" --query=symlink 2>/dev/null); do 
    [ -z "${i##disk/by-$type/*}" ] || continue

    # For type=id don't return ata* if scsi* exists
    # It is done automatically due to sorting, but let's keep explicit code here:
    [ "$type" = "id" -a -z "${ret##*/scsi/*}" -a -z "${i##*/ata*}" ] && continue ||:

    ret="/dev/$i"
  done
  echo "${ret:-$dev}"
}

## blockdev_follow_symlink $dev
##   revert of blockdev_find_symlink function
##   find file symlink points to
blockdev_follow_symlink(){
  local dev="${1:-}"
  [ -n "$dev" ] || return 0
  local ret="$(readlink -f "$dev")"
  echo "${ret:-$dev}"
}
