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 32readonly PROG=$0 33readonly ORIGPWD=$PWD 34readonly TMP_DIR=${TMPDIR:-/tmp}/${PROG##*/}.$$ 35 36# Must-have utilities 37readonly CPIO=/usr/bin/cpio 38readonly GZIP=/usr/bin/gzip 39readonly MKISOFS=/usr/bin/mkisofs 40readonly PATCHADD=/usr/sbin/patchadd 41readonly PKGTRANS=/usr/bin/pkgtrans 42readonly ROOT_ARCHIVE=/usr/sbin/root_archive 43readonly LOFIADM=/usr/sbin/lofiadm 44readonly MKDIR=/usr/bin/mkdir 45readonly RM=/usr/bin/rm 46readonly CP=/usr/bin/cp 47readonly HEAD=/usr/bin/head 48readonly SORT=/usr/bin/sort 49readonly MKBOOTMEDIA=/usr/bin/mkbootmedia 50readonly PKG2DU=/usr/bin/pkg2du 51readonly TOUCH=/usr/bin/touch 52readonly NAWK=/usr/bin/nawk 53readonly CHMOD=/usr/bin/chmod 54readonly GREP=/usr/bin/grep 55readonly LS=/usr/bin/ls 56readonly LN=/usr/bin/ln 57readonly SED=/usr/bin/sed 58readonly CAT=/usr/bin/cat 59readonly FIND=/usr/bin/find 60readonly UNAME=/usr/bin/uname 61readonly MACH=`$UNAME -p` 62 63# for gettext 64TEXTDOMAIN=SUNW_OST_OSCMD 65export TEXTDOMAIN 66 67 68function 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 81function 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 97function cleanup 98{ 99 $RM -rf "$TMP_DIR" 100} 101 102 103function 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 123function 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 142function 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" 197mail= 198instance=unique 199partial=nocheck 200runlevel=nocheck 201idepend=nocheck 202rdepend=nocheck 203space=nocheck 204setuid=nocheck 205conflict=nocheck 206action=nocheck 207EOF 208 209 # Create install.sh 210 $CAT > "$distdir/Tools/install.sh" <<"EOF" 211#!/sbin/sh 212# install.sh -R <basedir> - install packages to basedir 213basedir=/ 214toolsdir=`dirname $0` 215tmpfile=/tmp/`basename $0`.$$ 216while getopts "R:" arg 217do 218 case "$arg" in 219 R) basedir=$OPTARG;; 220 esac 221done 222/usr/bin/gzip -c -d "$toolsdir/../Product/pkgs.gz" > $tmpfile && 223 /usr/sbin/pkgadd -R "$basedir" -d "$tmpfile" -a "$toolsdir/admin" all 224status=$? 225/bin/rm -f "$tmpfile" 226exit $status 227EOF 228 $CHMOD a+rx "$distdir/Tools/install.sh" 229} 230 231 232function 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# 287trap cleanup EXIT 288 289FORCE= 290ISO= 291LABEL= 292RELEASE= 293ROOTDIR= 294VERBOSE_LEVEL=0 295 296while getopts ':d:fo:l:r:v' opt 297do 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 325done 326shift 'OPTIND - 1' 327 328# Release number must be specified. 329if [[ -z "$RELEASE" ]] 330then 331 gettext "Solaris release number must be specified (-r option).\n" 332 usage 333 exit 1 334fi 335 336# Verify release number. Allow major.minor or major.minor.micro format. 337if [[ $RELEASE != +([0-9]).+([0-9])?(.+([0-9])) ]] 338then 339 gettext "Invalid release number: $RELEASE\n" 340 exit 1 341fi 342VERSION=$(echo $RELEASE | $SED 's/5\./2/') 343 344# Either or both of -d or -o option must be specified. 345if [[ -z "$ROOTDIR" && -z "$ISO" ]] 346then 347 gettext "Either -d or -o option (or both) must be specified.\n" 348 usage 349 exit 1 350fi 351 352# There must be at least one package. 353if (( $# == 0 )) 354then 355 gettext "No package was specified.\n" 356 usage 357 exit 1 358fi 359 360# Check and collect packages 361unset PACKAGES 362collect_objs "$@" || exit 1 363 364# Default label for ISO image 365LABEL=${LABEL:-DU sol_$VERSION} 366 367check_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. 371unset ISODIR 372if [[ -n "$ISO" ]] 373then 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 385fi 386 387# If user specified a media root directory, verify it exists, else use 388# a temporary directory. 389if [[ -n "$ROOTDIR" ]] 390then 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 410else 411 ROOTDIR=$TMP_DIR/root 412fi 413 414# If DU directory already exists, ask user permission to remove it unless -f 415# option was specified. 416if [[ -d "$ROOTDIR/DU" ]] 417then 418 is_overwrite "$ROOTDIR/DU" || exit 0 419 $RM -rf "$ROOTDIR/DU" 420fi 421 422# If ISO image already exists, ask user permission to remove it unless -f 423# option was specified. 424if [[ -f "$ISO" ]] 425then 426 is_overwrite "$ISO" || exit 0 427 $RM -f "$ISO" 428fi 429 430# Create DU directory and the ISO image (if requested). 431mkdu && mkiso 432if (( $? )) 433then 434 $RM -rf "$ROOTDIR/DU" 435 [[ -n "$ISO" ]] && $RM -f "$ISO" 436 exit 1 437fi 438exit 0 439