Author: dteske
Date: Sat May 17 03:49:29 2014
New Revision: 266292
URL: http://svnweb.freebsd.org/changeset/base/266292

Log:
  MFC r264840: Implement GEOM based media device classification.

Added:
  stable/9/usr.sbin/bsdconfig/share/geom.subr
     - copied unchanged from r264840, head/usr.sbin/bsdconfig/share/geom.subr
Modified:
  stable/9/usr.sbin/bsdconfig/dot/dot
  stable/9/usr.sbin/bsdconfig/examples/browse_packages_ftp.sh
  stable/9/usr.sbin/bsdconfig/examples/browse_packages_http.sh
  stable/9/usr.sbin/bsdconfig/networking/share/device.subr
  stable/9/usr.sbin/bsdconfig/share/Makefile
  stable/9/usr.sbin/bsdconfig/share/common.subr
  stable/9/usr.sbin/bsdconfig/share/device.subr
  stable/9/usr.sbin/bsdconfig/share/media/cdrom.subr
  stable/9/usr.sbin/bsdconfig/share/media/common.subr
  stable/9/usr.sbin/bsdconfig/share/media/directory.subr
  stable/9/usr.sbin/bsdconfig/share/media/dos.subr
  stable/9/usr.sbin/bsdconfig/share/media/floppy.subr
  stable/9/usr.sbin/bsdconfig/share/media/ftp.subr
  stable/9/usr.sbin/bsdconfig/share/media/http.subr
  stable/9/usr.sbin/bsdconfig/share/media/nfs.subr
  stable/9/usr.sbin/bsdconfig/share/media/tcpip.subr
  stable/9/usr.sbin/bsdconfig/share/media/ufs.subr
  stable/9/usr.sbin/bsdconfig/share/media/usb.subr
  stable/9/usr.sbin/bsdconfig/share/packages/index.subr
  stable/9/usr.sbin/bsdconfig/share/packages/packages.subr
  stable/9/usr.sbin/bsdconfig/share/struct.subr
Directory Properties:
  stable/9/   (props changed)
  stable/9/usr.sbin/   (props changed)
  stable/9/usr.sbin/bsdconfig/   (props changed)

Modified: stable/9/usr.sbin/bsdconfig/dot/dot
==============================================================================
--- stable/9/usr.sbin/bsdconfig/dot/dot Sat May 17 03:39:56 2014        
(r266291)
+++ stable/9/usr.sbin/bsdconfig/dot/dot Sat May 17 03:49:29 2014        
(r266292)
@@ -29,7 +29,7 @@
 ############################################################ INCLUDES
 
 # Prevent common.subr from auto initializing debugging (this is not an inter-
-# active utility that requires debugging; also `-d' has been repurposed).
+# active utility so does not require debugging; also `-d' has been repurposed).
 #
 DEBUG_SELF_INITIALIZE=NO
 

Modified: stable/9/usr.sbin/bsdconfig/examples/browse_packages_ftp.sh
==============================================================================
--- stable/9/usr.sbin/bsdconfig/examples/browse_packages_ftp.sh Sat May 17 
03:39:56 2014        (r266291)
+++ stable/9/usr.sbin/bsdconfig/examples/browse_packages_ftp.sh Sat May 17 
03:49:29 2014        (r266292)
@@ -18,7 +18,7 @@ if [ ! -e "$TMPDIR/packages/INDEX" ]; th
        mediaSetFTP
        mediaOpen
        f_show_info "Downloading packages/INDEX from\n %s" "$_ftpPath" 
-       f_device_get media packages/INDEX > $TMPDIR/packages/INDEX
+       f_device_get device_media packages/INDEX > $TMPDIR/packages/INDEX
 fi
 _directoryPath=$TMPDIR
 mediaSetDirectory

Modified: stable/9/usr.sbin/bsdconfig/examples/browse_packages_http.sh
==============================================================================
--- stable/9/usr.sbin/bsdconfig/examples/browse_packages_http.sh        Sat May 
17 03:39:56 2014        (r266291)
+++ stable/9/usr.sbin/bsdconfig/examples/browse_packages_http.sh        Sat May 
17 03:49:29 2014        (r266292)
@@ -18,7 +18,7 @@ if [ ! -e "$TMPDIR/packages/INDEX" ]; th
        mediaSetHTTP
        mediaOpen
        f_show_info "Downloading packages/INDEX from\n %s" "$_httpPath"
-       f_device_get media packages/INDEX > $TMPDIR/packages/INDEX
+       f_device_get device_media packages/INDEX > $TMPDIR/packages/INDEX
 fi
 _directoryPath=$TMPDIR
 mediaSetDirectory

Modified: stable/9/usr.sbin/bsdconfig/networking/share/device.subr
==============================================================================
--- stable/9/usr.sbin/bsdconfig/networking/share/device.subr    Sat May 17 
03:39:56 2014        (r266291)
+++ stable/9/usr.sbin/bsdconfig/networking/share/device.subr    Sat May 17 
03:49:29 2014        (r266292)
@@ -75,10 +75,11 @@ f_dialog_menu_netdev()
        #
        # Get list of usable network interfaces
        #
-       local devs if iflist= # Calculated below
+       local dev devs if iflist= # Calculated below
        f_device_rescan_network
        f_device_find "" $DEVICE_TYPE_NETWORK devs
