While you can select base directories for various packages that are guaranteed unique to an architecture and version, this leads to unnecessary levels of directory hierarchy. For example, for a product designed for SPARC and x86 based processors, you could organize the base directories by processor and version as shown below.
Base Directory |
Version and Processor |
---|---|
/opt/SUNWstuf/sparc/1.0 |
Version 1.0, SPARC |
/opt/SUNWstuf/sparc/1.2 |
Version 1.2, SPARC |
/opt/SUNWstuf/x86/1.0 |
Version 1.0, x86 |
This is okay and it does work, but you are treating names and numbers as though they mean something to the administrator. A better approach is to do this automatically after explaining it to the administrator and obtaining permission.
This means that you can do the whole job in the package without requiring the administrator to do it manually. You can assign the base directory arbitrarily and then transparently establish the appropriate client links in a postinstall script. You can also use the pkgadd command to install all or part of the package to the clients in the postinstall script. You can even ask the administrator which users or clients need to know about this package and automatically update PATH environment variables and /etc files. This is completely acceptable as long as whatever the package does upon installation, it undoes upon removal.
You can take advantage of two methods for controlling the base directory at install time. The first is best for new packages that will install only to Solaris 2.5 and compatible releases; it provides very useful data for the administrator and supports multiple installed versions and architectures and requires minimal special work. The second method can be used by any package and makes use of the request script's inherent control over build parameters to ensure successful installations.
The checkinstall script can select the appropriate base directory at install time, which means that the base directory can be placed very low in the directory tree. This example increments the base directory sequentially, leading to directories of the form /opt/SUNWstuf, /opt/SUNWstuf.1, and /opt/SUNWstuf.2. The administrator can use the pkginfo command to determine which architecture and version are installed in each base directory.
If the SUNWstuf package (containing a set of utilities that do stuff) uses this method, its pkginfo and pkgmap files would look like this.
# pkginfo file PKG=SUNWstuf NAME=software stuff ARCH=sparc VERSION=1.0.0,REV=1.0.5 CATEGORY=application DESC=a set of utilities that do stuff BASEDIR=/opt/SUNWstuf VENDOR=Sun Microsystems, Inc. HOTLINE=Please contact your local service provider EMAIL= MAXINST=1000 CLASSES=none daemon PSTAMP=hubert990707141632 |
: 1 1758 1 d none EZstuf 0775 root bin 1 f none EZstuf/dirdel 0555 bin bin 40 773 751310229 1 f none EZstuf/usrdel 0555 bin bin 40 773 751310229 1 f none EZstuf/filedel 0555 bin bin 40 773 751310229 1 d none HRDstuf 0775 root bin 1 f none HRDstuf/mksmart 0555 bin bin 40 773 751310229 1 f none HRDstuf/mktall 0555 bin bin 40 773 751310229 1 f none HRDstuf/mkcute 0555 bin bin 40 773 751310229 1 f none HRDstuf/mkeasy 0555 bin bin 40 773 751310229 1 d none /etc ? ? ? 1 d none /etc/rc2.d ? ? ? 1 f daemon /etc/rc2.d/S70dostuf 0744 root sys 450 223443 1 i pkginfo 348 28411 760740163 1 i postinstall 323 26475 751309908 1 i postremove 402 33179 751309945 1 i preinstall 321 26254 751310019 1 i preremove 320 26114 751309865 1 i i.daemon 509 39560 752978103 1 i r.daemon 320 24573 742152591 |
Assume that the x86 version of SUNWstuf is already installed on the server in /opt/SUNWstuf. When the administrator uses the pkgadd command to install the SPARC version, the request script needs to detect the existence of the x86 version and interact with the administrator regarding the installation.
The base directory could be walked without administrator interaction in a checkinstall script, but if arbitrary operations like this happen too often, administrators lose confidence in the process.
The request script and checkinstall script for a package that handle this situation might look like this.
# request script for SUNWstuf to walk the BASEDIR parameter. PATH=/usr/sadm/bin:${PATH} # use admin utilities GENMSG="The base directory $LOCAL_BASE already contains a \ different architecture or version of $PKG." OLDMSG="If the option \"-a none\" was used, press the \ key and enter an unused base directory when it is requested." OLDPROMPT="Do you want to overwrite this version? " OLDHELP="\"y\" will replace the installed package, \"n\" will \ stop the installation." SUSPEND="Suspending installation at user request using error \ code 1." MSG="This package could be installed at the unused base directory $WRKNG_BASE." PROMPT="Do you want to use to the proposed base directory? " HELP="A response of \"y\" will install to the proposed directory and continue, \"n\" will request a different directory. If the option \"-a none\" was used, press the key and enter an unused base directory when it is requested." DIRPROMPT="Select a preferred base directory ($WRKNG_BASE) " DIRHELP="The package $PKG will be installed at the location entered." NUBD_MSG="The base directory has changed. Be sure to update \ any applicable search paths with the actual location of the \ binaries which are at $WRKNG_BASE/EZstuf and $WRKNG_BASE/HRDstuf." OldSolaris="" Changed="" Suffix="0" # # Determine if this product is actually installed in the working # base directory. # Product_is_present () { if [ -d $WRKNG_BASE/EZstuf -o -d $WRKNG_BASE/HRDstuf ]; then return 1 else return 0 fi } if [ ${BASEDIR} ]; then # This may be an old version of Solaris. In the latest Solaris # CLIENT_BASEDIR won't be defined yet. In older version it is. if [ ${CLIENT_BASEDIR} ]; then LOCAL_BASE=$BASEDIR OldSolaris="true" else # The base directory hasn't been processed yet LOCAL_BASE=${PKG_INSTALL_ROOT}$BASEDIR fi WRKNG_BASE=$LOCAL_BASE # See if the base directory is already in place and walk it if # possible while [ -d ${WRKNG_BASE} -a Product_is_present ]; do # There is a conflict # Is this an update of the same arch & version? if [ ${UPDATE} ]; then exit 0 # It's out of our hands. else # So this is a different architecture or # version than what is already there. # Walk the base directory Suffix=`expr $Suffix + 1` WRKNG_BASE=$LOCAL_BASE.$Suffix Changed="true" fi done # So now we can propose a base directory that isn't claimed by # any of our other versions. if [ $Changed ]; then puttext "$GENMSG" if [ $OldSolaris ]; then puttext "$OLDMSG" result=`ckyorn -Q -d "a" -h "$OLDHELP" -p "$OLDPROMPT"` if [ $result="n" ]; then puttext "$SUSPEND" exit 1 # suspend installation else exit 0 fi else # The latest functionality is available puttext "$MSG" result=`ckyorn -Q -d "a" -h "$HELP" -p "$PROMPT"` if [ $? -eq 3]; then echo quitinstall >> $1 exit 0 fi if [ $result="n" ]; then WRKNG_BASE=`ckpath -ayw -d "$WRKNG_BASE" \ -h "$DIRHELP" -p "$DIRPROMPT"` else if [ $result="a" ] exit 0 fi fi echo "BASEDIR=$WRKNG_BASE" >> $1 puttext "$NUBD_MSG" fi fi exit 0 |
# checkinstall script for SUNWstuf to politely suspend grep quitinstall $1 if [ $? -eq 0 ]; then exit 3 # politely suspend installation fi exit 0 |
This approach would not work very well if the base directory was simply /opt. This package has to call out the BASEDIR more precisely since /opt would be difficult to walk. In fact, depending on the mount scheme, it may not be possible. The example walks the base directory by creating a new directory under /opt, which does not introduce any problems.
This example uses a request script and a checkinstall script even though versions of Solaris prior to the 2.5 release cannot run a checkinstall script. The checkinstall script in this example is used for the purpose of politely halting the installation in response to a private message in the form of the string quitinstall. If this script executes under the Solaris 2.3 release, the checkinstall script is ignored and the request script halts the installation with an error message.
Remember that prior to the Solaris 2.5 and compatible releases, the BASEDIR parameter is a read-only parameter and cannot be changed by the request script. For this reason, if an old version of the SunOS operating system is detected (by testing for a conditioned CLIENT_BASEDIR environment variable), the request script has only two options—continue or quit.
If your software product might be installed on older versions of the SunOS operating system, the request script needs to do all the necessary work. This approach can also be used to manipulate multiple directories. If additional directories are required, they still need to be included under a single base directory in order to provide an easily administrable product. While the BASEDIR parameter does not provide the level of granularity available in the latest Solaris release, your package can still walk the base directory by using the request script to manipulate parametric paths. This is how the pkginfo and pkgmap files might look.
# pkginfo file PKG=SUNWstuf NAME=software stuff ARCH=sparc VERSION=1.0.0,REV=1.0.5 CATEGORY=application DESC=a set of utilities that do stuff BASEDIR=/opt SUBBASE=SUNWstuf VENDOR=Sun Microsystems, Inc. HOTLINE=Please contact your local service provider EMAIL= MAXINST=1000 CLASSES=none daemon PSTAMP=hubert990707141632 |
: 1 1758 1 d none $SUBBASE/EZstuf 0775 root bin 1 f none $SUBBASE/EZstuf/dirdel 0555 bin bin 40 773 751310229 1 f none $SUBBASE/EZstuf/usrdel 0555 bin bin 40 773 751310229 1 f none $SUBBASE/EZstuf/filedel 0555 bin bin 40 773 751310229 1 d none $SUBBASE/HRDstuf 0775 root bin 1 f none $SUBBASE/HRDstuf/mksmart 0555 bin bin 40 773 751310229 1 f none $SUBBASE/HRDstuf/mktall 0555 bin bin 40 773 751310229 1 f none $SUBBASE/HRDstuf/mkcute 0555 bin bin 40 773 751310229 1 f none $SUBBASE/HRDstuf/mkeasy 0555 bin bin 40 773 751310229 1 d none /etc ? ? ? 1 d none /etc/rc2.d ? ? ? 1 f daemon /etc/rc2.d/S70dostuf 0744 root sys 450 223443 1 i pkginfo 348 28411 760740163 1 i postinstall 323 26475 751309908 1 i postremove 402 33179 751309945 1 i preinstall 321 26254 751310019 1 i preremove 320 26114 751309865 1 i i.daemon 509 39560 752978103 1 i r.daemon 320 24573 742152591 |
This example is not perfect. A pkginfo -r command returns /opt for the installation base, which is pretty ambiguous. Many packages are in /opt, but at least it is a meaningful directory. Just like the previous example, this next example fully supports multiple architectures and versions. The request script can be tailored to the needs of the specific package and resolve whatever dependencies are applicable.
# request script for SUNWstuf to walk a parametric path PATH=/usr/sadm/bin:${PATH} # use admin utilities MSG="The target directory $LOCAL_BASE already contains \ different architecture or version of $PKG. This package \ could be installed at the unused target directory $WRKNG_BASE." PROMPT="Do you want to use to the proposed directory? " HELP="A response of \"y\" will install to the proposed directory \ and continue, \"n\" will request a different directory. If \ the option \"-a none\" was used, press the <RETURN> key and \ enter an unused base directory when it is requested." DIRPROMPT="Select a relative target directory under $BASEDIR/" DIRHELP="The package $PKG will be installed at the location entered." SUSPEND="Suspending installation at user request using error \ code 1." NUBD_MSG="The location of this package is not the default. Be \ sure to update any applicable search paths with the actual \ location of the binaries which are at $WRKNG_BASE/EZstuf \ and $WRKNG_BASE/HRDstuf." Changed="" Suffix="0" # # Determine if this product is actually installed in the working # base directory. # Product_is_present () { if [ -d $WRKNG_BASE/EZstuf -o -d $WRKNG_BASE/HRDstuf ]; then return 1 else return 0 fi } if [ ${BASEDIR} ]; then # This may be an old version of Solaris. In the latest Solaris # CLIENT_BASEDIR won't be defined yet. In older versions it is. if [ ${CLIENT_BASEDIR} ]; then LOCAL_BASE=$BASEDIR/$SUBBASE else # The base directory hasn't been processed yet LOCAL_BASE=${PKG_INSTALL_ROOT}$BASEDIR/$SUBBASE fi WRKNG_BASE=$LOCAL_BASE # See if the base directory is already in place and walk it if # possible while [ -d ${WRKNG_BASE} -a Product_is_present ]; do # There is a conflict # Is this an update of the same arch & version? if [ ${UPDATE} ]; then exit 0 # It's out of our hands. else # So this is a different architecture or # version than what is already there. # Walk the base directory Suffix=`expr $Suffix + 1` WRKNG_BASE=$LOCAL_BASE.$Suffix Changed="true" fi done # So now we can propose a base directory that isn't claimed by # any of our other versions. if [ $Changed ]; then puttext "$MSG" result=`ckyorn -Q -d "a" -h "$HELP" -p "$PROMPT"` if [ $? -eq 3 ]; then puttext "$SUSPEND" exit 1 fi if [ $result="n" ]; then WRKNG_BASE=`ckpath -lyw -d "$WRKNG_BASE" -h "$DIRHELP" \ -p "$DIRPROMPT"` elif [ $result="a" ]; then exit 0 else exit 1 fi echo SUBBASE=$SUBBASE.$Suffix >> $1 puttext "$NUBD_MSG" fi fi exit 0 |