#!/bin/bash
#Barry Kauler www.puppylinux.com
#LGPL 2007 Puppy Linux www.puppylinux.com
#17 june 2007
#21 June 2007 BK:
#some usb adaptors have slots for cards, plugging/unplugging these cards
#does not cause a hotplug event and the kernel does not update /proc.
#'disktype' does a direct hardware probe which forces /proc update.
#attempt here to run disktype when appropriate.
#v3.93 10 dec 2007 BK: updated for 2.6.24 kernel, no /dev/hd*.
#v3.97 31jan2008 BK: refinement for detecting kernel with /dev/hd support.
#v3.97 25feb2008 BK: guess_fstype does not work when testing 'makebootfat', use fdisk.
#v4.01 19may2008 BK: bugfix for 2.6.25.4, ram entries in /proc/partitions.
#v403 fix for SIZE of drives without partitions.
#v406 support for old kernel, /proc/ide, /dev/hd*
#v407 improved filesystem probe for optical discs.
#110126 remove code for SATADRIVES (not used in PUPSTATE anymore).
#120601 jemimah: fallback to use 'blkid' to find f.s. type. 120601 revert use of blkid, too slow.
#120602 kernel 3.2.18 major deviance from earlier kernels, /proc/partitions (and /sys/block) now shows /dev/sr0 when no disk.
#       new situation, getting duplicate /dev/sr0 so need 'sort -u'.
#120516 raspi, guess_fstype fails for ext4 and swap f.s., did detect fat. fallback blkid.
#120516 sort in old coreutils (as in wary/racy) does not have -V option
#130127 early kernels do not have sr0/sr1 in /proc/partitions, 3.2+ do, which can upset things. (tested 2.6.32.29 and 3.2.29+, so not sure exact version this difference came in)
#130128 improve detection of optical: distinguish iso9600, udf. no o/p if no media inserted.
#       previously, any optical media returned "iso9660", now have "udf" (also for video dvds), "audiocd" (audio cds), "none" (unknown f.s.).
#130526 Karl Godt: fix blkid parsing.
#140220 check device node exists. for childproofing, removing node, see /usr/sbin/.childproofing
#150320 able to run inside a self-extracting archive. refer: /usr/local/install_quirky
#150324 guess_fstype failed, create gpt efi bootable flash stick, 1st partition fat32 512mb. note, need full fdisk (busybox applet has different format)
#151204 screen out zram[0-9], as in quirky frugal/live-cd. Screen out extended partition. now have guess_fstype in busybox.
#170310 support exfat. note, guessfs_type and blkid are busybox applets, do support exfat. --so, nothing to do in this script.
#180408 support nvme drives.

#150320 detect if running inside a self-extracted archive:
PWD="`pwd`"
PRE=''
if [ -f ${PWD}/DISTRO_SPECS ];then
 if [ -f ${PWD}/gtkdialog ];then
  PRE="${PWD}/"
 fi
fi

[ -f /etc/rc.d/PUPSTATE ] && . /etc/rc.d/PUPSTATE #ATADRIVES is exported by 'installquirky' (which calls probepart).

SUNITS="$1" #allowed params are '-k' or '-m'.
OUTPUT=""

if [ -f /root/.usb-drive-log-probepart ];then #force /proc upate mechanism
 for ONEUSBDRV in `${PRE}busybox cat /root/.usb-drive-log-probepart | ${PRE}busybox tr '\n' ' '`
 do
  #disktype /dev/$ONEUSBDRV > /dev/null 2>&1
  ${PRE}busybox dd if=/dev/$ONEUSBDRV of=/dev/null bs=512 count=1 >/dev/null 2>&1 #v3.97 faster.
 done
fi

#devices that have partitions... 
#([^k] is to eliminate mmcblk0 device -- allow mmcblk0p1 etc) v4.01 bugfix eliminate ram...
#130127 [^kr] screens out sr0-sr9. early kernels do not have these in /proc/partitions, 3.2+ do, which causes desktop icon to not appear when audio-cd inserted.
#151204 screen out zram[0-9], "[^krm][0-9]$" (will also filter out sdm)...
#180408 drive name: nvme[0-9]n[1-9] partition: p[1-9]*, '^ .*[^krmn][0-9]$' only let partitons thru (will also filter out sdn)
PARTITIONS="`${PRE}busybox grep '^ .*[^krmn][0-9]$' /proc/partitions | ${PRE}busybox tr -s ' ' | ${PRE}busybox cut -f 4-5 -d ' ' | ${PRE}busybox grep -vE ' loop| ram'`" #each line ex: 16076800 sda5
PARTNAMES="`${PRE}busybox echo "$PARTITIONS" | ${PRE}busybox cut -f 2 -d ' '`" #120602