-       for if in $devs; do
+       for dev in $devs; do
+               f_struct "$dev" get name if || continue
                # Skip unsavory interfaces
                case "$if" in
                lo[0-9]*|ppp[0-9]*|sl[0-9]*|faith[0-9]*) continue ;;

Modified: stable/9/usr.sbin/bsdconfig/share/Makefile
==============================================================================
--- stable/9/usr.sbin/bsdconfig/share/Makefile  Sat May 17 03:39:56 2014        
(r266291)
+++ stable/9/usr.sbin/bsdconfig/share/Makefile  Sat May 17 03:49:29 2014        
(r266292)
@@ -5,7 +5,7 @@ NO_OBJ=
 SUBDIR=        media packages
 
 FILESDIR=      ${SHAREDIR}/bsdconfig
-FILES=         common.subr device.subr dialog.subr keymap.subr \
+FILES=         common.subr device.subr dialog.subr geom.subr keymap.subr \
                mustberoot.subr script.subr strings.subr struct.subr \
                sysrc.subr variable.subr
 

Modified: stable/9/usr.sbin/bsdconfig/share/common.subr
==============================================================================
--- stable/9/usr.sbin/bsdconfig/share/common.subr       Sat May 17 03:39:56 
2014        (r266291)
+++ stable/9/usr.sbin/bsdconfig/share/common.subr       Sat May 17 03:49:29 
2014        (r266292)
@@ -146,7 +146,7 @@ f_debug_init()
        # Process stored command-line arguments
        #
        set -- $ARGV
-       local OPTIND flag
+       local OPTIND OPTARG flag
        f_dprintf "f_debug_init: ARGV=[%s] GETOPTS_STDARGS=[%s]" \
                  "$ARGV" "$GETOPTS_STDARGS"
        while getopts "$GETOPTS_STDARGS$GETOPTS_EXTRA$GETOPTS_ALLFLAGS" flag \
@@ -762,14 +762,30 @@ f_running_as_init()
 }
 
 # f_mounted $local_directory
+# f_mounted -b $device
 #
-# Return success if a filesystem is mounted on a particular directory.
+# Return success if a filesystem is mounted on a particular directory. If `-b'
+# is present, instead check that the block device (or a partition thereof) is
+# mounted.
 #
 f_mounted()
 {
-       local dir="$1"
-       [ -d "$dir" ] || return $FAILURE
-       mount | grep -Eq " on $dir \([^)]+\)$"
+       local OPTIND OPTARG flag use_device=
+       while getopts b flag; do
+               case "$flag" in
+               b) use_device=1 ;;
+               esac
+       done
+       shift $(( $OPTIND - 1 ))
+       if [ "$use_device" ]; then
+               local device="$1"
+               mount | grep -Eq \
+                       "^$device([[:space:]]|p[0-9]|s[0-9]|\.nop|\.eli)"
+       else
+               [ -d "$dir" ] || return $FAILURE
+               mount | grep -Eq " on $dir \([^)]+\)$"
+       fi
+       # Return status is that of last grep(1)
 }
 
 # f_eval_catch [-de] [-k $var_to_set] $funcname $utility \
@@ -854,7 +870,7 @@ f_eval_catch()
        #
        # Process local function arguments
        #
-       local OPTIND __flag
+       local OPTIND OPTARG __flag
        while getopts "dek:" __flag > /dev/null; do
                case "$__flag" in
                d) __no_dialog=1 ;;

Modified: stable/9/usr.sbin/bsdconfig/share/device.subr
==============================================================================
--- stable/9/usr.sbin/bsdconfig/share/device.subr       Sat May 17 03:39:56 
2014        (r266291)
+++ stable/9/usr.sbin/bsdconfig/share/device.subr       Sat May 17 03:49:29 
2014        (r266292)
@@ -32,6 +32,7 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
 . $BSDCFG_SHARE/common.subr || exit 1
 f_dprintf "%s: loading includes..." device.subr
 f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/geom.subr
 f_include $BSDCFG_SHARE/strings.subr
 f_include $BSDCFG_SHARE/struct.subr
 
@@ -40,42 +41,53 @@ f_include_lang $BSDCFG_LIBE/include/mess
 
 ############################################################ GLOBALS
 
-DEVICES=
-DEVICE_NAMES=
-NDEVICES=0
+NDEVICES=0 # Set by f_device_register(), used by f_device_*()
 
-# A "device" from sysinstall's point of view
+#
+# A "device" from legacy sysinstall's point of view (mostly)
+#
+# NB: Disk devices have their `private' property set to GEOM ident
+# NB: USB devices have their `private' property set to USB disk device name
+#
 f_struct_define DEVICE \
-       name            \
+       capacity        \
        desc            \
        devname         \
-       type            \
-       capacity        \
        enabled         \
-       init            \
-       get             \
-       shutdown        \
        flags           \
+       get             \
+       init            \
+       name            \
        private         \
+       shutdown        \
+       type            \
        volume  
 
 # Network devices have their `private' property set to this
 f_struct_define DEVICE_INFO \
