Guest User

lsblk.sh

a guest
May 4th, 2020
29
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 14.75 KB | None | 0 0
  1. #! /bin/sh
  2.  
  3. # Copyright (c) 2016-2019 Slawomir Wojciech Wojtczak (vermaden)
  4. # All rights reserved.
  5. #
  6. # THIS SOFTWARE USES FREEBSD LICENSE (ALSO KNOWN AS 2-CLAUSE BSD LICENSE)
  7. # https://www.freebsd.org/copyright/freebsd-license.html
  8. #
  9. # Redistribution and use in source and binary forms, with or without
  10. # modification, are permitted provided that following conditions are met:
  11. # 1. Redistributions of source code must retain the above copyright
  12. #    notice, this list of conditions and the following disclaimer.
  13. # 2. Redistributions in binary form must reproduce the above copyright
  14. #    notice, this list of conditions and the following disclaimer in the
  15. #    documentation and/or other materials provided with the distribution.
  16. #
  17. # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS 'AS IS' AND ANY
  18. # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. # DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
  21. # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24. # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. #
  28. # ------------------------------
  29. # REPLACEMENT FOR LINUX lsblk(8)
  30. # ------------------------------
  31. # vermaden [AT] interia [DOT] pl
  32. # https://vermaden.wordpress.com
  33.  
  34. PATH=${PATH}:/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin
  35.  
  36. # DISPLAY HELP/USAGE/EXAMPLES
  37. __usage() {
  38.   local NAME="${0##*/}"
  39.   cat << __EOF
  40. usage:
  41.  
  42.   BASIC USAGE INFORMATION
  43.   =======================
  44.   # ${NAME} [DISK]
  45.  
  46. example(s):
  47.  
  48.   LIST ALL BLOCK DEVICES IN SYSTEM
  49.   --------------------------------
  50.   # ${NAME}
  51.   DEVICE         MAJ:MIN SIZE TYPE                      LABEL MOUNT
  52.   ada0             0:92  932G GPT                           - -
  53.     ada0p1         0:100 200M efi                    efiboot0 -
  54.     ada0p2         0:101 512K freebsd-boot           gptboot0 -
  55.     <FREE>         -:-   492K -                             - -
  56.     ada0p3         0:102 931G freebsd-zfs                zfs0 <ZFS>
  57.     ada0p3.eli     0:106 931G freebsd-zfs                   - <ZFS>
  58.  
  59.  
  60.   LIST ONLY da1 BLOCK DEVICE
  61.   --------------------------
  62.   # ${NAME} da1
  63.   DEVICE         MAJ:MIN SIZE TYPE                      LABEL MOUNT
  64.   da1              0:80  2.0G MBR                           - -
  65.     da1s1          0:80  2.0G freebsd                       - -
  66.       da1s1a       0:81  1.0G freebsd-ufs                root /
  67.       da1s1b       0:82  1.0G freebsd-swap               swap SWAP
  68.  
  69. hint(s):
  70.  
  71.   DISPLAY PHYSICAL DISKS
  72.   ----------------------
  73.   # sysctl kern.disks
  74.   kern.disks: ada0 da0 da1
  75.  
  76.   DISPLAY MEMORY BACKED DISKS
  77.   ---------------------------
  78.   # mdconfig -l
  79.   md0
  80.  
  81. __EOF
  82.   exit 1
  83. }
  84. # __usage() ENDED
  85.  
  86. # GET MAJOR/MINOR NUMBERS
  87. __major_minor() { # 1=DEV
  88.   local DEV=${1}
  89.   MAJ=$( stat -f "%Hr" /dev/${DEV} )
  90.   MIN=$( stat -f "%Lr" /dev/${DEV} )
  91. }
  92. # __major_minor() ENDED
  93.  
  94. # DETECT IF SWAP IS BEING USED
  95. __swap_mount() { # 1=DEV
  96.   local DEV="${1}"
  97.   SWAP_FOUND=0
  98.  
  99.   # DETECT SWAP BY RAW DEVICE
  100.   if swapctl -l | grep -q -- ${DEV} 2> /dev/null
  101.   then
  102.     TYPE=freebsd-swap
  103.     MOUNT=SWAP
  104.     LABEL="-"
  105.     SWAP_FOUND=1
  106.     return
  107.   fi
  108.  
  109.   # DETECT SWAP BY LABEL
  110.   while read LABELER GARBAGE PROVIDER
  111.   do
  112.     if [ "${DEV}" = "${PROVIDER}" ]
  113.     then
  114.       if swapctl -l | grep -q -- ${LABELER} 2> /dev/null
  115.       then
  116.         TYPE=freebsd-swap
  117.         LABEL=${LABELER}
  118.         MOUNT=SWAP
  119.         SWAP_FOUND=1
  120.         break
  121.       fi
  122.     fi
  123.   done << __EOF
  124.     $( echo "${GLABEL}" )
  125. __EOF
  126. }
  127. # __swap_mount() ENDED
  128.  
  129. # DETECT TYPE WITH fstyp(8) TOOL
  130. __type() { # 1=DEV
  131.   local DEV=${1}
  132.   TYPE=$( fstyp -u /dev/${DEV} 2> /dev/null )
  133.   [ "${TYPE}" = "" ] && __swap_mount ${DEV}
  134.   [ "${TYPE}" = "" ] && TYPE="-"
  135. }
  136. # __type() ENDED
  137.  
  138. # DETECT MOUNT/LABEL IF POSSIBLE
  139. __mount_label() { # 1=TARGET
  140.   local TARGET="${1}"
  141.   local MOUNT_FOUND=0
  142.   local LABEL_FOUND=0
  143.   LABEL="-"
  144.   if [ "${SWAP_FOUND}" = "1" ]
  145.   then
  146.     local MOUNT_FOUND=1
  147.   else
  148.     MOUNT="-"
  149.   fi
  150.  
  151.   # CHECK IF DEVICE EXISTS
  152.   [ ! -e /dev/${TARGET} ] && return
  153.  
  154.   # TRY CLASSIC MOUNT POINT WITH DEVICE NAME
  155.   if [ "${MOUNT_FOUND}" != "1" ]
  156.   then
  157.     MOUNT=$( mount | grep "/dev/${TARGET} " | awk 'END{print $3}' )
  158.     if [ "${MOUNT}" = "" ]
  159.     then
  160.       MOUNT="-"
  161.     else
  162.       local MOUNT_FOUND=1
  163.     fi
  164.   fi
  165.  
  166.   # GET LABEL/MOUNT FOR UFS/zfs(8)/msdosfs(8) FILESYSTEM
  167.   case ${TYPE} in
  168.     (freebsd-ufs)
  169.       LABEL=$( tunefs -p /dev/${TARGET} 2>&1 | awk '/volume label/ {print $5}' )
  170.       if [ "${LABEL}" = "" ]
  171.       then
  172.         LABEL="-"
  173.       else
  174.         LABEL="ufs/${LABEL}"
  175.         local LABEL_FOUND=1
  176.       fi
  177.       ;;
  178.     (freebsd-zfs)
  179.       # zfs(8) IS NEVER MOUNTED BY RAW DEVICE NAME
  180.       # SO NO NEED TO CHECK IF MOUNT_FOUND = 1 HERE
  181.       MOUNT="<ZFS>"
  182.       local MOUNT_FOUND=1
  183.       ;;
  184.     (msdosfs)
  185.       LABEL=$( file -s /dev/${DEV} | tr ',' '\n' | awk -F '"' '/label:/ {print $2}' )
  186.       if [ "${LABEL}" = "" ]
  187.       then
  188.         LABEL="-"
  189.       else
  190.         LABEL="msdosfs/${LABEL}"
  191.         local LABEL_FOUND=1
  192.       fi
  193.       ;;
  194.     (exfat)
  195.       if which exfatlabel 1> /dev/null 2> /dev/null
  196.       then
  197.         LABEL=$( exfatlabel /dev/${DEV} 2> /dev/null )
  198.         if [ "${LABEL}" = "" ]
  199.         then
  200.           LABEL="-"
  201.         else
  202.           LABEL="exfat/${LABEL}"
  203.           local LABEL_FOUND=1
  204.         fi
  205.       fi
  206.       ;;
  207.   esac
  208.  
  209.   # GET LABEL USING glabel(8)
  210.   if [ "${LABEL_FOUND}" != "1" ]
  211.   then
  212.     # TRY GLABEL MOUNTPOINT AS msdosfs MOUNT IS NOT POSSIBLE WITHOUT GPT/MBR
  213.     local GLABEL_GREP=$( echo "${GLABEL}" | grep -v ufsid | grep "${TARGET}\$" )
  214.     if [ "${GLABEL_GREP}" = "" ]
  215.     then
  216.       LABEL="-"
  217.     else
  218.       while read PROVIDER STATUS DEVICE
  219.       do
  220.         LABEL=$( echo "${GLABEL_GREP}" | grep -m 1 "${TARGET}"  | awk '{print $1}' )
  221.         local LABEL_FOUND=1
  222.         break
  223.       done << ______EOF
  224.         $( echo "${GLABEL_GREP}" )
  225. ______EOF
  226.     fi
  227.   fi
  228.  
  229.   # GET MOUNT USING glabel(8)
  230.   if [ "${MOUNT_FOUND}" != "1" ]
  231.   then
  232.     # TRY GLABEL MOUNTPOINT AS msdosfs MOUNT IS NOT POSSIBLE WITHOUT GPT/MBR
  233.     local GLABEL_GREP=$( echo "${GLABEL}" | grep -v ufsid | grep "${TARGET}\$" )
  234.     if [ "${GLABEL_GREP}" != "" ]
  235.     then
  236.       while read PROVIDER STATUS DEVICE
  237.       do
  238.         MOUNT=$( mount | grep "${PROVIDER}" | awk 'END{print $3}' )
  239.         if [ "${MOUNT}" = "" ]
  240.         then
  241.           MOUNT="-"
  242.         else
  243.           local MOUNT_FOUND=1
  244.         fi
  245.         break
  246.       done << ______EOF
  247.         $( echo "${GLABEL_GREP}" )
  248. ______EOF
  249.     fi
  250.   fi
  251.  
  252.   # GET MOUNT FROM fuse(8)
  253.   if [ "${MOUNT_FOUND}" != "1" ]
  254.   then
  255.     local FUSE_PIDS=$( pgrep mount.exfat ntfs-3g | tr '\n' ',' | sed '$s/.$//' )
  256.     if [ "${FUSE_PIDS}" != "" ]
  257.     then
  258.       local FUSE_MOUNTS=$( ps -p "${FUSE_PIDS}" -o command | sed 1d | sort -u )
  259.       MOUNT=$( echo "${FUSE_MOUNTS}" | grep "/dev/${TARGET} " | awk '{print $3}' )
  260.       if [ "${MOUNT}" = "" ]
  261.       then
  262.         MOUNT="-"
  263.       else
  264.         local MOUNT_FOUND=1
  265.       fi
  266.     fi
  267.   fi
  268.  
  269.   # GET LABEL FROM gpart(8)
  270.   if [ "${LABEL_FOUND}" != "1" ]
  271.   then
  272.     LABEL=$( gpart show -p -l ${DEV} 2> /dev/null | sed 's|=>||g' | sed 's-\[active\]--g' | grep "${TARGET} " | awk '{print $4}' )
  273.     if [ "${LABEL}" = "" -o "${LABEL}" = "(null)" ]
  274.     then
  275.       LABEL="-"
  276.     else
  277.       LABEL="gpt/${LABEL}"
  278.     fi
  279.   fi
  280.   SWAP_FOUND=0
  281. }
  282. # __mount_label() ENDED
  283.  
  284. # LIST BLOCK DEVICES
  285. __list_block_devices() {
  286.   # FIRST 1000 DEVICES OF EACH CLASS SHOULD DO
  287.   for I in ada da mmcsd md vtbd
  288.   do
  289.     ls -1 /dev/${I}[0-9]           2> /dev/null
  290.     ls -1 /dev/${I}[0-9][0-9]      2> /dev/null
  291.     ls -1 /dev/${I}[0-9][0-9][0-9] 2> /dev/null
  292.   done \
  293.     | sed 's|/dev/||g' \
  294.     | sort -u \
  295.     | sed '/^s*$/d'
  296. }
  297. # __list_block_devices() ENDED
  298.  
  299. # PRINT DEVICES AND PARTITIONS
  300. __print_parts() { # 1=NAME 2=TYPE 3=SIZE 4=SIZE_FREE
  301.   local NAME=${1}
  302.   local TYPE=${2}
  303.   local SIZE=${3}
  304.   local SIZE_FREE=${4}
  305.  
  306.   case ${TYPE} in
  307.     (free)
  308.       # REMOVE BRACKETS FROM SIZE
  309.       local SIZE_FREE=$( echo ${SIZE_FREE} | tr -d '()' )
  310.       # FIRST 16 SECTORS ARE ALWAYS EMPTY ON bsdlabel(8) PARTITION SCHEMA
  311.       [ "${SIZE_FREE}" = "8.0K" ] && return
  312.       # OUTPUT
  313.       printf "${FORMAT}" "<FREE>" - - ${SIZE_FREE} "-" ${LABEL} ${MOUNT}
  314.       ;;
  315.     (*)
  316.       # NEEDED FOR bsdlabel(8) ON WHOLE DISK WITHOUT PARTITION
  317.       # WORKAROUND FOR gpart(8) BUG 241004
  318.       # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=241004
  319.       if [ "${TYPE}" = "!0" ]
  320.       then
  321.         local TYPE=freebsd-ufs
  322.       fi
  323.  
  324.       # REMOVE BRACKETS FROM SIZE
  325.       local SIZE=$( echo ${SIZE} | tr -d '()' )
  326.       [ "${LABEL}" = "" ] && local LABEL="-"
  327.       [ "${MOUNT}" = "" ] && local MOUNT="-"
  328.       __major_minor ${NAME}
  329.       printf "${FORMAT}" ${NAME} ${MAJ} ${MIN} ${SIZE} ${TYPE} ${LABEL} ${MOUNT}
  330.       if [ -e /dev/${NAME}.eli ]
  331.       then
  332.         # GET GELI MOUNT/LABEL/MAJOR/MINOR
  333.         __major_minor ${NAME}.eli
  334.         __type ${NAME}.eli
  335.         __mount_label ${NAME}.eli
  336.         printf "${FORMAT}" ${NAME}.eli ${MAJ} ${MIN} ${SIZE} ${TYPE} ${LABEL} ${MOUNT}
  337.         MOUNT="-"
  338.       fi
  339.       ;;
  340.   esac
  341. }
  342. # __print_parts() ENDED
  343.  
  344. # WHEN GPART OUTPUT EXISTS (partition table / not entire device)
  345. __gpart_present() { # 1=DEV
  346.   local DEV=${1}
  347.   local TYPE="-"
  348.   local SIZE="-"
  349.   local SIZE_FREE="-"
  350.   # CHECK IF DEVICE EXISTS
  351.   [ ! -e /dev/${DEV} ] && return
  352.   local GPART=$( gpart show -p ${DEV} 2> /dev/null )
  353.  
  354.   # WORKAROUND FOR gpart(1) BUG 240998
  355.   # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=240998
  356.   TYPE_EXFAT_HELPER_DEVICE=$( echo "${GPART}" | head -1 | sed 's-\[active\]--g' | awk '{print $5}' )
  357.   if [ "${TYPE_EXFAT_HELPER_DEVICE}" = "MBR" ]
  358.   then
  359.     TYPE_EXFAT_HELPER=$( fstyp -u /dev/${DEV} 2> /dev/null )
  360.     if [ "${TYPE_EXFAT_HELPER}" = "exfat" ]
  361.     then
  362.       TYPE=exfat
  363.       SIZE=$( diskinfo -v ${DEV} 2> /dev/null | awk '/mediasize in bytes/ {print $NF}' | tr -d '()' )
  364.       __print_parts ${DEV} ${TYPE} ${SIZE} -
  365.       unset TYPE_EXFAT_HELPER_DEVICE
  366.       unset TYPE_EXFAT_HELPER
  367.       continue
  368.     fi
  369.   fi
  370.   unset TYPE_EXFAT_HELPER_DEVICE
  371.   unset TYPE_EXFAT_HELPER
  372.  
  373.   # READ PARTITIONS OF PROVIDER
  374.   local GPART=$( echo "${GPART}" | sed 's-\[active\]--g' | sed 's|=>||g' )
  375.   # PARSE gpart(8) OUTPUT
  376.   echo "${GPART}" \
  377.     | while read BEG END NAME TYPE SIZE SIZE_FREE
  378.       do
  379.         # VISITED ONLY ONCE FOR WHOLE DEVICE
  380.         if [ ${LEVEL_DEV} = "0" ]
  381.         then
  382.           # WHOLE DEVICE
  383.           LEVEL_DEV=1
  384.           FORMAT="${FORMAT_L0}"
  385.           __print_parts ${NAME} ${TYPE} ${SIZE} ${SIZE_FREE}
  386.         else
  387.           # PARTITION
  388.           FORMAT="${FORMAT_L1}"
  389.           # READ PARTITIONS OF PROVIDER
  390.           local GPART_PARTS=$( gpart show -p ${NAME} 2> /dev/null | sed 's-\[active\]--g' | sed 's|=>||g' )
  391.           # PARSE gpart(8) OUTPUT
  392.           if [ "${GPART_PARTS}" != "" ]
  393.           then
  394.             # PARTITION IN PARTITION
  395.             [ ! -e /dev/${NAME} ] && return
  396.             # PARSE DEVICE
  397.             echo "${GPART_PARTS}" \
  398.               | while read BEG END NAMEONE TYPE SIZE SIZE_FREE
  399.                 do
  400.  
  401.  
  402.  
  403.                   # WORKAROUND FOR gpart(1) BUG <SUBMIT>
  404.                   # https://  SUBMIT / NEW / BUG
  405.                   TYPE_EXFAT_HELPER_DEVICE=$( echo "${GPART_PARTS}" | grep ${NAMEONE} | awk '{print $4}' )
  406.                   if [ "${TYPE_EXFAT_HELPER_DEVICE}" = "ntfs" ]
  407.                   then
  408.                     TYPE_EXFAT_HELPER=$( fstyp -u ${NAMEONE} 2> /dev/null )
  409.                     if [ "${TYPE_EXFAT_HELPER}" = "exfat" ]
  410.                     then
  411.                       TYPE=exfat
  412.                     fi
  413.                   fi
  414.                   unset TYPE_EXFAT_HELPER_DEVICE
  415.                   unset TYPE_EXFAT_HELPER
  416.  
  417.  
  418.  
  419.  
  420.                   # VISITED ONLY ONCE FOR WHOLE DEVICE
  421.                   if [ ${LEVEL_PAR} = "0" ]
  422.                   then
  423.                     # WHOLE DEVICE
  424.                     LEVEL_PAR=1
  425.                     FORMAT="${FORMAT_L1}"
  426.                   else
  427.                     # PARTITION
  428.                     FORMAT="${FORMAT_L2}"
  429.                   fi
  430.                   # CHECK IF SWAP IS ENABLED FOR SWAP DEVICES
  431.                   [ "${TYPE}" = "freebsd-swap" ] && __swap_mount ${NAMEONE}
  432.                   __mount_label ${NAMEONE}
  433.                   __print_parts ${NAMEONE} ${TYPE} ${SIZE} ${SIZE_FREE}
  434.                 done
  435.           else
  436.             # FILESYSTEM
  437.             [ "${TYPE}" = "freebsd-swap" ] && __swap_mount ${DEV}
  438.             __mount_label ${NAME}
  439.             __print_parts ${NAME} ${TYPE} ${SIZE} ${SIZE_FREE}
  440.           fi
  441.         fi
  442.       done
  443. }
  444. # __gpart_present() ENDED
  445.  
  446. # WHEN GPART OUTPUT DO NOT EXISTS (no partition table / entire device)
  447. __gpart_absent() { # 1=DEV
  448.   local DEV=${1}
  449.   # EXIT IF DEVICE DOES NOT EXISTS
  450.   [ ! -e /dev/${DEV} ] && return
  451.   local SIZE=$( diskinfo -v ${DEV} 2> /dev/null | awk '/mediasize in bytes/ {print $NF}' | tr -d '()' )
  452.   local SIZE_FREE="-"
  453.   __type ${DEV}
  454.   __mount_label ${DEV}
  455.   [ "${SIZE}"  = "" ] && local SIZE="-"
  456.   [ "${TYPE}"  = "" ] && local TYPE="-"
  457.   [ "${LABEL}" = "" ] && local LABEL="-"
  458.   [ "${MOUNT}" = "" ] && local MOUNT="-"
  459.   __print_parts ${DEV} ${TYPE} ${SIZE} ${SIZE_FREE}
  460. }
  461. # __gpart_absent() ENDED
  462.  
  463. # PARSE ARGUMENTS IF THERE ARE ANY
  464. LEVEL_DEV=0
  465. LEVEL_PAR=0
  466. GLABEL=$( glabel status | sed 1d )
  467. DISKS=$( __list_block_devices )
  468. case ${#} in
  469.   (0)
  470.     # LIST ALL DISKS
  471.     :
  472.     ;;
  473.   (1)
  474.     # SINGLE ARGUMENT MEANS SINGLE DISK OR HELP
  475.     case ${1} in
  476.       (h|-h|--h|help|-help|--help)
  477.         __usage
  478.         ;;
  479.     esac
  480.     # SINGLE DISK CHECK
  481.     if echo "${DISKS}" | grep -q -- "${1}"
  482.     then
  483.       DISKS="${1}"
  484.     else
  485.       echo "NOPE: disk '${1}' does not exist in the system"
  486.       echo
  487.       __usage
  488.     fi
  489.     ;;
  490.   (*)
  491.     # ONLY '0' and '1' ARGUMENTS ARE COVERED
  492.     __usage
  493.     ;;
  494. esac
  495.  
  496. # SET OUTPUT FORMAT AND PRINT HEADER
  497.     FORMAT_L0="%-14s %3s:%-3s %4s %-18s %20s %s\n"
  498.   FORMAT_L1="  %-12s %3s:%-3s %4s %-18s %20s %s\n"
  499. FORMAT_L2="    %-10s %3s:%-3s %4s %-18s %20s %s\n"
  500. FORMAT="${FORMAT_L0}"
  501. printf "${FORMAT}" DEVICE MAJ MIN SIZE TYPE LABEL MOUNT
  502.  
  503. # DO THE JOB
  504. echo "${DISKS}" \
  505.   | while read DEVICE
  506.     do
  507.       if gpart show ${DEVICE} 1> /dev/null 2> /dev/null
  508.       then
  509.         __gpart_present ${DEVICE}
  510.       else
  511.         __gpart_absent ${DEVICE}
  512.       fi
  513.     done
Add Comment
Please, Sign In to add comment