1if [ ! "$_DEVICE_SUBR" ]; then _DEVICE_SUBR=1 2# 3# Copyright (c) 2012-2013 Devin Teske 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25# SUCH DAMAGE. 26# 27# $FreeBSD$ 28# 29############################################################ INCLUDES 30 31BSDCFG_SHARE="/usr/share/bsdconfig" 32. $BSDCFG_SHARE/common.subr || exit 1 33f_dprintf "%s: loading includes..." device.subr 34f_include $BSDCFG_SHARE/dialog.subr 35f_include $BSDCFG_SHARE/strings.subr 36f_include $BSDCFG_SHARE/struct.subr 37 38BSDCFG_LIBE="/usr/libexec/bsdconfig" 39f_include_lang $BSDCFG_LIBE/include/messages.subr 40 41############################################################ GLOBALS 42 43DEVICES= 44DEVICE_NAMES= 45NDEVICES=0 46 47# A "device" from sysinstall's point of view 48f_struct_define DEVICE \ 49 name \ 50 desc \ 51 devname \ 52 type \ 53 capacity \ 54 enabled \ 55 init \ 56 get \ 57 shutdown \ 58 flags \ 59 private \ 60 volume 61 62# Network devices have their `private' property set to this 63f_struct_define DEVICE_INFO \ 64 use_rtsol use_dhcp ipaddr ipv6addr netmask extras 65 66setvar DEVICE_TYPE_NONE 1 67setvar DEVICE_TYPE_DISK 2 68setvar DEVICE_TYPE_FLOPPY 3 69setvar DEVICE_TYPE_FTP 4 70setvar DEVICE_TYPE_NETWORK 5 71setvar DEVICE_TYPE_CDROM 6 72setvar DEVICE_TYPE_USB 7 73setvar DEVICE_TYPE_DOS 8 74setvar DEVICE_TYPE_UFS 9 75setvar DEVICE_TYPE_NFS 10 76setvar DEVICE_TYPE_ANY 11 77setvar DEVICE_TYPE_HTTP_PROXY 12 78setvar DEVICE_TYPE_HTTP 13 79 80# Network devices have the following flags available 81setvar IF_ETHERNET 1 82setvar IF_WIRELESS 2 83setvar IF_ACTIVE 4 84 85# 86# Default behavior is to call f_device_get_all() automatically when loaded. 87# 88: ${DEVICE_SELF_SCAN_ALL=1} 89 90############################################################ FUNCTIONS 91 92# f_device_try $name [$i [$var_path]] 93# 94# Test a particular device. If $i is given, then $name is expected to contain a 95# single "%d" where $i will be inserted using printf. If $var_path is given, 96# it is used as a variable name to provide the caller the device pathname. 97# 98# Returns success if the device path exists and is a cdev. 99# 100f_device_try() 101{ 102 local name="$1" i="$2" var_path="$3" unit 103 if [ "$i" ]; then 104 f_sprintf unit "$name" "$i" 105 else 106 unit="$name" 107 fi 108 case "$unit" in 109 /dev/*) : good ;; # already qualified 110 *) unit="/dev/$unit" ;; 111 esac 112 [ "$var_path" ] && setvar "$var_path" "$unit" 113 f_dprintf "f_device_try: making sure %s is a device node" "$unit" 114 if [ -c "$unit" ]; then 115 f_dprintf "f_device_try: %s is a cdev [good]" "$unit" 116 return $SUCCESS 117 else 118 f_dprintf "f_device_try: %s is not a cdev [skip]" "$unit" 119 return $FAILURE 120 fi 121} 122 123# f_device_register $name $desc $devname $type $enabled $init_function \ 124# $get_function $shutdown_function $private $capacity 125# 126# Register a device. A `structure' (see struct.subr) is created with the name 127# device_$name (so make sure $name contains only alpha-numeric characters or 128# the underscore, `_'). The remaining arguments after $name correspond to the 129# properties of the `DEVICE' structure-type (defined above). 130# 131# If not already registered, the device is then appended to the DEVICES 132# environment variable, a space-separated list of all registered devices. 133# 134f_device_register() 135{ 136 local name="$1" desc="$2" devname="$3" type="$4" enabled="$5" 137 local init_func="$6" get_func="$7" shutdown_func="$8" private="$9" 138 local capacity="${10}" 139 140 f_struct_new DEVICE "device_$name" || return $FAILURE 141 device_$name set name "$name" 142 device_$name set desc "$desc" 143 device_$name set devname "$devname" 144 device_$name set type "$type" 145 device_$name set enabled "$enabled" 146 device_$name set init "$init_func" 147 device_$name set get "$get_func" 148 device_$name set shutdown "$shutdown_func" 149 device_$name set private "$private" 150 device_$name set capacity "$capacity" 151 152 # Scan our global register to see if it needs ammending 153 local dev found= 154 for dev in $DEVICES; do 155 [ "$dev" = "$name" ] || continue 156 found=1 && break 157 done 158 [ "$found" ] || DEVICES="$DEVICES $name" 159 160 return $SUCCESS 161} 162 163# f_device_reset 164# 165# Reset the registered device chain. 166# 167f_device_reset() 168{ 169 local dev 170 for dev in $DEVICES; do 171 f_device_shutdown $dev 172 173 # 174 # XXX this potentially leaks $dev->private if it's being 175 # used to point to something dynamic, but you're not supposed 176 # to call this routine at such times that some open instance 177 # has its private member pointing somewhere anyway. XXX 178 # 179 f_struct_free device_$dev 180 done 181 DEVICES= 182} 183 184# f_device_reset_network 185# 186# Reset the registered network device chain. 187# 188f_device_reset_network() 189{ 190 local dev type private pruned_list= 191 for dev in $DEVICES; do 192 device_$dev get type type 193 if [ "$type" != "$DEVICE_TYPE_NETWORK" ]; then 194 pruned_list="$pruned_list $dev" 195 continue 196 fi 197 198 # 199 # Leave the device up (don't call shutdown routine) 200 # 201 202 # Network devices may have DEVICE_INFO private member 203 device_$dev get private private 204 [ "$private" ] && f_struct_free "$private" 205 206 f_struct_free device_$dev 207 done 208 DEVICES="${pruned_list# }" 209} 210 211# f_device_get_all 212# 213# Get all device information for devices we have attached. 214# 215f_device_get_all() 216{ 217 local devname desc capacity 218 219 f_dprintf "f_device_get_all: Probing devices..." 220 f_dialog_info "$msg_probing_devices_please_wait_this_can_take_a_while" 221 222 # First go for the network interfaces 223 f_device_get_all_network 224 225 # Next, try to find all the types of devices one might use 226 # as a media source for content 227 # 228 229 local dev type max n=0 230 for dev in $DEVICE_NAMES; do 231 n=$(( $n + 1 )) 232 # Get the desc, type, and max (with debugging disabled) 233 # NOTE: Bypassing f_device_name_get() for efficiency 234 # ASIDE: This would be equivalent to the following: 235 # debug= f_device_name_get $dev desc 236 # debug= f_device_name_get $dev type 237 # debug= f_device_name_get $dev max 238 debug= f_getvar _device_desc$n desc 239 debug= f_getvar _device_type$n type 240 debug= f_getvar _device_max$n max 241 242 local k=0 243 while [ $k -lt ${max:-0} ]; do 244 i=$k k=$(( $k + 1 )) 245 devname="" 246 case "$type" in 247 $DEVICE_TYPE_CDROM) 248 f_device_try "$dev" "$i" devname || continue 249 f_device_capacity "$devname" capacity 250 f_device_register "${devname##*/}" "$desc" \ 251 "$devname" $DEVICE_TYPE_CDROM 1 \ 252 f_media_init_cdrom f_media_get_cdrom \ 253 f_media_shutdown_cdrom "" "$capacity" 254 f_dprintf "Found a CDROM device for %s" \ 255 "$devname" 256 ;; 257 $DEVICE_TYPE_FLOPPY) 258 f_device_try "$dev" "$i" devname || continue 259 f_device_capacity "$devname" capacity 260 f_device_register "${devname##*/}" "$desc" \ 261 "$devname" $DEVICE_TYPE_FLOPPY 1 \ 262 f_media_init_floppy \ 263 f_media_get_floppy \ 264 f_media_shutdown_floppy "" "$capacity" 265 f_dprintf "Found a floppy device for %s" \ 266 "$devname" 267 ;; 268 $DEVICE_TYPE_USB) 269 f_device_try "$dev" "$i" devname || continue 270 f_device_capacity "$devname" capacity 271 f_device_register "${devname##*/}" "$desc" \ 272 "$devname" $DEVICE_TYPE_USB 1 \ 273 f_media_init_usb f_media_get_usb \ 274 f_media_shutdown_usb "" "$capacity" 275 f_dprintf "Found a USB disk for %s" "$devname" 276 ;; 277 esac 278 done 279 done 280 281 # Register ISO9660 providers as CDROM devices 282 for devname in /dev/iso9660/*; do 283 f_device_try "$devname" || continue 284 f_device_capacity "$devname" capacity 285 f_device_register "${devname##*/}" "ISO9660 file system" \ 286 "$devname" $DEVICE_TYPE_CDROM 1 \ 287 f_media_init_cdrom f_media_get_cdrom \ 288 f_media_shutdown_cdrom "" "$capacity" 289 f_dprintf "Found a CDROM device for %s" "$devname" 290 done 291 292 # Scan for mdconfig(8)-created md(4) devices 293 local filename 294 for devname in /dev/md[0-9] /dev/md[0-9][0-9]; do 295 f_device_try "$devname" || continue 296 297 # See if the md(4) device is a vnode type backed by a file 298 filename=$( sysctl kern.geom.conftxt | 299 awk -v devname="${devname##*/}" \ 300 ' 301 ( $2 == "MD" ) && \ 302 ( $3 == devname ) && \ 303 ( $(NF-2) == "vnode" ) && \ 304 ( $(NF-1) == "file" ) \ 305 { 306 print $NF 307 } 308 ' ) 309 case "$filename" in 310 *.iso) # Register the device as an ISO9660 provider 311 f_device_capacity "$devname" capacity 312 f_device_register "${devname##*/}" \ 313 "md(4) vnode file system" \ 314 "$devname" $DEVICE_TYPE_CDROM 1 \ 315 f_media_init_cdrom f_media_get_cdrom \ 316 f_media_shutdown_cdrom "" "$capacity" 317 f_dprintf "Found a CDROM device for %s" "$devname" 318 ;; 319 esac 320 done 321 322 # Finally go get the disks and look for partitions to register 323 local diskname slices index type rest slice part 324 for diskname in $( sysctl -n kern.disks ); do 325 326 case "$diskname" in 327 cd*) 328 # XXX 329 # Due to unknown reasons, kern.disks returns SCSI 330 # CDROM as a valid disk. This will prevent bsdconfig 331 # from presenting SCSI CDROMs as available disks in 332 # various menus. Why GEOM treats SCSI CDROM as a disk 333 # is beyond me and that should be investigated. 334 # For temporary workaround, ignore SCSI CDROM device. 335 # 336 continue ;; 337 esac 338 339 # Try to create a list of partitions and their types, 340 # consisting of "N,typeN ..." (e.g., "1,0xa5 2,0x06"). 341 if ! slices=$( fdisk -p "$diskname" 2> /dev/null | 342 awk '( $1 == "p" ) { print $2","$3 }' ) 343 then 344 f_dprintf "Unable to open disk %s" "$diskname" 345 continue 346 fi 347 348 # Try and find its description 349 f_device_desc "$diskname" $DEVICE_TYPE_DISK desc 350 351 f_device_capacity "$diskname" capacity 352 f_device_register "$diskname" "$desc" \ 353 "/dev/$diskname" $DEVICE_TYPE_DISK 0 \ 354 "" "" "" "" "$capacity" 355 f_dprintf "Found a disk device named %s" "$diskname" 356 357 # Look for existing partitions to register 358 for slice in $slices; do 359 index="${slice%%,*}" type="${slice#*,}" 360 slice=${diskname}s$index 361 case "$type" in 362 0x01|0x04|0x06|0x0b|0x0c|0x0e|0xef) 363 # DOS partitions to add as "DOS media devices" 364 f_device_capacity "/dev/$slice" capacity 365 f_device_register "$slice" "" \ 366 "/dev/$slice" $DEVICE_TYPE_DOS 1 \ 367 f_media_init_dos f_media_get_dos \ 368 f_media_shutdown_dos "" "$capacity" 369 f_dprintf "Found a DOS partition %s" "$slice" 370 ;; 371 0xa5) # FreeBSD partition 372 for part in $( 373 bsdlabel -r $slice 2> /dev/null | 374 awk -v slice="$slice" ' 375 ( $1 ~ /[abdefgh]:/ ) { 376 printf "%s%s\n", 377 slice, 378 substr($1,1,1) 379 }' 380 ); do 381 f_quietly dumpfs -m /dev/$part || 382 continue 383 f_device_capacity \ 384 "$/dev/$part" capacity 385 f_device_register \ 386 "$part" "" "/dev/$part" \ 387 $DEVICE_TYPE_UFS 1 \ 388 f_media_init_ufs \ 389 f_media_get_ufs \ 390 f_media_shutdown_ufs "" \ 391 "$capacity" 392 f_dprintf "Found a UFS partition %s" \ 393 "$part" 394 done # parts 395 ;; 396 esac 397 done # slices 398 399 done # disks 400} 401 402# f_device_get_all_network 403# 404# Get all network device information for attached network devices. 405# 406f_device_get_all_network() 407{ 408 local devname desc flags 409 for devname in $( ifconfig -l ); do 410 # Eliminate network devices that don't make sense 411 case "$devname" in 412 lo*) continue ;; 413 esac 414 415 # Try and find its description 416 f_device_desc "$devname" $DEVICE_TYPE_NETWORK desc 417 418 f_dprintf "Found a network device named %s" "$devname" 419 f_device_register $devname \ 420 "$desc" "$devname" $DEVICE_TYPE_NETWORK 1 \ 421 f_media_init_network "" f_media_shutdown_network "" -1 422 423 # Set flags based on media and status 424 flags=0 425 eval "$( ifconfig $devname 2> /dev/null | awk -v var=flags ' 426 function _or(var, mask) { 427 printf "%s=$(( $%s | $%s ))\n", var, var, mask 428 } 429 BEGIN { S = "[[:space:]]+" } 430 { 431 if (!match($0, "^" S "(media|status):" S)) next 432 value = substr($0, RLENGTH + 1) 433 if ($1 == "media:") { 434 if (value ~ /Ethernet/) _or(var, "IF_ETHERNET") 435 if (value ~ /802\.11/) _or(var, "IF_WIRELESS") 436 } else if ($1 == "status:") { 437 if (value ~ /^active/) _or(var, "IF_ACTIVE") 438 } 439 }' )" 440 device_$devname set flags $flags 441 done 442} 443 444# f_device_name_get $type $name type|desc|max [$var_to_set] 445# 446# Fetch the device type (type), description (desc), or maximum number of 447# devices to scan for (max) associated with device $name and $type. If $type is 448# either NULL, missing, or set to $DEVICE_TYPE_ANY then only $name is used. 449# Returns success if a match was found, otherwise failure. 450# 451# If $var_to_set is missing or NULL, the device name is printed to standard out 452# for capturing in a sub-shell (which is less-recommended because of 453# performance degredation; for example, when called in a loop). 454# 455f_device_name_get() 456{ 457 local __type="$1" __name="$2" __prop="$3" __var_to_set="$4" 458 local __dev __devtype __n=0 459 460 # Return failure if no $name or $prop is an unknown property 461 [ "$__name" ] || return $FAILURE 462 case "$__prop" in type|desc|max) : good ;; 463 *) return $FAILURE; esac 464 465 # 466 # Attempt to create an alternate-form of $__name that contains the 467 # first contiguous string of numbers replaced with `%d' for comparison 468 # against stored pattern names (see MAIN). 469 # 470 local __left="${__name%%[0-9]*}" __right="${__name#*[0-9]}" __dname= 471 if [ "$__left" != "$__name" ]; then 472 # Chop leading digits from right 'til we hit first non-digit 473 while :; do 474 case "$__right" in 475 [0-9]*) __right="${__right#[0-9]}" ;; 476 *) break 477 esac 478 done 479 __dname="${__left}%d$__right" 480 fi 481 482 [ "$__type" = "$DEVICE_TYPE_ANY" ] && __type= 483 for __dev in $DEVICE_NAMES; do 484 __n=$(( $__n + 1 )) 485 [ "$__dev" = "$__name" -o "$__dev" = "$__dname" ] || continue 486 f_getvar _device_type$__n __devtype 487 [ "${__type:-$__devtype}" = "$__devtype" ] || continue 488 f_getvar _device_$__prop$__n $__var_to_set 489 return $? 490 done 491 return $FAILURE 492} 493 494# f_device_name_set $type $name $desc [$max] 495# 496# Store a description (desc) and [optionally] maximum number of devices to scan 497# for (max) in-association with device $type and $name. Returns success unless 498# $name is NULL or missing. Use the f_device_name_get() routine with the same 499# $name and optionally $type to retrieve one of type, desc, or max properties. 500# 501f_device_name_set() 502{ 503 local type="$1" name="$2" desc="$3" max="$4" 504 local dev devtype n=0 found= 505 [ "$name" ] || return $FAILURE 506 for dev in $DEVICE_NAMES; do 507 n=$(( $n + 1 )) 508 [ "$dev" = "$name" ] || continue 509 if f_getvar _device_type$n devtype; then 510 # Allow multiple entries with same name but diff type 511 [ "$devtype" = "$type" ] || continue 512 fi 513 found=1 && break 514 done 515 if [ ! "$found" ]; then 516 DEVICE_NAMES="$DEVICE_NAMES $name" 517 n=$(( $n + 1 )) 518 fi 519 setvar _device_type$n "$type" 520 setvar _device_desc$n "$desc" 521 [ "${4+set}" ] && setvar _device_max$n "$max" 522 return $SUCCESS 523} 524 525# f_device_desc $device_name $device_type [$var_to_set] 526# 527# Print a description for a device name (eg., `fxp0') given a specific device 528# type/class. 529# 530# If $var_to_set is missing or NULL, the device description is printed to 531# standard out for capturing in a sub-shell (which is less-recommended because 532# of performance degredation; for example, when called in a loop). 533# 534f_device_desc() 535{ 536 local __name="$1" __type="$2" __var_to_set="$3" 537 local __devname __devunit __cp 538 539 # Check variables 540 [ "$__name" ] || return $SUCCESS 541 [ "$__type" = "$DEVICE_TYPE_ANY" ] && type= 542 [ "$__var_to_set" ] && { setvar "$__var_to_set" "" || return; } 543 544 # 545 # Return sysctl MIB dev.NAME.UNIT.%desc if it exists, 546 # otherwise fall through to below static list. 547 # 548 if f_have sysctl; then 549 __devname="${__name%%[0-9]*}" 550 __devunit="${__name#$__devname}" 551 __devunit="${__devunit%%[!0-9]*}" 552 if [ "$__var_to_set" ]; then 553 if __cp=$( 554 sysctl -n "dev.$__devname.$__devunit.%desc" \ 555 2> /dev/null 556 ); then 557 setvar "$__var_to_set" "$__cp" && 558 return $SUCCESS 559 fi 560 else 561 sysctl -n "dev.$__devname.$__devunit.%desc" \ 562 2> /dev/null && return $SUCCESS 563 fi 564 fi 565 566 # 567 # For disks, attempt to return camcontrol(8) descriptions. 568 # Otherwise fall through to below static list. 569 # 570 f_have camcontrol && 571 [ "${__type:-$DEVICE_TYPE_DISK}" = "$DEVICE_TYPE_DISK" ] && 572 __cp=$( camcontrol devlist 2> /dev/null | awk -v disk="$__name" ' 573 $0~"(\\(|,)"disk"(,|\\))" { 574 if (!match($0, "<[^>]+>")) next 575 print substr($0, RSTART+1, RLENGTH-2) 576 found = 1 577 exit 578 } 579 END { exit ! found } 580 ' ) && setvar "$__var_to_set" "$__cp" && return $SUCCESS 581 582 # 583 # Attempt to create an alternate-form of $__name that contains the 584 # first contiguous string of numbers replaced with `%d' for comparison 585 # against stored pattern names (see MAIN). 586 # 587 local __left="${__name%%[0-9]*}" __right="${__name#*[0-9]}" __dname= 588 if [ "$__left" != "$__name" ]; then 589 # Chop leading digits from right 'til we hit first non-digit 590 while :; do 591 case "$__right" in 592 [0-9]*) __right="${__right#[0-9]}" ;; 593 *) break 594 esac 595 done 596 __dname="${__left}%d$__right" 597 fi 598 599 local __dev __devtype __n=0 600 for __dev in $DEVICE_NAMES; do 601 __n=$(( $__n + 1 )) 602 debug= f_getvar _device_type$__n __devtype 603 [ "${__type:-$__devtype}" = "$__devtype" ] || continue 604 if [ "$__devtype" = "$DEVICE_TYPE_NETWORK" ]; then 605 __devname=$( f_substr "$__name" 0 ${#__dev} ) 606 [ "$__devname" = "$__dev" ] || continue 607 else 608 [ "$__dev" = "$__name" -o "$__dev" = "$__dname" ] || 609 continue 610 fi 611 debug= f_getvar _device_desc$__n $__var_to_set 612 return $? 613 done 614 615 # 616 # Sensible fall-backs for specific types 617 # 618 case "$__type" in 619 $DEVICE_TYPE_CDROM) __cp="<unknown cdrom device type>" ;; 620 $DEVICE_TYPE_DISK) __cp="<unknown disk device type>" ;; 621 $DEVICE_TYPE_FLOPPY) __cp="<unknown floppy device type>" ;; 622 $DEVICE_TYPE_USB) __cp="<unknown usb storage device type>" ;; 623 $DEVICE_TYPE_NETWORK) __cp="<unknown network interface type>" ;; 624 *) 625 __cp="<unknown device type>" 626 esac 627 628 if [ "$__var_to_set" ]; then 629 setvar "$__var_to_set" "$__cp" 630 else 631 echo "$__cp" 632 fi 633 634 return $FAILURE 635} 636 637# f_device_is_ethernet $device 638# 639# Returns true if $device is a wired Ethernet network interface. Otherwise 640# returns false. Example wired interfaces include: fxp0 em0 bge0 rl0 etc. 641# 642f_device_is_ethernet() 643{ 644 local dev="$1" type flags 645 646 # Make sure we have an actual device by that name 647 f_struct "device_$dev" || return $FAILURE 648 649 # Make sure that the device is a network device 650 device_$dev get type type 651 [ "$type" = "$DEVICE_TYPE_NETWORK" ] || return $FAILURE 652 653 # Make sure that the media flags indicate that it is Ethernet 654 device_$dev get flags flags 655 [ $(( ${flags:-0} & $IF_ETHERNET )) -eq $IF_ETHERNET ] 656} 657 658# f_device_is_wireless $device 659# 660# Returns true if $device is a Wireless network interface. Otherwise returns 661# false. Examples of wireless interfaces include: iwn0 662# 663f_device_is_wireless() 664{ 665 local dev="$1" type flags 666 667 # Make sure we have an actual device by that name 668 f_struct "device_$dev" || return $FAILURE 669 670 # Make sure that the device is a network device 671 device_$dev get type type 672 [ "$type" = "$DEVICE_TYPE_NETWORK" ] || return $FAILURE 673 674 # Make sure that the media flags indicate that it is Ethernet 675 device_$dev get flags flags 676 [ $(( ${flags:-0} & $IF_WIRELESS )) -eq $IF_WIRELESS ] 677} 678 679# f_device_is_active $device 680# 681# Returns true if $device is active. Otherwise returns false. Currently this 682# only works for network interfaces. 683# 684f_device_is_active() 685{ 686 local dev="$1" type flags=0 687 688 # Make sure we have an actual device by that name 689 f_struct "device_$dev" || return $FAILURE 690 691 device_$dev get type type 692 case "$type" in 693 $DEVICE_TYPE_NETWORK) 694 # Make sure that the media flags indicate that it is active 695 device_$dev get flags flags 696 [ $(( ${flags:-0} & $IF_ACTIVE )) -eq $IF_ACTIVE ] 697 ;; 698 *) 699 return $FAILURE 700 esac 701} 702 703# f_device_rescan 704# 705# Rescan all devices, after closing previous set - convenience function. 706# 707f_device_rescan() 708{ 709 f_device_reset 710 f_device_get_all 711} 712 713# f_device_rescan_network 714# 715# Rescan all network devices, after closing previous set - for convenience. 716# 717f_device_rescan_network() 718{ 719 f_device_reset_network 720 f_device_get_all_network 721} 722 723# f_device_find $name [$type [$var_to_set]] 724# 725# Find one or more registered devices by name, type, or both. Returns a space- 726# separated list of devices matching the search criterion. 727# 728# If $var_to_set is missing or NULL, the device name(s) are printed to standard 729# out for capturing in a sub-shell (which is less-recommended because of 730# performance degredation; for example, when called in a loop). 731# 732f_device_find() 733{ 734 local __name="$1" __type="${2:-$DEVICE_TYPE_ANY}" __var_to_set="$3" 735 local __dev __devname __devtype __found= 736 for __dev in $DEVICES; do 737 device_$__dev get name __devname 738 device_$__dev get type __devtype 739 if [ "$__name" = "$__devname" -o ! "$__name" ] && 740 [ "$__type" = "$DEVICE_TYPE_ANY" -o \ 741 "$__type" = "$__devtype" ] 742 then 743 __found="$__found $__dev" 744 fi 745 done 746 if [ "$__var_to_set" ]; then 747 setvar "$__var_to_set" "${__found# }" 748 else 749 echo $__found 750 fi 751 [ "$__found" ] # Return status 752} 753 754# f_device_init $name 755# 756# Initialize a device by evaluating its `init' function. 757# 758f_device_init() 759{ 760 local name="$1" init_func 761 device_$name get init init_func || return $? 762 ${init_func:-:} $name 763} 764 765# f_device_get $name $file [$probe] 766# 767# Read $file by evaluating the device's `get' function. The file is commonly 768# produced on standard output (but it truly depends on the function called). 769# 770f_device_get() 771{ 772 local name="$1" file="$2" probe="$3" get_func 773 device_$name get get get_func || return $? 774 ${get_func:-:} $name "$file" ${3+"$probe"} 775} 776 777# f_device_shutdown $name 778# 779# Shutdown a device by evaluating its `shutdown' function. 780# 781f_device_shutdown() 782{ 783 local name="$1" shutdown_func 784 device_$name get shutdown shutdown_func || return $? 785 ${shutdown_func:-:} $name 786} 787 788# f_device_menu $title $prompt $hline $device_type [$helpfile] 789# 790# Display a menu listing all the devices of a certain type in the system. 791# 792f_device_menu() 793{ 794 f_dialog_title "$1" 795 local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE" 796 f_dialog_title_restore 797 798 local prompt="$2" hline="$3" type="$4" helpfile="$5" 799 800 local dev devtype devs= 801 for dev in $DEVICES; do 802 device_$dev get type devtype || continue 803 [ "$devtype" = "$type" ] || continue 804 devs="$devs $dev" 805 done 806 [ "$devs" ] || return $DIALOG_CANCEL 807 808 local desc menu_list= 809 for dev in $devs; do 810 device_$dev get desc desc 811 f_shell_escape "$desc" desc 812 menu_list="$menu_list '$dev' '$desc'" 813 done 814 815 local height width rows 816 eval f_dialog_menu_size height width rows \ 817 \"\$title\" \ 818 \"\$btitle\" \ 819 \"\$prompt\" \ 820 \"\$hline\" \ 821 $menu_list 822 823 local errexit= 824 case $- in *e*) errexit=1; esac 825 set +e 826 827 local mtag 828 while :; do 829 mtag=$( eval $DIALOG \ 830 --title \"\$title\" \ 831 --backtitle \"\$btitle\" \ 832 --ok-label \"\$msg_ok\" \ 833 --cancel-label \"\$msg_cancel\" \ 834 ${helpfile:+ \ 835 --help-button \ 836 --help-label \"\$msg_help\" \ 837 ${USE_XDIALOG:+--help \"\"} \ 838 } \ 839 --menu \"\$prompt\" \ 840 $height $width $rows \ 841 $menu_list \ 842 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 843 ) 844 local retval=$? 845 846 [ $retval -ne $DIALOG_HELP ] && break 847 # Otherwise, the Help button was pressed 848 f_show_help "$helpfile" 849 # ...then loop back to menu 850 done 851 f_dprintf "retval=%u mtag=[%s]" $retval "$mtag" 852 853 [ "$errexit" ] && set -e 854 855 if [ $retval -eq $DIALOG_OK ]; then 856 # Clean up the output of [X]dialog(1) and return it 857 f_dialog_data_sanitize mtag 858 echo "$mtag" >&2 859 fi 860 861 return $retval 862} 863 864# f_device_capacity $device [$var_to_set] 865# 866# Return the capacity of $device in bytes. 867# 868f_device_capacity() 869{ 870 local __dev="$1" __var_to_set="$2" 871 local __bytes 872 873 __bytes=$( diskinfo -v "$__dev" 2> /dev/null | 874 awk '/# mediasize in bytes/{print $1}' ) || __bytes=-1 875 876 if [ "$__var_to_set" ]; then 877 setvar "$__var_to_set" "$__bytes" 878 else 879 echo "$__bytes" 880 fi 881} 882 883# 884# Short-hand 885# 886f_cdrom() { f_device_name_set $DEVICE_TYPE_CDROM "$1" "$2" "$3"; } 887f_disk() { f_device_name_set $DEVICE_TYPE_DISK "$1" "$2" "$3"; } 888f_floppy() { f_device_name_set $DEVICE_TYPE_FLOPPY "$1" "$2" "$3"; } 889f_serial() { f_device_name_set $DEVICE_TYPE_NETWORK "$1" "$2" "$3"; } 890f_usb() { f_device_name_set $DEVICE_TYPE_USB "$1" "$2" "$3"; } 891f_network() { f_device_name_set $DEVICE_TYPE_NETWORK "$1" "$2"; } 892 893############################################################ MAIN 894 895# CDROM, Disk, Floppy, Serial, and USB devices/names 896f_cdrom "cd%d" "SCSI CDROM drive" 4 897f_cdrom "mcd%d" "Mitsumi (old model) CDROM drive" 4 898f_cdrom "scd%d" "Sony CDROM drive - CDU31/33A type" 4 899f_disk "aacd%d" "Adaptec FSA RAID array" 4 900f_disk "ada%d" "ATA/SATA disk device" 16 901f_disk "amrd%d" "AMI MegaRAID drive" 4 902f_disk "da%d" "SCSI disk device" 16 903f_disk "idad%d" "Compaq RAID array" 4 904f_disk "ipsd%d" "IBM ServeRAID RAID array" 4 905f_disk "mfid%d" "LSI MegaRAID SAS array" 4 906f_disk "mlxd%d" "Mylex RAID disk" 4 907f_disk "twed%d" "3ware ATA RAID array" 4 908f_disk "vtbd%d" "VirtIO Block Device" 16 909f_floppy "fd%d" "Floppy Drive unit A" 4 910f_serial "cuau%d" "%s on device %s (COM%d)" 16 911f_usb "da%da" "USB Mass Storage Device" 16 912 913# Network interfaces/names 914f_network "ae" "Attansic/Atheros L2 Fast Ethernet" 915f_network "age" "Attansic/Atheros L1 Gigabit Ethernet" 916f_network "alc" "Atheros AR8131/AR8132 PCIe Ethernet" 917f_network "ale" "Atheros AR8121/AR8113/AR8114 PCIe Ethernet" 918f_network "an" "Aironet 4500/4800 802.11 wireless adapter" 919f_network "ath" "Atheros IEEE 802.11 wireless adapter" 920f_network "aue" "ADMtek USB Ethernet adapter" 921f_network "axe" "ASIX Electronics USB Ethernet adapter" 922f_network "bce" "Broadcom NetXtreme II Gigabit Ethernet card" 923f_network "bfe" "Broadcom BCM440x PCI Ethernet card" 924f_network "bge" "Broadcom BCM570x PCI Gigabit Ethernet card" 925f_network "bm" "Apple BMAC Built-in Ethernet" 926f_network "bwn" "Broadcom BCM43xx IEEE 802.11 wireless adapter" 927f_network "cas" "Sun Cassini/Cassini+ or NS DP83065 Saturn Ethernet" 928f_network "cc3i" "SDL HSSI sync serial PCI card" 929f_network "cue" "CATC USB Ethernet adapter" 930f_network "cxgb" "Chelsio T3 10Gb Ethernet card" 931f_network "dc" "DEC/Intel 21143 (and clones) PCI Fast Ethernet card" 932f_network "de" "DEC DE435 PCI NIC or other DC21040-AA based card" 933f_network "disc" "Software discard network interface" 934f_network "ed" "Novell NE1000/2000; 3C503; NE2000-compatible PCMCIA" 935f_network "el" "3Com 3C501 Ethernet card" 936f_network "em" "Intel(R) PRO/1000 Ethernet card" 937f_network "en" "Efficient Networks ATM PCI card" 938f_network "ep" "3Com 3C509 Ethernet card/3C589 PCMCIA" 939f_network "et" "Agere ET1310 based PCI Express Gigabit Ethernet card" 940f_network "ex" "Intel EtherExpress Pro/10 Ethernet card" 941f_network "fe" "Fujitsu MB86960A/MB86965A Ethernet card" 942f_network "fpa" "DEC DEFPA PCI FDDI card" 943f_network "fwe" "FireWire Ethernet emulation" 944f_network "fwip" "IP over FireWire" 945f_network "fxp" "Intel EtherExpress Pro/100B PCI Fast Ethernet card" 946f_network "gem" "Apple GMAC or Sun ERI/GEM Ethernet adapter" 947f_network "hme" "Sun HME (Happy Meal Ethernet) Ethernet adapter" 948f_network "ie" "AT&T StarLAN 10 and EN100; 3Com 3C507; NI5210" 949f_network "igb" "Intel(R) PRO/1000 PCI Express Gigabit Ethernet card" 950f_network "ipw" "Intel PRO/Wireless 2100 IEEE 802.11 adapter" 951f_network "iwi" "Intel PRO/Wireless 2200BG/2225BG/2915ABG adapter" 952f_network "iwn" "Intel Wireless WiFi Link 4965AGN IEEE 802.11n adapter" 953f_network "ixgbe" "Intel(R) PRO/10Gb Ethernet card" 954f_network "ixgb" "Intel(R) PRO/10Gb Ethernet card" 955f_network "ix" "Intel Etherexpress Ethernet card" 956 # Maintain sequential order of above(3): ixgbe ixgb ix 957f_network "jme" "JMicron JMC250 Gigabit/JMC260 Fast Ethernet" 958f_network "kue" "Kawasaki LSI USB Ethernet adapter" 959f_network "le" "AMD Am7900 LANCE or Am79C9xx PCnet Ethernet adapter" 960f_network "lge" "Level 1 LXT1001 Gigabit Ethernet card" 961f_network "lnc" "Lance/PCnet (Isolan/Novell NE2100/NE32-VL) Ethernet" 962f_network "lo" "Loop-back (local) network interface" 963f_network "lp" "Parallel Port IP (PLIP) peer connection" 964f_network "malo" "Marvell Libertas 88W8335 802.11 wireless adapter" 965f_network "msk" "Marvell/SysKonnect Yukon II Gigabit Ethernet" 966f_network "mxge" "Myricom Myri10GE 10Gb Ethernet card" 967f_network "nfe" "NVIDIA nForce MCP Ethernet" 968f_network "nge" "NatSemi PCI Gigabit Ethernet card" 969f_network "ng" "Vimage netgraph(4) bridged Ethernet device" 970 # Maintain sequential order of above(2): nge ng 971f_network "nve" "NVIDIA nForce MCP Ethernet" 972f_network "nxge" "Neterion Xframe 10GbE Server/Storage adapter" 973f_network "pcn" "AMD Am79c79x PCI Ethernet card" 974f_network "plip" "Parallel Port IP (PLIP) peer connection" 975f_network "ral" "Ralink Technology IEEE 802.11 wireless adapter" 976f_network "ray" "Raytheon Raylink 802.11 wireless adapter" 977f_network "re" "RealTek 8139C+/8169/8169S/8110S PCI Ethernet adapter" 978f_network "rl" "RealTek 8129/8139 PCI Ethernet card" 979f_network "rue" "RealTek USB Ethernet card" 980f_network "rum" "Ralink Technology USB IEEE 802.11 wireless adapter" 981f_network "sf" "Adaptec AIC-6915 PCI Ethernet card" 982f_network "sge" "Silicon Integrated Systems SiS190/191 Ethernet" 983f_network "sis" "SiS 900/SiS 7016 PCI Ethernet card" 984f_network "sk" "SysKonnect PCI Gigabit Ethernet card" 985f_network "snc" "SONIC Ethernet card" 986f_network "sn" "SMC/Megahertz Ethernet card" 987 # Maintain sequential order of above(2): snc sn 988f_network "sr" "SDL T1/E1 sync serial PCI card" 989f_network "ste" "Sundance ST201 PCI Ethernet card" 990f_network "stge" "Sundance/Tamarack TC9021 Gigabit Ethernet" 991f_network "ti" "Alteon Networks PCI Gigabit Ethernet card" 992f_network "tl" "Texas Instruments ThunderLAN PCI Ethernet card" 993f_network "txp" "3Com 3cR990 Ethernet card" 994f_network "tx" "SMC 9432TX Ethernet card" 995 # Maintain sequential order of above(2): txp tx 996f_network "uath" "Atheros AR5005UG and AR5005UX USB wireless adapter" 997f_network "upgt" "Conexant/Intersil PrismGT USB wireless adapter" 998f_network "ural" "Ralink Technology RT2500USB 802.11 wireless adapter" 999f_network "urtw" "Realtek 8187L USB wireless adapter" 1000f_network "vge" "VIA VT612x PCI Gigabit Ethernet card" 1001f_network "vlan" "IEEE 802.1Q VLAN network interface" 1002f_network "vr" "VIA VT3043/VT86C100A Rhine PCI Ethernet card" 1003f_network "vx" "3COM 3c590 / 3c595 Ethernet card" 1004f_network "wb" "Winbond W89C840F PCI Ethernet card" 1005f_network "wi" "Lucent WaveLAN/IEEE 802.11 wireless adapter" 1006f_network "wpi" "Intel 3945ABG IEEE 802.11 wireless adapter" 1007f_network "wx" "Intel Gigabit Ethernet (82452) card" 1008f_network "xe" "Xircom/Intel EtherExpress Pro100/16 Ethernet card" 1009f_network "xl" "3COM 3c90x / 3c90xB PCI Ethernet card" 1010f_network "zyd" "ZyDAS ZD1211/ZD1211B USB 802.11 wireless adapter" 1011 1012f_count NDEVICES $DEVICE_NAMES 1013f_dprintf "%s: Initialized %u known device names/descriptions." device.subr \ 1014 $NDEVICES 1015 1016# 1017# Scan for the above devices unless requeted otherwise 1018# 1019f_dprintf "%s: DEVICE_SELF_SCAN_ALL=[%s]" device.subr "$DEVICE_SELF_SCAN_ALL" 1020case "$DEVICE_SELF_SCAN_ALL" in 1021""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;; 1022*) f_device_get_all 1023esac 1024 1025f_dprintf "%s: Successfully loaded." device.subr 1026 1027fi # ! $_DEVICE_SUBR 1028