-       use_rtsol use_dhcp ipaddr ipv6addr netmask extras
-
-setvar DEVICE_TYPE_NONE                1
-setvar DEVICE_TYPE_DISK                2
-setvar DEVICE_TYPE_FLOPPY      3
-setvar DEVICE_TYPE_FTP         4
-setvar DEVICE_TYPE_NETWORK     5
-setvar DEVICE_TYPE_CDROM       6
-setvar DEVICE_TYPE_USB         7
-setvar DEVICE_TYPE_DOS         8
-setvar DEVICE_TYPE_UFS         9
-setvar DEVICE_TYPE_NFS         10
-setvar DEVICE_TYPE_ANY         11
-setvar DEVICE_TYPE_HTTP_PROXY  12
-setvar DEVICE_TYPE_HTTP                13
+       extras          \
+       ipaddr          \
+       ipv6addr        \
+       netmask         \
+       use_dhcp        \
+       use_rtsol
+
+#
+# Device types for f_device_register(), f_device_find(), et al.
+#
+setvar DEVICE_TYPE_ANY         "any"           # Any
+setvar DEVICE_TYPE_NONE                "NONE"          # Unknown
+setvar DEVICE_TYPE_DISK                "DISK"          # GEOM `DISK'
+setvar DEVICE_TYPE_FLOPPY      "FD"            # GEOM `FD'
+setvar DEVICE_TYPE_FTP         "FTP"           # Dynamic network device
+setvar DEVICE_TYPE_NETWORK     "NETWORK"       # See f_device_get_all_network
+setvar DEVICE_TYPE_CDROM       "CDROM"         # GEOM `DISK'
+setvar DEVICE_TYPE_USB         "USB"           # GEOM `PART'
+setvar DEVICE_TYPE_DOS         "DOS"           # GEOM `DISK' `PART' or `LABEL'
+setvar DEVICE_TYPE_UFS         "UFS"           # GEOM `DISK' `PART' or `LABEL'
+setvar DEVICE_TYPE_NFS         "NFS"           # Dynamic network device
+setvar DEVICE_TYPE_HTTP_PROXY  "HTTP_PROXY"    # Dynamic network device
+setvar DEVICE_TYPE_HTTP                "HTTP"          # Dynamic network device
 
 # Network devices have the following flags available
 setvar IF_ETHERNET     1
@@ -87,76 +99,70 @@ setvar IF_ACTIVE    4
 #
 : ${DEVICE_SELF_SCAN_ALL=1}
 
-############################################################ FUNCTIONS
-
-# f_device_try $name [$i [$var_path]]
-#
-# Test a particular device. If $i is given, then $name is expected to contain a
-# single "%d" where $i will be inserted using printf. If $var_path is given,
-# it is used as a variable name to provide the caller the device pathname.
 #
-# Returns success if the device path exists and is a cdev.
+# Device Catalog variables
 #