#all disk devices... 
#note, /proc/diskstats only updated when a disk accessed, so devs may be missing...
#NO, NO, NO, /sys is very flakey for hd devices...
ALLDRVS="`${PRE}busybox ls -1 /sys/block | ${PRE}busybox grep -E '^scd|^sd|^mmc|^sr|^nvme'`" #180408
[ -e /proc/ide ] && ALLDRVS="${ALLDRVS}
`${PRE}busybox ls -1 /proc/ide | ${PRE}busybox grep '^hd'`"

##all drives and partitions... 120602 sort...
##120516 sort in old coreutils (as in wary/racy) does not have -V option...
#COREUTILSVER="$(${PRE}sort --version | ${PRE}busybox head -n 1 | ${PRE}busybox rev | ${PRE}busybox cut -f 1 -d ' ' | ${PRE}busybox rev)"
#if vercmp $COREUTILSVER le 6.12;then
# ALLDEVS="`${PRE}busybox echo "${PARTNAMES}
#${ALLDRVS}" | ${PRE}busybox tr '\n' ' '`"
#else
 ALLDEVS="`${PRE}busybox echo "${PARTNAMES}
${ALLDRVS}" | ${PRE}sort -V -u | ${PRE}busybox tr '\n' ' '`"
#fi

for ONEDEV in $ALLDEVS
do
 MEDIATYPE="" #130128
 FSTYPE="unknown"
 DPATTERN=' '${ONEDEV}'$'
 SIZE=`${PRE}busybox echo "$PARTITIONS" | ${PRE}busybox grep "$DPATTERN" | ${PRE}busybox cut -f 1 -d ' '`
 DEVICE="`${PRE}busybox echo "$PARTITIONS" | ${PRE}busybox grep "$DPATTERN" | ${PRE}busybox cut -f 2 -d ' '`"
 if [ ! $SIZE ];then
  [ "`${PRE}busybox echo "$PARTITIONS" | ${PRE}busybox grep "$ONEDEV"`" != "" ] && continue
  #must be a device without partitions...
  SIZE=0
  DEVICE="$ONEDEV"
  case $DEVICE in
   hd*)
    [ "`cat /proc/ide/$DEVICE/media`" = "cdrom" ] && MEDIATYPE="optical" #130128
   ;;
   scd*|sr*) #usb,sata,scsi cd/dvd drive.
    MEDIATYPE="optical" #130128
   ;;
  esac
  if [ -e /sys/block/${DEVICE}/size ];then
   SIZE=`${PRE}busybox cat /sys/block/${DEVICE}/size`
   SIZE=$(($SIZE/2)) #get KB.
  fi
  #for hd* or sd* superfloppy, determine size (avoid probing optical drive)...
  if [ "$MEDIATYPE" = "" -a $SIZE -eq 0 ];then #130128
   #BSIZE=`disktype /dev/$DEVICE 2>/dev/null | grep '^Block device' | cut -f 2 -d '(' | cut -f 1 -d ' '`
   BSIZE=`${PRE}fdisk -l /dev/${DEVICE} 2>/dev/null | grep '^Disk /dev' | cut -f 5 -d ' '` #150324
   [ $BSIZE ] && SIZE=$(($BSIZE/1024)) #KB
  fi
  if [ "$MEDIATYPE" = "optical" ];then #130128
   opticalPATTERN='^/dev/'"$DEVICE"
   if [ "`${PRE}busybox grep "$opticalPATTERN" /proc/mounts`" = "" ];then
    ${PRE}cddetect_quick -d/dev/${DEVICE} >/dev/null 2>&1 #very fast.
    #...returns 0 if disc inserted, else 255.
    [ $? -ne 0 ] && continue #130128 go no further, as no media inserted.
   fi
  fi
 fi
 FSTYPE="`${PRE}busybox guess_fstype /dev/$DEVICE 2>/dev/null`" #130128 note, audio-cd returns "unknown", as no f.s.

 if [ "$FSTYPE" = "unknown" -a "$MEDIATYPE" = "optical" ];then #130128 probe optical a bit more.
  ${PRE}cddetect -q -d/dev/${DEVICE} > /dev/null 2>&1
  case $? in
   1) FSTYPE="audiocd" ;;
  esac
 fi
 
 #v3.97 guess_fstype fails sometimes...
 #(using makebootfat to setup a USB-FLOPPY/-HDD/-ZIP combined bootable FAT drive).
 xFSTYPE=''
 if [ "$FSTYPE" = "unknown" -a "$MEDIATYPE" = "" ];then #130128 not optical.
  fsPATTERN='^/dev/'"$DEVICE"' '
  xDEVICE="`${PRE}busybox echo -n "$DEVICE" | ${PRE}busybox sed -e 's/[0-9]*$//' -e 's%p$%%'`" #"${DEVICE/[0-9]/}" #remove partition number. 120516 remove 'p' from mmcblk0p1  180408 and from nvme0n1p1
  xFSTYPE="`${PRE}fdisk -l /dev/$xDEVICE 2>/dev/null | ${PRE}busybox grep "$fsPATTERN" | ${PRE}busybox head -n 1 | ${PRE}busybox grep -o -E 'FAT|swap|Linux|NTFS|EFI|Extended'`" #120516 FAT12$|FAT16$|FAT32$  150324 added EFI, need full fdisk. 151204 added "Extended"
  case $xFSTYPE in #120516
   FAT|EFI) FSTYPE='vfat' ;; #150324 added EFI
   swap) FSTYPE='swap' ;;
   NTFS) FSTYPE='ntfs' ;;
   Extended) continue ;; #151204 ignore extended partition.
   #151204 remove, as guess_fstype now in busybox, just as good as blkid...
