1 #!/bin/ksh93 -p 2 # 3 # 4 # CDDL HEADER START 5 # 6 # The contents of this file are subject to the terms of the 7 # Common Development and Distribution License (the "License"). 8 # You may not use this file except in compliance with the License. 9 # 10 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11 # or http://www.opensolaris.org/os/licensing. 12 # See the License for the specific language governing permissions 13 # and limitations under the License. 14 # 15 # When distributing Covered Code, include this CDDL HEADER in each 16 # file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17 # If applicable, add the following below this CDDL HEADER, with the 18 # fields enclosed by brackets "[]" replaced with your own identifying 19 # information: Portions Copyright [yyyy] [name of copyright owner] 20 # 21 # CDDL HEADER END 22 # 23 # 24 # Copyright 2009 Sun Microsystems, Inc. All rights reserved. 25 # Use is subject to license terms. 26 # 27 28 # 29 # pkg2du - convert driver packages to Driver Update (DU) format 30 # 31 32 readonly PROG=$0 33 readonly ORIGPWD=$PWD 34 readonly TMP_DIR=${TMPDIR:-/tmp}/${PROG##*/}.$$ 35 36 # Must-have utilities 37 readonly CPIO=/usr/bin/cpio 38 readonly GZIP=/usr/bin/gzip 39 readonly MKISOFS=/usr/bin/mkisofs 40 readonly PATCHADD=/usr/sbin/patchadd 41 readonly PKGTRANS=/usr/bin/pkgtrans 42 readonly ROOT_ARCHIVE=/usr/sbin/root_archive 43 readonly LOFIADM=/usr/sbin/lofiadm 44 readonly MKDIR=/usr/bin/mkdir 45 readonly RM=/usr/bin/rm 46 readonly CP=/usr/bin/cp 47 readonly HEAD=/usr/bin/head 48 readonly SORT=/usr/bin/sort 49 readonly MKBOOTMEDIA=/usr/bin/mkbootmedia 50 readonly PKG2DU=/usr/bin/pkg2du 51 readonly TOUCH=/usr/bin/touch 52 readonly NAWK=/usr/bin/nawk 53 readonly CHMOD=/usr/bin/chmod 54 readonly GREP=/usr/bin/grep 55 readonly LS=/usr/bin/ls 56 readonly LN=/usr/bin/ln 57 readonly SED=/usr/bin/sed 58 readonly CAT=/usr/bin/cat 59 readonly FIND=/usr/bin/find 60 readonly UNAME=/usr/bin/uname 61 readonly MACH=`$UNAME -p` 62 63 # for gettext 64 TEXTDOMAIN=SUNW_OST_OSCMD 65 export TEXTDOMAIN 66 67 68 function usage 69 { 70 gettext "Usage:\n${PROG##*/} -r <release> [-f] [-v] [-d <dir>] [-o <iso>] [-l <label>]\n <pkg> [<pkg> ...]\n" 71 gettext "Options:\n -d <dir>\n Directory where the Driver Update directory should be created.\n" 72 gettext " -o <iso>\n Create a Solaris ISO image of the Driver Update directory.\n" 73 gettext " -f\n If <dir>/DU or <iso> exists, remove it without asking first.\n" 74 gettext " -l <label>\n Label/volume name of the ISO image (if -o option is specified).\n" 75 gettext " -r <release>\n Solaris release number to use. It takes the form of 5.10.\n This option must be specified.\n" 76 gettext " -v\n Verbose. Multiple -v options increase verbosity.\n" 77 echo; 78 } 79 80 81 function check_prereqs 82 { 83 typeset f 84 85 # We must have these utilities. 86 for f in $GZIP ${ISO:+$MKISOFS} $PKGTRANS 87 do 88 if [[ ! -x "$f" ]] 89 then 90 gettext "Cannot find required utilty $f" 91 exit 1 92 fi 93 done 94 } 95 96 97 function cleanup 98 { 99 $RM -rf "$TMP_DIR" 100 } 101 102 103 function is_overwrite 104 { 105 typeset arg=$1 106 typeset -l ans 107 108 [[ $FORCE == yes ]] && return 0 109 110 while true 111 do 112 gettext "$arg already exists. Overwrite it? (y/n) " 113 read ans 114 case $ans in 115 y*|Y*) return 0 ;; # go ahead overwrite 116 n*|N*) return 1 ;; # don't overwrite 117 esac 118 done 119 echo; 120 } 121 122 123 function collect_objs # <pkg> ... 124 { 125 typeset obj fail=0 126 127 for obj 128 do 129 if [[ -f "$obj"/pkginfo ]] 130 then 131 PACKAGES[ ${#PACKAGES[*]} ]=$obj 132 else 133 gettext "$obj is not in package format\n" 134 (( fail += 1 )) 135 fi 136 done 137 (( fail )) && return 1 138 return 0 139 } 140 141 142 function mkdu 143 { 144 typeset distdir tmpdudir pkgs obj statusfile 145 146 trap '/bin/rm -rf $statusfile $tmpdudir' EXIT 147 148 # Create DU directory first. 149 distdir=$ROOTDIR/DU/sol_$VERSION/$MACH 150 $MKDIR -p "$distdir/Tools" "$distdir/Product" 151 152 # to the other UltraSPARC architecture 153 if [[ "$MACH" != "i386" ]] 154 then 155 cd $ROOTDIR/DU/sol_$VERSION 156 $LN -s sparc sun4v 157 $LN -s sparc sun4u 158 else 159 cd $ROOTDIR/DU/sol_$VERSION 160 $LN -s i386 i86pc 161 fi 162 163 # Unfortunately pkgtrans insists that all packages must be in 164 # <device1> (see pkgtrans(1)). The packages can't have any path 165 # components. So we'll create a temporary directory first and then 166 # symlinks to the specified packages. Then run pkgtrans with 167 # the temporary directory as <device1>. 168 tmpdudir=$TMP_DIR/mkdu 169 $MKDIR -p "$tmpdudir" 170 171 for obj in "${PACKAGES[@]}" 172 do 173 # Get rid of trailing /'s, if any. 174 [[ "$obj" == */ ]] && obj=${obj%%+(/)} 175 176 # Make sure it's a full pathname. 177 [[ "$obj" != /* ]] && obj=$ORIGPWD/$obj 178 179 $LN -s "$obj" "$tmpdudir" || exit 1 180 181 # Remember just the file component. 182 pkgs[ ${#pkgs[*]} ]=${obj##*/} 183 done 184 185 # Package up packages as compressed data stream. 186 statusfile=$TMP_DIR/.pkgtrans.status 187 { 188 $PKGTRANS -s "$tmpdudir" /dev/stdout "${pkgs[@]}" 189 echo $? > $statusfile 190 $TOUCH $statusfile # make sure file is created 191 } | $GZIP -9 > "$distdir/Product/pkgs.gz" 192 193 [[ -s $statusfile && $(<$statusfile) != 0 ]] && return 1 194 195 # Create admin file for pkgadd 196 $CAT > "$distdir/Tools/admin" <<"EOF" 197 mail= 198 instance=unique 199 partial=nocheck 200 runlevel=nocheck 201 idepend=nocheck 202 rdepend=nocheck 203 space=nocheck 204 setuid=nocheck 205 conflict=nocheck 206 action=nocheck 207 EOF 208 209 # Create install.sh 210 $CAT > "$distdir/Tools/install.sh" <<"EOF" 211 #!/sbin/sh 212 # install.sh -R <basedir> - install packages to basedir 213 basedir=/ 214 toolsdir=`dirname $0` 215 tmpfile=/tmp/`basename $0`.$$ 216 while getopts "R:" arg 217 do 218 case "$arg" in 219 R) basedir=$OPTARG;; 220 esac 221 done 222 /usr/bin/gzip -c -d "$toolsdir/../Product/pkgs.gz" > $tmpfile && 223 /usr/sbin/pkgadd -R "$basedir" -d "$tmpfile" -a "$toolsdir/admin" all 224 status=$? 225 /bin/rm -f "$tmpfile" 226 exit $status 227 EOF 228 $CHMOD a+rx "$distdir/Tools/install.sh" 229 } 230 231 232 function mkiso 233 { 234 typeset vflag 235 236 # Skip if no ISO image was specified. 237 [[ -z "$ISO" ]] && return 0 238 239 # Determine mkisofs' verbose flag depending on $VERBOSE_LEVEL. 240 case $VERBOSE_LEVEL in 241 0) vflag=-quiet 242 ;; 243 1) vflag= # mkisofs' default verboseness 244 ;; 245 *) vflag= 246 i=$VERBOSE_LEVEL 247 while ((i > 0)) 248 do 249 vflag="-v $vflag" 250 (( i -= 1 )) 251 done 252 ;; 253 esac 254 255 (( VERBOSE_LEVEL )) && gettext "Creating ISO image ..." 256 257 # Note: the "-log-file >(cat -u >&2)" and "2>/dev/null" below is a 258 # trick to filter out mkisofs's warning message about being 259 # non-conforming to ISO-9660. 260 # We do some funky architecture-specific stuff here so that we can 261 # actually create a bootable media image for UltraSPARC systems 262 263 ISOARGS_sparc="-B ... -joliet-long -R -U" 264 ISOARGS_i386="-d -N -r -relaxed-filenames" 265 if [[ "$MACH" = "i386" ]] 266 then 267 ISOARGS=$ISOARGS_i386 268 else 269 ISOARGS=$ISOARGS_sparc 270 fi 271 272 $MKISOFS -o "$ISO" \ 273 -allow-leading-dots \ 274 $ISOARGS \ 275 -ldots -full-iso9660-filenames \ 276 -R -J \ 277 -V "$ISOLABEL" \ 278 $vflag \ 279 -log-file >($CAT -u >&2) \ 280 "$ROOTDIR" 2>/dev/null 281 } 282 283 284 # 285 # Main 286 # 287 trap cleanup EXIT 288 289 FORCE= 290 ISO= 291 LABEL= 292 RELEASE= 293 ROOTDIR= 294 VERBOSE_LEVEL=0 295 296 while getopts ':d:fo:l:r:v' opt 297 do 298 case $opt in 299 d) ROOTDIR=$OPTARG 300 ;; 301 f) FORCE=yes 302 ;; 303 o) ISO=$OPTARG 304 if [ ! -z `echo $ISO | $GREP "^/tmp"` ]; then 305 gettext "ISO images will not be created on /tmp.\n" 306 gettext "Please choose a different output location.\n" 307 exit 3 308 fi 309 ;; 310 l) LABEL=$OPTARG 311 ;; 312 r) RELEASE=$OPTARG 313 ;; 314 v) (( VERBOSE_LEVEL += 1 )) 315 ;; 316 :) gettext "Option -$OPTARG missing argument." 317 usage 318 exit 1 319 ;; 320 *) gettext "Option -$OPTARG invalid.\n" 321 usage 322 exit 2 323 ;; 324 esac 325 done 326 shift 'OPTIND - 1' 327 328 # Release number must be specified. 329 if [[ -z "$RELEASE" ]] 330 then 331 gettext "Solaris release number must be specified (-r option).\n" 332 usage 333 exit 1 334 fi 335 336 # Verify release number. Allow major.minor or major.minor.micro format. 337 if [[ $RELEASE != +([0-9]).+([0-9])?(.+([0-9])) ]] 338 then 339 gettext "Invalid release number: $RELEASE\n" 340 exit 1 341 fi 342 VERSION=$(echo $RELEASE | $SED 's/5\./2/') 343 344 # Either or both of -d or -o option must be specified. 345 if [[ -z "$ROOTDIR" && -z "$ISO" ]] 346 then 347 gettext "Either -d or -o option (or both) must be specified.\n" 348 usage 349 exit 1 350 fi 351 352 # There must be at least one package. 353 if (( $# == 0 )) 354 then 355 gettext "No package was specified.\n" 356 usage 357 exit 1 358 fi 359 360 # Check and collect packages 361 unset PACKAGES 362 collect_objs "$@" || exit 1 363 364 # Default label for ISO image 365 LABEL=${LABEL:-DU sol_$VERSION} 366 367 check_prereqs # must be called after $ISO is possibly set 368 369 # If an ISO image was specified, check its parent directory and get its 370 # full pathname. 371 unset ISODIR 372 if [[ -n "$ISO" ]] 373 then 374 if [[ "$ISO" = */* ]] 375 then 376 ISODIR=$(cd "${ISO%/*}" 2>/dev/null && pwd -P) 377 if (( $? )) 378 then 379 gettext "Can't access parent directory of ISO image\n" 380 exit 1 381 fi 382 else 383 ISODIR=$(pwd -P) 384 fi 385 fi 386 387 # If user specified a media root directory, verify it exists, else use 388 # a temporary directory. 389 if [[ -n "$ROOTDIR" ]] 390 then 391 $MKDIR -p "$ROOTDIR"; 392 if [ $? != 0 ]; then 393 gettext "$ROOTDIR is not a directory.\n" 394 exit 1 395 elif [[ ! -w "$ROOTDIR" ]] then 396 gettext "Directory $ROOTDIR is not writable.\n" 397 exit 1 398 fi 399 # If an ISO image path is also specified, make sure it's not under 400 # $ROOTDIR since we're going to take the ISO image of $ROOTDIR. 401 if [[ -n "$ISODIR" ]] 402 then 403 realroot=$(cd "$ROOTDIR" 2>/dev/null && pwd -P) 404 if [[ "$ISODIR" = "$realroot"?(/*) ]] 405 then 406 gettext "ISO image must not be under Driver Update's parent directory ($realroot)\n" 407 exit 1 408 fi 409 fi 410 else 411 ROOTDIR=$TMP_DIR/root 412 fi 413 414 # If DU directory already exists, ask user permission to remove it unless -f 415 # option was specified. 416 if [[ -d "$ROOTDIR/DU" ]] 417 then 418 is_overwrite "$ROOTDIR/DU" || exit 0 419 $RM -rf "$ROOTDIR/DU" 420 fi 421 422 # If ISO image already exists, ask user permission to remove it unless -f 423 # option was specified. 424 if [[ -f "$ISO" ]] 425 then 426 is_overwrite "$ISO" || exit 0 427 $RM -f "$ISO" 428 fi 429 430 # Create DU directory and the ISO image (if requested). 431 mkdu && mkiso 432 if (( $? )) 433 then 434 $RM -rf "$ROOTDIR/DU" 435 [[ -n "$ISO" ]] && $RM -f "$ISO" 436 exit 1 437 fi 438 exit 0