-f_device_try()
-{
-       local name="$1" i="$2" var_path="$3" unit
-       if [ "$i" ]; then
-               f_sprintf unit "$name" "$i"
-       else
-               unit="$name"
-       fi
-       case "$unit" in
-       /dev/*) : good ;; # already qualified
-       *) unit="/dev/$unit" ;;
-       esac
-       [ "$var_path" ] && setvar "$var_path" "$unit"
-       f_dprintf "f_device_try: making sure %s is a device node" "$unit"
-       if [ -c "$unit" ]; then
-               f_dprintf "f_device_try: %s is a cdev [good]" "$unit"
-               return $SUCCESS
-       else
-               f_dprintf "f_device_try: %s is not a cdev [skip]" "$unit"
-               return $FAILURE
-       fi
-}
+DEVICE_CATALOG_APPEND_ONLY= # Used by f_device_catalog_set()
+NCATALOG_DEVICES=0          # Used by f_device_catalog_*() and MAIN
 
-# f_device_register $name $desc $devname $type $enabled $init_function \
-#                   $get_function $shutdown_function $private $capacity
 #
-# Register a device. A `structure' (see struct.subr) is created with the name
-# device_$name (so make sure $name contains only alpha-numeric characters or
-# the underscore, `_'). The remaining arguments after $name correspond to the
-# properties of the `DEVICE' structure-type (defined above).
+# A ``catalog'' device is for mapping GEOM devices to media devices (for
+# example, determining if a $GEOM_CLASS_DISK geom is $DEVICE_TYPE_CDROM or
+# $DEVICE_TYPE_DISK) and also getting default descriptions for devices that
+# either lack a GEOM provided description or lack a presence in GEOM)
 #
-# If not already registered, the device is then appended to the DEVICES
-# environment variable, a space-separated list of all registered devices.
+f_struct_define CATALOG_DEVICE \
+       desc    \
+       name    \
+       type
+
+############################################################ FUNCTIONS
+
+# f_device_register $var_to_set $name $desc $devname $type $enabled
+#                   $init_function $get_function $shutdown_function
+#                   $private $capacity
+#
+# Register a device. A `structure' (see struct.subr) is created and if
+# $var_to_set is non-NULL, upon success holds the name of the struct created.
+# The remaining positional arguments correspond to the properties of the
+# `DEVICE' structure-type to be assigned (defined above).
+#
+# If not already registered (based on $name and $type), a new device is created
+# and $NDEVICES is incremented.
 #
 f_device_register()
 {
-       local name="$1" desc="$2" devname="$3" type="$4" enabled="$5"
-       local init_func="$6" get_func="$7" shutdown_func="$8" private="$9"
-       local capacity="${10}"
-
-       f_struct_new DEVICE "device_$name" || return $FAILURE
-       device_$name set name     "$name"
-       device_$name set desc     "$desc"
-       device_$name set devname  "$devname"
-       device_$name set type     "$type"
-       device_$name set enabled  "$enabled"
-       device_$name set init     "$init_func"
-       device_$name set get      "$get_func"
-       device_$name set shutdown "$shutdown_func"
-       device_$name set private  "$private"
-       device_$name set capacity "$capacity"
-
-       # Scan our global register to see if it needs ammending
-       local dev found=
-       for dev in $DEVICES; do
-               [ "$dev" = "$name" ] || continue
-               found=1 && break
-       done
-       [ "$found" ] || DEVICES="$DEVICES $name"
+       local __var_to_set="$1" __name="$2" __desc="$3" __devname="$4"
+       local __type="$5" __enabled="$6" __init_func="$7" __get_func="$8"
+       local __shutdown_func="$9" __private="${10}" __capacity="${11}"
 
+       # Required parameter(s)
+       [ "$__name" ] || return $FAILURE
+       if [ "$__var_to_set" ]; then
+               setvar "$__var_to_set" "" || return $FAILURE
+       fi
+
+       local __device
+       if f_device_find -1 "$__name" "$__type" __device; then
+               f_struct_free "$__device"
+               f_struct_new DEVICE "$__device" || return $FAILURE
+       else
+               __device=device_$(( NDEVICES + 1 ))
+               f_struct_new DEVICE "$__device" || return $FAILURE
+               NDEVICES=$(( $NDEVICES + 1 ))
+       fi
+       $__device set name     "$__name"
+       $__device set desc     "$__desc"
+       $__device set devname  "$__devname"
+       $__device set type     "$__type"
+       $__device set enabled  "$__enabled"
+       $__device set init     "$__init_func"
+       $__device set get      "$__get_func"
+       $__device set shutdown "$__shutdown_func"
+       $__device set private  "$__private"
+       $__device set capacity "$__capacity"
+
+       [ "$__var_to_set" ] && setvar "$__var_to_set" "$__device"
        return $SUCCESS
 }
 
@@ -166,18 +172,21 @@ f_device_register()
 #
 f_device_reset()
 {
-       local dev
-       for dev in $DEVICES; do
-               f_device_shutdown $dev
+       local n=1
+       while [ $n -le $NDEVICES ]; do
+               f_device_shutdown device_$n
 
+               #
                # XXX This potentially leaks $dev->private if it's being
                # used to point to something dynamic, but you're not supposed
                # to call this routine at such times that some open instance
                # has its private member pointing somewhere anyway.
                #
-               f_struct_free device_$dev
+               f_struct_free device_$n
+
+               n=$(( $n + 1 ))
        done
-       DEVICES=
+       NDEVICES=0
 }
 
 # f_device_reset_network
@@ -186,34 +195,45 @@ f_device_reset()
 #
 f_device_reset_network()
 {
-       local dev type private pruned_list=
-       for dev in $DEVICES; do
-               device_$dev get type type
-               if [ "$type" != "$DEVICE_TYPE_NETWORK" ]; then
-                       pruned_list="$pruned_list $dev"
-                       continue
-               fi
+       local n=1 device type private i
+       while [ $n -le $NDEVICES ]; do
+               device=device_$n
+               f_struct $device || continue
+               $device get type type
+               [ "$type" = "$DEVICE_TYPE_NETWORK" ] || continue
 
                #
                # Leave the device up (don't call shutdown routine)
                #
 
                # Network devices may have DEVICE_INFO private member
-               device_$dev get private private
+               $device get private private
                [ "$private" ] && f_struct_free "$private"
 
-               f_struct_free device_$dev
+               # Free the network device
+               f_struct_free $device
+
+               # Fill the gap we just created
+               i=$n
+               while [ $i -lt $NDEVICES ]; do
+                       f_struct_copy device_$(( $i + 1 )) device_$i
+               done
+               f_struct_free device_$NDEVICES
+
+               # Finally decrement the number of devices
+               NDEVICES=$(( $NDEVICES - 1 ))
+
+               n=$(( $n + 1 ))
        done
-       DEVICES="${pruned_list# }"
 }
 
 # f_device_get_all
 #
-# Get all device information for devices we have attached.
+# Get all device information for all devices.
 #
 f_device_get_all()
 {
-       local devname desc capacity
+       local devname type desc capacity
 
        f_dprintf "f_device_get_all: Probing devices..."
        f_dialog_info "$msg_probing_devices_please_wait_this_can_take_a_while"
@@ -221,180 +241,16 @@ f_device_get_all()
        # First go for the network interfaces
        f_device_get_all_network
 
-       # Next, try to find all the types of devices one might use
-       # as a media source for content
-       #
-
-       local dev type max n=0
-       for dev in $DEVICE_NAMES; do
-               n=$(( $n + 1 ))
-               # Get the desc, type, and max (with debugging disabled)
-               # NOTE: Bypassing f_device_name_get() for efficiency
-               # ASIDE: This would be equivalent to the following:
-               #       debug= f_device_name_get $dev desc
-               #       debug= f_device_name_get $dev type
-               #       debug= f_device_name_get $dev max
-               debug= f_getvar _device_desc$n desc
-               debug= f_getvar _device_type$n type
-               debug= f_getvar _device_max$n max
-
-               local k=0
-               while [ $k -lt ${max:-0} ]; do
-                       i=$k k=$(( $k + 1 ))
-                       devname=""
-                       case "$type" in
-                       $DEVICE_TYPE_CDROM)
-                               f_device_try "$dev" "$i" devname || continue
-                               f_device_capacity "$devname" capacity
-                               f_device_register "${devname##*/}" "$desc" \
-                                       "$devname" $DEVICE_TYPE_CDROM 1 \
-                                       f_media_init_cdrom f_media_get_cdrom \
-                                       f_media_shutdown_cdrom "" "$capacity"
-                               f_dprintf "Found a CDROM device for %s" \
-                                         "$devname"
-                               ;;
-                       $DEVICE_TYPE_FLOPPY)
-                               f_device_try "$dev" "$i" devname || continue
-                               f_device_capacity "$devname" capacity
-                               f_device_register "${devname##*/}" "$desc" \
-                                       "$devname" $DEVICE_TYPE_FLOPPY 1 \
-                                       f_media_init_floppy \
-                                       f_media_get_floppy \
-                                       f_media_shutdown_floppy "" "$capacity"
-                               f_dprintf "Found a floppy device for %s" \
-                                         "$devname"
-                               ;;
-                       $DEVICE_TYPE_USB)
-                               f_device_try "$dev" "$i" devname || continue
-                               f_device_capacity "$devname" capacity
-                               f_device_register "${devname##*/}" "$desc" \
-                                       "$devname" $DEVICE_TYPE_USB 1 \
-                                       f_media_init_usb f_media_get_usb \
-                                       f_media_shutdown_usb "" "$capacity"
-                               f_dprintf "Found a USB disk for %s" "$devname"
-                               ;;
-                       esac
-               done
-       done
-
-       # Register ISO9660 providers as CDROM devices
-       for devname in /dev/iso9660/*; do
-               f_device_try "$devname" || continue
-               f_device_capacity "$devname" capacity
-               f_device_register "${devname##*/}" "ISO9660 file system" \
-                       "$devname" $DEVICE_TYPE_CDROM 1 \
-                       f_media_init_cdrom f_media_get_cdrom \
-                       f_media_shutdown_cdrom "" "$capacity"
-               f_dprintf "Found a CDROM device for %s" "$devname"
-       done
-
-       # Scan for mdconfig(8)-created md(4) devices
-       local filename
-       for devname in /dev/md[0-9] /dev/md[0-9][0-9]; do
-               f_device_try "$devname" || continue
-
-               # See if the md(4) device is a vnode type backed by a file
-               filename=$( sysctl kern.geom.conftxt |
-                       awk -v devname="${devname##*/}" \
-                       '
-                               ( $2 == "MD" ) && \
-                               ( $3 == devname ) && \
-                               ( $(NF-2) == "vnode" ) && \
-                               ( $(NF-1) == "file" ) \
-                               {
-                                       print $NF
-                               }
-                       ' )
-               case "$filename" in
-               *.iso) # Register the device as an ISO9660 provider
-                       f_device_capacity "$devname" capacity
-                       f_device_register "${devname##*/}" \
-                               "md(4) vnode file system" \
-                               "$devname" $DEVICE_TYPE_CDROM 1 \
-                               f_media_init_cdrom f_media_get_cdrom \
-                               f_media_shutdown_cdrom "" "$capacity"
-                       f_dprintf "Found a CDROM device for %s" "$devname"
-                       ;;
-               esac
-       done
-
-       # Finally go get the disks and look for partitions to register
-       local diskname slices index type rest slice part
-       for diskname in $( sysctl -n kern.disks ); do
-
-               case "$diskname" in
-               cd*)
-                       # XXX Due to unknown reasons, kern.disks returns SCSI
-                       # CDROM as a valid disk. This will prevent bsdconfig
-                       # from presenting SCSI CDROMs as available disks in
-                       # various menus. Why GEOM treats SCSI CDROM as a disk
-                       # is beyond me and that should be investigated.
-                       # For temporary workaround, ignore SCSI CDROM device.
-                       #
-                       continue ;;
-               esac
-
-               # Try to create a list of partitions and their types,
-               # consisting of "N,typeN ..." (e.g., "1,0xa5 2,0x06").
-               if ! slices=$( fdisk -p "$diskname" 2> /dev/null |
-                       awk '( $1 == "p" ) { print $2","$3 }' )
-               then
-                       f_dprintf "Unable to open disk %s" "$diskname"
-                       continue
+       # Next, go for the GEOM devices we might want to use as media
+       local geom geoms geom_name
+       debug= f_geom_find "" $GEOM_CLASS_DEV geoms
+       for geom in $geoms; do
+               if ! f_device_probe_geom $geom; then
+                       debug= $geom get name geom_name
+                       f_dprintf "WARNING! Unable to classify %s as %s" \
+                                 "GEOM device $geom_name" "media source"
                fi
