Accommodating Relocation
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.
Walking Base Directories
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.
Using the BASEDIR Parameter
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.
The pkginfo File
# 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
The pkgmap File
: 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
Example—Analysis Scripts That Walk a BASEDIR
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.
Note - 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.
The request Script
# 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
The checkinstall Script
# 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.
Using Relative Parametric Paths
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.
The pkginfo File
# 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
The pkgmap File
: 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.
Example—A request Script That Walks a Relative Parametric Path
# 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