Home | History | Annotate | Download | only in ucblinks
      1 #!/bin/sh
      2 #
      3 # CDDL HEADER START
      4 #
      5 # The contents of this file are subject to the terms of the
      6 # Common Development and Distribution License (the "License").
      7 # You may not use this file except in compliance with the License.
      8 #
      9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10 # or http://www.opensolaris.org/os/licensing.
     11 # See the License for the specific language governing permissions
     12 # and limitations under the License.
     13 #
     14 # When distributing Covered Code, include this CDDL HEADER in each
     15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16 # If applicable, add the following below this CDDL HEADER, with the
     17 # fields enclosed by brackets "[]" replaced with your own identifying
     18 # information: Portions Copyright [yyyy] [name of copyright owner]
     19 #
     20 # CDDL HEADER END
     21 #
     22 
     23 # Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
     24 # Use is subject to license terms.
     25 #
     26 #ident	"%Z%%M%	%I%	%E% SMI"
     27 
     28 PATH=/sbin:/usr/sbin:/usr/bin:/etc
     29 export PATH
     30 
     31 RULEBASE=/usr/ucblib/ucblinks.awk
     32 
     33 # Name of device-type list produced by "devlinks"
     34 DEVTYPES=/etc/.obp_devices
     35 
     36 USAGE="Usage: `basename $0` [-r rootdir] [-e rulebase] [-d]"
     37 DOIT_CMD="sh -s"
     38 
     39 while getopts 'de:r:' flag
     40 do
     41 	case $flag in
     42 	d)	DOIT_CMD="cat -"
     43 		;;
     44 	e)
     45 		RULEBASE=$OPTARG;
     46 		case "$RULEBASE" in
     47 		/*)	;;
     48 		*)	RULEBASE="`pwd`/$RULEBASE";;
     49 		esac
     50 		;;
     51 	r)	ROOTDIR=$OPTARG;
     52 		;;
     53 	\?)	echo "$USAGE" >&2
     54 		exit 2;
     55 		;;
     56 	esac
     57 done
     58 
     59 shift `expr $OPTIND - 1`
     60 
     61 #
     62 # The rest of this script looks a mess.  But in fact underneath all the
     63 # 'sed's and 'awk's it is quite simple.
     64 #
     65 # First it creates a list of all the device nodes in the /devices directory
     66 # (by cd'ing to /dev, then doing a 'find' of all special files in ../devices
     67 # doing an 'ls -l' of these files, and sedding the output to produce a list
     68 # of the form 'major minor type name').
     69 #
     70 # As an added wrinkle it changes 'major' from a number to a driver-name using
     71 # sed rules produced from the "/etc/name_to_major file.
     72 #
     73 # Then it runs the awk rules in the rule-base on this list to produce a list
     74 # of compatability-links that must be created.  However, this does not produce
     75 # the links themselves because of the next stage:
     76 #
     77 # Finally this list of compatability-links is inspected and where possible links
     78 # to the SunOS5 names are created instead of links directly to the /devices
     79 # directory
     80 # (by 'find'ing all the symbolic links under /dev, ancomparing the
     81 # subdirectory they occur in, and the file to which they point, to
     82 # the comaptability-link information built above. If a match is found
     83 # a command to make a link to the 5.0 link, rather than to the /devices
     84 # entry, is created.  If not, a direct link is created)
     85 # And then the list of link command is executed by a shell, or printed on stdout
     86 # (in debugging mode)
     87 #
     88 # See -- not so complicated!  However the syntax of all these rules makes
     89 # the code below nearly incomprehensible.  Fear not; the only part you need
     90 # to change for extra devices is located in the 'RULEBASE' file.
     91 
     92 cd $ROOTDIR/dev
     93 
     94 GENSED=/tmp/mkcompat.sed$$
     95 GENAWK=/tmp/mkcompat.awk$$
     96 GENRULE=/tmp/mkcompat.rule$$
     97 
     98 rm -f $GENSED $GENAWK $GENRULE
     99 
    100 trap "rm -f $GENSED $GENAWK $GENRULE" 0
    101 
    102 #
    103 # First generate full rulebase.  This is done to keep common functions
    104 # out of the rulebase
    105 
    106 
    107 cat - >$GENRULE <<\!EOD
    108 function out(dev, dir, extraname)	{
    109 	c = split(dir, junk, "/") - 1;
    110 
    111 	if (junk[1] == ".")
    112 		c--;
    113 
    114 	fulldevfs = "";
    115 
    116 	while ( c > 0) {
    117 		fulldevfs = "../" fulldevfs;
    118 		c--;
    119 	}
    120 	fulldevfs = fulldevfs $4;
    121 
    122 	printf "devname[\"" fulldevfs "\"] = \"" dev "\";";
    123 
    124 	if (length(dir) > 0)
    125 		printf " devdir[\"" fulldevfs "\"] = \"" dir "\";";
    126 
    127 	if (length(extraname) > 0)
    128 		printf " devextra[\"" fulldevfs "\"] = \"" extraname "\";";
    129 	printf "\n";
    130 	} 
    131 
    132 !EOD
    133 
    134 #
    135 # Now see if we need to do CD drive special handling.  The SCSI CD and disk
    136 # drivers have been merged in SunOS5, so we cannot do the normal differentiation
    137 # on major number with these devices.  However the "disks" program does write
    138 # a list of all OBP cd device names in a pecial file; by massaging this file
    139 # we are able to construct rules which correctly differentiate between sd and sr
    140 # devices.
    141 
    142 if [ -s $DEVTYPES ]
    143 then
    144 	echo "BEGIN	{" >>$GENRULE
    145 	sed -ne '/^ddi_block:cdrom[:	]/s-^[^	 ]*[ 	]\{1,\}\(.*\)$-	cddev["../devices/\1"] = 1;-p' <$DEVTYPES >>$GENRULE
    146 	echo "	}" >>$GENRULE
    147 fi
    148 
    149 cat $RULEBASE >>$GENRULE
    150 
    151 
    152 #
    153 #----------------------------------------------------------------------
    154 #
    155 # Construct sedscr ... a script to massage the output of an 'ls -l'
    156 # of all the special files in the '../devices' directory.
    157 #
    158 # First 3 lines of scr change line to format "maj	min	[b|c]	name
    159 #
    160 cat <<\!EOD >$GENSED
    161 1,$s/^\(.\).*[ 	]\([0-9][0-9]*\), *\([0-9][0-9]*\)[ 	].*[ 	]\([^ 	][^ 	]*\)$/\2	\3	\1	\4/
    162 /:[^	,][^ 	,]*$/s/^\(.*\):\([^	,]*\)$/\1:\2	\2/
    163 /:[^	,][^	,]*,[^ ]*$/s/^\(.*\):\([^	,]*\),\([^ ]*\)$/\1:\2,\3	\2/
    164 !EOD
    165 
    166 # Next lines are generated from the "/etc/name_to_major file; they change the
    167 # "major number" field into its corresponding 'name'.  This is so that
    168 # the difference in major-numbers among different machines can be hidden.
    169 #
    170 nawk -v del='#' '$1 !~ /^#|^$/ { \
    171     num = split($2, maj, del); \
    172     if (num > 1) { printf("/^%s\t/ s/^%s\t/%s\t/\n", maj[1], maj[1], $1) } \
    173     else { printf("/^%s\t/ s/^%s\t/%s\t/\n", $2, $2, $1) } \
    174 } ' /etc/name_to_major >> $GENSED
    175 
    176 #
    177 #----------------------------------------------------------------------
    178 #
    179 # Have finished generating sedscr.  Now we generate 'nawkscr'; first we insert
    180 # the header ...
    181 
    182 cat >$GENAWK <<\!EOD
    183 BEGIN	{
    184 !EOD
    185 
    186 # and then we find all the symbolic-links under /dev, massage the output of
    187 # an 'ls -l' with the sed script we generated above, and then 'nawk' the output
    188 # using the actual link data table script.  This generates the heart of our
    189 # link-creating 'nawk' script.
    190 
    191 echo "Scanning /devices/ directory tree..." >&2
    192 
    193 ls -l `find ../devices \( -type b -o -type c \) -print` |  sed -f $GENSED |\
    194 sort -b +0 -1 +1n -2 +4 -5 | nawk -f $GENRULE >>$GENAWK
    195 
    196 cat >>$GENAWK <<\!EOD
    197 	}
    198 $2 in devname	{
    199 	if (length(devdir[$2]) <= 0)
    200 		next;
    201 	if (devdir[$2] == "./") {
    202 		if ($1 == devname[$2])
    203 			next;
    204 	}
    205 	else if (match($1, "^" devdir[$2] "[^/]*$") == 0)
    206 		next;
    207 
    208 	printf "rm -f %s; ln -s %s %s\n", devname[$2], $1, devname[$2];
    209 	if (length(devextra[$2]) > 0) {
    210 		printf "rm -f %s; ln -s %s %s\n", devextra[$2],
    211 			devname[$2], devextra[$2];
    212 		delete devextra[$2];
    213 	}
    214 	delete devname[$2];
    215 	delete devdir[$2];
    216 	}
    217 END	{
    218 	for (dev in devname) {
    219 		printf "rm -f %s; ln -s %s %s\n", devname[dev],
    220 		   substr(dev, match(dev, "\.\./devices/"), 999),
    221 		   devname[dev];
    222 		if (length(devextra[dev]) > 0)
    223 			printf "rm -f %s; ln -s %s %s\n", devextra[dev],
    224 				devname[dev], devextra[dev];
    225 	}
    226 	}
    227 !EOD
    228 
    229 #
    230 #----------------------------------------------------------------------
    231 #
    232 echo "Scanning /dev/ directory tree..." >&2
    233 
    234 ls -l `find . -type l -print` |\
    235 	sed -e '1,$s/^.* \.\/\([^ ][^ ]*\) -> \([^ ][^ ]*\)$/\1	\2/' |\
    236 	nawk -f $GENAWK |\
    237 	$DOIT_CMD
    238