-
-               # Try and find its description
-               f_device_desc "$diskname" $DEVICE_TYPE_DISK desc
-
-               f_device_capacity "$diskname" capacity
-               f_device_register "$diskname" "$desc" \
-                                 "/dev/$diskname" $DEVICE_TYPE_DISK 0 \
-                                 "" "" "" "" "$capacity"
-               f_dprintf "Found a disk device named %s" "$diskname"
-
-               # Look for existing partitions to register
-               for slice in $slices; do
-                       index="${slice%%,*}" type="${slice#*,}"
-                       slice=${diskname}s$index
-                       case "$type" in
-                       0x01|0x04|0x06|0x0b|0x0c|0x0e|0xef)
-                               # DOS partitions to add as "DOS media devices"
-                               f_device_capacity "/dev/$slice" capacity
-                               f_device_register "$slice" "" \
-                                       "/dev/$slice" $DEVICE_TYPE_DOS 1 \
-                                       f_media_init_dos f_media_get_dos \
-                                       f_media_shutdown_dos "" "$capacity"
-                               f_dprintf "Found a DOS partition %s" "$slice"
-                               ;;
-                       0xa5) # FreeBSD partition
-                               for part in $(
-                                       bsdlabel -r $slice 2> /dev/null |
-                                               awk -v slice="$slice" '
-                                               ( $1 ~ /[abdefgh]:/ ) {
-                                                       printf "%s%s\n",
-                                                              slice,
-                                                              substr($1,1,1)
-                                               }'
-                               ); do
-                                       f_quietly dumpfs -m /dev/$part ||
-                                               continue
-                                       f_device_capacity \
-                                               "$/dev/$part" capacity
-                                       f_device_register \
-                                               "$part" "" "/dev/$part" \
-                                               $DEVICE_TYPE_UFS 1 \
-                                               f_media_init_ufs \
-                                               f_media_get_ufs \
-                                               f_media_shutdown_ufs "" \
-                                               "$capacity"
-                                       f_dprintf "Found a UFS partition %s" \
-                                                 "$part"
-                               done # parts
-                               ;;
-                       esac
-               done # slices
-
-       done # disks
+       done
 }
 
 # f_device_get_all_network