#   Linux)
#    #FSTYPE="$(blkid -c /dev/$DEVICE | grep "$DEVICE"| awk '{print $NF}' |cut -f2 -d\")"
#    #130526 Karl Godt: example o/p from blkid that breaks above:
#    # /dev/sdb1: UUID="5a126d47-065d-4eb6-baf9-dd7701bfe71a" TYPE="ext4" LABEL="boot"
#    # ref: http://www.murga-linux.com/puppy/viewtopic.php?t=85965
#    FSTYPE=$(${PRE}busybox blkid -c /dev/null /dev/${DEVICE} | ${PRE}busybox grep -w "${DEVICE}" | ${PRE}busybox grep -o ' TYPE=".*"' | ${PRE}busybox cut -f2 -d'"')
#    [ "$FSTYPE" = "" ] && FSTYPE="unknown"
#   ;;
  esac
 fi
 
 [ "$FSTYPE" = "unknown" ] && FSTYPE="none"

 [ "$SUNITS" = "" ] && SIZE=$(($SIZE*2)) #want 512 byte blocks.
 [ "$SUNITS" = '-m' ] && SIZE=$(($SIZE/1024)) #want MB

 [ -e /dev/$DEVICE ] && ${PRE}busybox echo "/dev/$DEVICE|$FSTYPE|$SIZE" #140220 precaution. for childproofing, removing node, see /usr/sbin/.childproofing
 
 #keep record of usb sd*, for forced updating of /proc...
 case $DEVICE in
  sd*)
   #log if usb drive (not a ata drive)...
   DEVDRV="`${PRE}busybox echo -n "$DEVICE" | ${PRE}busybox tr -d '[0-9]'`"
   if [ "`${PRE}busybox echo "$ATADRIVES" | ${PRE}busybox grep "$DEVDRV"`" = "" ];then #110126
    ${PRE}busybox echo "$DEVDRV" >> /root/.usb-drive-log-probepart
    ${PRE}sort -u /root/.usb-drive-log-probepart > /tmp/usb-drive-log-probepart-tmp
    ${PRE}busybox mv -f /tmp/usb-drive-log-probepart-tmp /root/.usb-drive-log-probepart
   fi
   ;;
 esac
 
done

###END###
