#! /bin/bash
#
# Copyright (c) 2002 SuSE Linux AG, Nuremberg
#
# Author:  Susanne Oberhauser <froh@suse.de>, 2002
#
# the GNU Public License applies
#
usage="${0##*/}

create device nodes for all dasds in /proc/dasd/devices and create
symlinks mapping old style device names to the device nodes.

Example:

1098(ECKD) at ( 94:  8) is dasdc:active at blocksize: 4096, 1803060 blocks, 7043 MB

would e.g. create symlinks

/dev/dasdc  -> /dev/dasd/1098/disk
/dev/dasdc1 -> /dev/dasd/1098/part1
/dev/dasdc2 -> /dev/dasd/1098/part2
/dev/dasdc3 -> /dev/dasd/1098/part3

and /dev/dasd/1098/* device nodes.

This script will preserve ownership and permissions if a device node
existed with different major and minor (because major and minor can
change between reboots).

"

# abort on error
set -eu

# to preserve the script from doing anything real, call it with
# CONDOM=echo
: ${CONDOM=}

# create devices here
: ${DEV_ROOT="/dev"}
: ${DEV_DIR="$DEV_ROOT/dasd"}

# these are the default ownership and permissions
: ${DEV_OWNER="root:disk"}
: ${DEV_MODE="u=rw,g=rw,o="}


# this is the utility to get a VOLSER label of a partition
: ${QUERY_VOLSER:=}

function die # comment
{
    echo "$*" >&2
    exit 1
}

function create_node # node major minor device
# create /dev/$node and /dev/$device -> $node
# if $node contains a path, create the path as well.
# if $node exists and is a block device, retain its ownership and permission.
{
    local node="$1"
    local major="$2"
    local minor="$3"
    local device="$4"

    local node_abs=$DEV_ROOT/$node

    # remove any existing symlink
    $CONDOM rm -rf $DEV_ROOT/$device

    if test -e "$node_abs"
    then

	# if the file exists, check that it is a block device with the
	# correct major and minor and that it has the correct
	# permissions:

	if test -b "$node_abs"
	then
	    ls -l $node_abs | {

		read existing_mode existing_nlink \
		    existing_user existing_group \
		    existing_major existing_minor \
		    dummy

		if test "$existing_major" != "$major," -o "$existing_minor" != "$minor"
		then
		    # create a new node using the existing
		    # permissions, ownership and timestamp
		    $CONDOM mknod --mode="a=" $node_abs$$ b $major $minor || die mknod failed
		    $CONDOM chown --reference=$node_abs $node_abs$$
		    $CONDOM chmod --reference=$node_abs $node_abs$$
		    $CONDOM touch --reference=$node_abs $node_abs$$
		    $CONDOM mv $node_abs$$ $node_abs
		fi
	    }
	else
	    echo "$node_abs is not a block device:"
	    ls -l $node_abs
	    # this is an error condition.  should it be fatal?
	fi
    else
	# if the node does not exist yet, create it
	local node_abs_dir=$(dirname $node_abs)
	test -d $node_abs_dir || {
	    test -e $node_abs_dir && die "$node_abs_dir exists but is not a directory:
$(ls -l $node_abs_dir)"
	} || {
	    $CONDOM install --directory --owner=${DEV_OWNER%:*} --group=${DEV_OWNER#*:} $node_abs_dir
	}

	$CONDOM mknod --mode="a="  $node_abs b $major $minor
	$CONDOM chown "$DEV_OWNER" $node_abs
	$CONDOM chmod "$DEV_MODE"  $node_abs
    fi

    $CONDOM ln -snf $node $DEV_ROOT/$device
}

###################################################################
# scan /proc/dasd/devices and create the nodes for each device

# remove punctuation with tr, so read gets sane input
tr -s "[:punct:][:blank:]" " " < /proc/dasd/devices | 
while read address type at major minor is device state dummy
  do

  create_node dasd/$address/device $major $minor $device
  create_node dasd/$address/disc   $major $minor $device
  for partition in 1 2 3
  do
      create_node dasd/$address/part$partition $major $((minor+partition)) $device$partition
  done
done
# EOF