@@ -403,7 +259,7 @@ f_device_get_all()
 #
 f_device_get_all_network()
 {
-       local devname desc flags
+       local devname desc device flags
        for devname in $( ifconfig -l ); do
                # Eliminate network devices that don't make sense
                case "$devname" in
@@ -413,9 +269,9 @@ f_device_get_all_network()
                # Try and find its description
                f_device_desc "$devname" $DEVICE_TYPE_NETWORK desc
 
-               f_dprintf "Found a network device named %s" "$devname"
-               f_device_register $devname \
-                       "$desc" "$devname" $DEVICE_TYPE_NETWORK 1 \
+               f_dprintf "Found network device named %s" "$devname"
+               debug= f_device_register device $devname "$desc" \
+                       "$devname" $DEVICE_TYPE_NETWORK 1 \
                        f_media_init_network "" f_media_shutdown_network "" -1
 
                # Set flags based on media and status
@@ -435,37 +291,532 @@ f_device_get_all_network()
                                if (value ~ /^active/) _or(var, "IF_ACTIVE")
                        }
                }' )"
-               device_$devname set flags $flags
+               $device set flags $flags
        done
 }
 
-# f_device_name_get $type $name type|desc|max [$var_to_set]
+# f_device_rescan
+#
+# Rescan all devices, after closing previous set - convenience function.
 #
