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