-# Fetch the device type (type), description (desc), or maximum number of
-# devices to scan for (max) associated with device $name and $type. If $type is
-# either NULL, missing, or set to $DEVICE_TYPE_ANY then only $name is used.
+f_device_rescan()
+{
+       f_device_reset
+       f_geom_rescan
+       f_device_get_all
+}
+
+# f_device_rescan_network
+#
+# Rescan all network devices, after closing previous set - for convenience.
+#
+f_device_rescan_network()
+{
+       f_device_reset_network
+       f_device_get_all_network
+}
+
+# f_device_probe_geom $geom
+#
+# Probe a single GEOM device and if it can be classified as a media source,
+# register it using f_device_register() with known type-specific arguments.
+#
+f_device_probe_geom()
+{
+       local geom="$1"
+
+       f_struct "$geom" || return $FAILURE
+
+       # geom associated variables
+       local geom_name geom_consumer provider_ref geom_provider=
+       local provider_geom provider_config provider_class=
+       local provider_config_type catalog_struct catalog_type
+       local disk_ident
+
+       # gnop(8)/geli(8) associated variables (p for `parent device')
+       local p_devname p_geom p_consumer p_provider_ref p_provider 
+       local p_provider_config p_provider_geom p_provider_class
+
+       # md(4) associated variables
+       local config config_type config_file magic=
+
+       # Temporarily disable debugging to keep debug output light
+       local old_debug="$debug" debug=
+
+       #
+       # Get the GEOM name (for use below in device registration)
+       #
+       $geom get name devname || continue
+
+       #
+       # Attempt to get the consumer, provider, provider config, and
+       # provider class for this geom (errors ignored).
+       #
+       # NB: Each GEOM in the `DEV' class should have one consumer.
+       #     That consumer should have a reference to its provider.
+       #
+       $geom get consumer1 geom_consumer
+       f_struct "$geom_consumer" get provider_ref provider_ref &&
+               f_geom_find_by id "$provider_ref" provider geom_provider
+       if f_struct "$geom_provider"; then
+               $geom_provider get config provider_config
+               f_geom_parent $geom_provider provider_geom &&
+                       f_geom_parent $provider_geom provider_class
+       fi
+
+       #
+       # Get values for device registration (errors ignored)
+       #
+       f_struct "$provider_class"  get name      type
+       f_struct "$geom_provider"   get mediasize capacity
+       f_struct "$provider_config" get descr     desc
+
+       #
+       # For gnop(8), geli(8), or combination thereof, change device type to
+       # that of the consumer
+       #
+       p_devname= p_geom= p_provider= p_provider_config=
+       case "$devname" in
+       *.nop.eli) p_devname="${devname%.nop.eli}" ;;
+       *.eli.nop) p_devname="${devname%.eli.nop}" ;;
+       *.eli)     p_devname="${devname%.eli}" ;;
+       *.nop)     p_devname="${devname%.nop}" ;;
+       esac
+       [ "$p_devname" ] && f_geom_find "$p_devname" $GEOM_CLASS_DEV p_geom
+       if [ "${p_geom:-$geom}" != "$geom" ]; then
+               f_struct "$p_geom" get consumer1 p_consumer
+               f_struct "$p_consumer" get provider_ref p_provider_ref &&
+                       f_geom_find_by id "$p_provider_ref" provider p_provider
+               if f_struct "$p_provider"; then
+                       $p_provider get config p_provider_config
+                       f_geom_parent $p_provider p_provider_geom &&
+                               f_geom_parent $p_provider_geom p_provider_class
+               fi
+               f_struct "$p_provider_class" get name type
+       fi
+
+       # Look up geom device in device catalog for default description
+       f_device_catalog_get \
+               $DEVICE_TYPE_ANY "${p_devname:-$devname}" catalog_struct
+       [ "$desc" ] || f_struct "catalog_device_$catalog_struct" get desc desc
+
+       # Use device catalog entry for potential re-classification(s)
+       f_struct "catalog_device_$catalog_struct" get type catalog_type
+
+       # Restore debugging for this next part (device registration)
+       debug="$old_debug"
+
+       #
+       # Register the device
+       #
+       local retval device
+       case "$type" in
+       $GEOM_CLASS_DISK)
+               # First attempt to classify by device catalog (see MAIN)
+               case "$catalog_type" in
+               $DEVICE_TYPE_CDROM)
+                       f_dprintf "Found CDROM device for disk %s" "$devname"
+                       debug= f_device_register device "$devname" "$desc" \
+                               "/dev/$devname" $DEVICE_TYPE_CDROM 1 \
+                               f_media_init_cdrom f_media_get_cdrom \
+                               f_media_shutdown_cdrom "" "$capacity" &&
+                               return $SUCCESS
+                       ;;
+               esac
+
+               # Fall back to register label device as a disk and taste it
+               f_dprintf "Found disk device named %s" "$devname"
+               debug= f_struct "$p_provider_config" get \
+                       ident disk_ident ||
+                       debug= f_struct "$provider_config" get \
+                               ident disk_ident
+               debug= f_device_register device "$devname" "$desc" \
+                       "/dev/$devname" $DEVICE_TYPE_DISK 1 \
+                       "" "" "" "$disk_ident" "$capacity"
+               retval=$?
+
+               # Detect ``dangerously dedicated'' filesystems (errors ignored)
+               f_device_probe_disk_fs device "$devname" "$capacity" &&
+                       retval=$SUCCESS
+
+               return $retval
+               ;;
+       $GEOM_CLASS_FD)
+               f_dprintf "Found floppy device named %s" "$devname"
+               debug= f_device_register device "$devname" "$desc" \
+                       "/dev/$devname" $DEVICE_TYPE_FLOPPY 1 \
+                       f_media_init_floppy f_media_get_floppy \
+                       f_media_shutdown_floppy "" "$capacity"
+               return $?
+               ;;
+       $GEOM_CLASS_LABEL)
+               : fall through to below section # reduces indentation level
+               ;;
+       $GEOM_CLASS_MD)
+               f_dprintf "Found disk device named %s" "$devname"
+               debug= f_device_register device "$devname" "$desc" \
+                       "/dev/$devname" $DEVICE_TYPE_DISK 1 \
+                       "" "" "" "" "$capacity"
+               retval=$?
+
+               #
+               # Attempt to get file(1) magic to potentially classify as
+               # alternate media type. If unable to get magic, fall back to
+               # md(4) characteristics (such as vnode filename).
+               #
+               [ -r "/dev/$devname" ] &&
+                       magic=$( file -bs "/dev/$devname" 2> /dev/null )
+               if [ ! "$magic" ]; then
+                       # Fall back to md(4) characteristics
+                       if f_struct "$p_provider_config"; then
+                               config="$p_provider_config"
+                       else
+                               config="$provider_config"
+                       fi
+                       debug= f_struct "$config" get type config_type
+                       debug= f_struct "$config" get file config_file
+
+                       # Substitute magic for below based on type and file
+                       case "$config_type=$config_file" in
+                       vnode=*.iso) magic="ISO 9660" ;;
+                       esac
+               fi
+               f_device_probe_disk_fs device \
+                       "$devname" "$capacity" "$magic" &&
+                       retval=$SUCCESS # Errors ignored
+
+               return $retval
+               ;;
+       $GEOM_CLASS_PART)
+               if f_struct "$p_provider_config"; then
+                       config="$p_provider_config"
+               else
+                       config="$provider_config"
+               fi
+               debug= f_struct "$config" get type provider_config_type
+               f_device_probe_geom_part device \
+                       "$provider_config_type" "$devname" "$capacity"
+               retval=$?
+               device_type=$DEVICE_TYPE_NONE
+               [ $retval -eq $SUCCESS ] &&
+                       debug= f_struct "$device" get type device_type
+
+               # Potentially re-classify as USB device
+               if [ "$device_type" = "$DEVICE_TYPE_UFS" -a \
+                    "$catalog_type" = "$DEVICE_TYPE_USB" ]
+               then
+                       f_dprintf "Found USB device for partition %s" \
+                                 "$devname"
+                       debug= f_struct "$p_provider_geom" get \
+                               name disk_name ||
+                               debug= f_struct "$provider_geom" get \
+                                       name disk_name
+                       debug= f_device_register device "$devname" "$desc" \
+                               "/dev/$devname" $DEVICE_TYPE_USB 1 \
+                               f_media_init_usb f_media_get_usb \
+                               f_media_shutdown_usb "$disk_name" "$capacity"
+                       retval=$?
+               fi
+
+               return $retval
+               ;;
+       $GEOM_CLASS_RAID)
+               # Use the provider geom name as the description
+               if [ ! "$desc" ]; then
+                       f_struct "$p_provider_geom" get name desc ||
+                               f_struct "$provider_geom" get name desc
+               fi
+
+               f_dprintf "Found disk device named %s" "$devname"
+               debug= f_device_register device \
+                       "$devname" "${desc:-GEOM RAID device}" \
+                       "/dev/$devname" $DEVICE_TYPE_DISK 1 \
+                       "" "" "" "" "$capacity"
+               retval=$?
+               
+               # Detect ``dangerously dedicated'' filesystems
+               f_device_probe_disk_fs device "$devname" "$capacity" &&
+                       retval=$SUCCESS # Errors ignored
+
+               return $retval
+               ;;
+       $GEOM_CLASS_ZFS_ZVOL)
+               f_dprintf "Found disk device named %s" "$devname"
+               debug= f_device_register device \
+                       "$devname" "${desc:-GEOM ZFS::ZVOL device}" \
+                       "/dev/$devname" $DEVICE_TYPE_DISK 1 \
+                       "" "" "" "" "$capacity"
+               retval=$?
+               
+               # Detect ``dangerously dedicated'' filesystems
+               f_device_probe_disk_fs device "$devname" "$capacity" &&
+                       retval=$SUCCESS # Errors ignored
+
+               return $retval
+               ;;
+       *)
+               return $FAILURE # Unknown GEOM class
+       esac
+
+       #
+       # Still here? Must be $GEOM_CLASS_LABEL
+       #
+
+       local label_geom label_devname label_devgeom= label_devconsumer
+       local label_devprovider= label_devprovider_ref label_devprovider_config
+       local label_gpart_type
+
+       if f_struct "$p_provider"; then
+               label_geom="$p_provider_geom"
+       else
+               label_geom="$provider_geom"
+       fi
+
+       case "$devname" in
+       gpt/*|gptid/*)
+               #
+               # Attempt to get the partition type by getting the `config'
+               # member of the provider for our device (which is named in the
+               # parent geom of our current provider).
+               #
+               debug= f_struct "$label_geom" get name label_devname &&
+                       debug= f_geom_find "$label_devname" $GEOM_CLASS_DEV \
+                               label_devgeom
+               debug= f_struct "$label_devgeom" get \
+                       consumer1 label_devconsumer
+               debug= f_struct "$label_devconsumer" get \
+                       provider_ref label_devprovider_ref &&
+                       debug= f_geom_find_by id "$label_devprovider_ref" \
+                               provider label_devprovider
+               debug= f_struct "$label_devprovider" get \
+                       config label_devprovider_config
+               debug= f_struct "$label_devprovider_config" get \
+                       type label_gpart_type
+
+               #
+               # Register device label based on partition type
+               #
+               f_device_probe_geom_part device \
+                       "$label_gpart_type" "$devname" "$capacity"
+               return $?
+               ;;
+       iso9660/*)
+               f_dprintf "Found CDROM device labeled %s" "$devname"
+               debug= f_device_register device \
+                       "$devname" "ISO9660 file system" \
+                       "/dev/$devname" $DEVICE_TYPE_CDROM 1 \
+                       f_media_init_cdrom f_media_get_cdrom \
+                       f_media_shutdown_cdrom "" "$capacity"
+               return $?
+               ;;
+       label/*)
+               # For generic labels, use provider geom name as real device
+               debug= f_struct "$label_geom" get name label_devname
+
+               # Look up label geom device in device catalog for default desc
+               debug= f_device_catalog_get \
+                       $DEVICE_TYPE_ANY "$label_devname" catalog_struct
+               [ "$desc" ] || debug= f_struct \
+                       "catalog_device_$catalog_struct" get desc desc
+
+               # Use device catalog entry for potential re-classification(s)
+               debug= f_struct "catalog_device_$catalog_struct" get \
+                       type catalog_type
+
+               # First attempt to classify by device catalog (see MAIN)
+               case "$catalog_type" in
+               $DEVICE_TYPE_CDROM)
+                       f_dprintf "Found CDROM device for disk %s" "$devname"
+                       debug= f_device_register device "$devname" "$desc" \
+                               "/dev/$devname" $DEVICE_TYPE_CDROM 1 \
+                               f_media_init_cdrom f_media_get_cdrom \
+                               f_media_shutdown_cdrom "" "$capacity" &&
+                               return $SUCCESS
+                       ;;
+               esac
+
+               # Fall back to register label device as a disk and taste it
+               f_dprintf "Found disk device labeled %s" "$devname"
+               debug= f_device_register device \
+                       "$devname" "GEOM LABEL device" \
+                       "/dev/$devname" $DEVICE_TYPE_DISK 1 \
+                       "" "" "" "" "$capacity"
+               retval=$?
+
+               # Detect ``dangerously dedicated'' filesystems (errors ignored)
+               f_device_probe_disk_fs device "$devname" "$capacity" &&
+                       retval=$SUCCESS
+
+               return $retval
+               ;;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to