4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2017 Peter Tribble.
27 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
30 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
31 /* All Rights Reserved */
35 * Program: pkgadd / pkgask
37 * Function: public command and private utility functions that
38 * implement the package add and package ask operations.
52 #include <sys/types.h>
65 * consolidation pkg command library includes
69 #include <instzones_api.h>
72 * local pkg command library includes
81 * pkgadd local includes
87 * imported global variables/functions
91 extern int preinstall_verify(char **a_pkgList
, zoneList_t a_zlst
,
95 * ckquit is a global that controls 'ckyorn' (defined in libadm)
96 * If ckquit is non-zero, then "quit" is allowed as an answer when
97 * ckyorn is called. If is it zero, then "quit" is not an allowed answer.
102 * exported global variables
105 /* these globals are set by ckreturn and used by quit.c */
107 int admnflag
= 0; /* != 0 if any pkg op admin setting failure (4) */
108 int doreboot
= 0; /* != 0 if reboot required after installation */
109 int failflag
= 0; /* != 0 if fatal error has occurred (1) */
110 int intrflag
= 0; /* != 0 if user selected quit (3) */
111 int ireboot
= 0; /* != 0 if immediate reboot required */
112 int nullflag
= 0; /* != 0 if admin interaction required (5) */
113 int warnflag
= 0; /* != 0 if non-fatal error has occurred (2) */
115 /* imported by quit.c */
116 int npkgs
= 0; /* the number of packages yet to be installed */
118 /* imported by various (many) */
119 char *respfile
= NULL
; /* response pathname (or NULL) */
120 char *tmpdir
= NULL
; /* location to place temporary files */
122 struct admin adm
; /* holds info about installation admin */
123 struct pkgdev pkgdev
; /* holds info about the installation device */
126 * internal global variables
129 static char *admnfile
= NULL
; /* file to use for installation admin */
130 static char *ids_name
= NULL
; /* name of data stream device */
131 static char *pkgcontsrc
= NULL
; /* continuation file (-c option) */
132 static char *pkgdrtarg
= NULL
; /* dry run file (-D option) */
133 static char *pkginst
= NULL
; /* current pkg/src instance 2 process */
134 static char *respdir
= NULL
; /* respfile is a directory spec */
135 static char *rw_block_size
= NULL
;
136 static char *vfstab_file
= NULL
;
137 static int askflag
= 0; /* non-zero if invoked as "pkgask" */
138 static int disableAttributes
= 0; /* Disabling attribute checking */
139 static int disableChecksum
= 0; /* Disable checksumming */
140 static int disableSaveSpool
= 0; /* Disable partial spool dir create */
141 static int init_install
= 0; /* inform scripts initial install */
142 static int no_map_client
= 0; /* do not map from vfstab file */
143 static int nointeract
= 0; /* non-zero - no user interaction */
144 static int pkgverbose
= 0; /* non-zero if verbose mode selected */
145 static int saveSpoolInstall
= 0; /* installing from save spool dir */
146 static int suppressCopyright
= 0; /* suppress copyright notices */
148 /* set by ckreturn() */
150 static int interrupted
= 0; /* last pkg op was quit (1,2,3,4,5) */
151 static int needconsult
= 0; /* essential ask admin now (1,2,3,5) */
153 /* Set by -O nozones: do not process any zones */
155 static boolean_t noZones
= B_FALSE
;
157 /* Set by -O zonelist=<names...>: process only named zones */
159 static boolean_t usedZoneList
= B_FALSE
;
161 /* Set by -O debug: debug output is enabled? */
163 static boolean_t debugFlag
= B_FALSE
;
165 /* Set by the -G option: install packages in global zone only */
167 static boolean_t globalZoneOnly
= B_FALSE
;
170 * Assume the package is ABI and POSIX compliant as regards user
171 * interactiion during procedure scripts.
174 static int old_pkg
= 0;
176 /* Assume pkg should be installed according to the ABI */
178 static int old_symlinks
= 0;
181 * Default name length will be 32 chars - if this is set,
182 * disable the 32 char name limit extension
185 static int ABI_namelength
= 0;
187 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
188 #define TEXT_DOMAIN "SYS_TEST"
191 /* printable string - if string is null results in ??? */
193 #define PSTR(STR) (((STR) == (char *)NULL) ? "???" : (STR))
198 * forward declarations
201 static int boot_and_pkginstall_check_in_zones(zoneList_t a_zlst
,
202 char *a_idsName
, char *a_altBinDir
,
203 char *a_zoneAdminFile
, char *a_zoneTempDir
);
204 static int boot_and_install_in_zones(zoneList_t a_zlst
,
205 char *a_idsName
, char *a_altBinDir
,
206 char *a_zoneAdminFile
, char *a_zoneTempDir
);
207 static void pkginstall_check_in_one_zone(char *a_zoneName
,
208 char *a_idsName
, char *a_zoneAdminFile
,
209 char *a_zoneTempDir
, char *a_altBinDir
,
210 char *a_scratchName
, zone_state_t a_zoneState
,
212 static void ckreturn(int retcode
);
213 static void create_zone_adminfile(char **r_zoneAdminFile
,
214 char *a_zoneTempDir
, char *a_admnfile
);
215 static void create_zone_tempdir(char **r_zoneTempDir
,
217 static void install_in_one_zone(char *a_zoneName
, char *a_idsName
,
218 char *a_zoneAdminFile
, char *a_zoneTempDir
,
219 char *a_altBinDir
, zone_state_t a_zoneState
,
221 static int pkginstall_check_in_zones(zoneList_t a_zlst
,
222 char *a_idsName
, char *a_altBinDir
,
223 char *a_zoneAdminFile
, char *a_zoneTempDir
);
224 static int install_in_zones(zoneList_t a_zlst
, char *a_idsName
,
225 char *a_altBinDir
, char *a_zoneAdminFile
,
226 char *a_zoneTempDir
);
227 static int pkgInstall(char *ir
, char *a_idsName
, char *a_pkgDir
,
229 static int pkgZoneCheckInstall(char *a_zoneName
,
230 zone_state_t a_zoneState
,
231 char *a_idsName
, char *a_altBinDir
,
232 char *a_adminFile
, char *a_stdoutPath
,
234 static int pkgZoneInstall(char *a_zoneName
,
235 zone_state_t a_zoneState
,
236 char *a_idsName
, char *a_altBinDir
,
237 char *a_adminFile
, boolean_t a_tmpzn
);
238 static void resetreturn();
239 static void usage(void);
240 static boolean_t
add_packages(char **a_pkgList
,
241 char *a_idsName
, int a_repeat
,
242 char *a_altBinDir
, char *a_device
,
243 boolean_t a_noZones
);
244 static boolean_t
add_packages_in_global_no_zones(char **a_pkgList
,
245 char *a_idsName
, int a_repeat
,
246 char *a_altBinDir
, char *a_device
);
247 static boolean_t
add_packages_in_global_with_zones(char **a_pkgList
,
248 char *a_idsName
, int a_repeat
,
249 char *a_altBinDir
, char *a_device
,
251 static boolean_t
add_packages_in_nonglobal_zone(char **a_pkgList
,
252 char *a_idsName
, int a_repeat
,
253 char *a_altBinDir
, char *a_device
);
254 static boolean_t
check_applicability(char *a_packageDir
,
255 char *a_pkgInst
, char *a_rootPath
,
257 static boolean_t
get_package_list(char ***r_pkgList
, char **a_argv
,
258 char *a_categories
, char **a_categoryList
,
259 char *a_idsName
, int *r_repeat
);
260 static boolean_t
continue_installation(void);
261 static boolean_t
unpack_and_check_packages(char **a_pkgList
,
262 char *a_idsName
, char *a_packageDir
);
264 * *****************************************************************************
265 * global external (public) functions
266 * *****************************************************************************
271 * Description: main entry point for pkgadd/pkgask
273 * 0 Successful completion
278 * 5 Administration. Interaction is required. Do not use pkgadd -n.
279 * In addition, one of the following values may be added to the previous value
281 * 10 Reboot after installation of all packages.
282 * 20 Reboot after installation of this package.
283 * For example, "14" would indicate both "administration" and "reboot after
284 * installation of all packages".
288 main(int argc
, char **argv
)
290 char **category
= NULL
;
292 char *altBinDir
= (char *)NULL
;
293 char *catg_arg
= NULL
;
294 char *device
= NULL
; /* dev pkg stored on */
298 char *prog_full_name
= NULL
;
299 char *spoolDir
= NULL
; /* specified with -s */
300 char Rpath
[PATH_MAX
+1] = {'\0'};
304 struct sigaction nact
;
305 struct sigaction oact
;
307 /* initialize locale environment */
309 (void) setlocale(LC_ALL
, "");
310 (void) textdomain(TEXT_DOMAIN
);
312 /* initialize program name */
314 prog_full_name
= argv
[0];
315 prog
= set_prog_name(argv
[0]);
317 /* tell spmi zones interface how to access package output functions */
319 z_set_output_functions(echo
, echoDebug
, progerr
);
321 askflag
= (strcmp(prog
, "pkgask") == 0);
327 /* tell quit which ckreturn function to call */
329 quitSetCkreturnFunc(&ckreturn
);
331 /* initially no source "device" */
335 /* reset npkgs (used as pkg remaining count in quit.c) */
339 if (z_running_in_global_zone() && !enable_local_fs()) {
340 progerr(ERR_CANNOT_ENABLE_LOCAL_FS
);
343 pkgserversetmode(DEFAULTMODE
);
346 * ********************************************************************
347 * parse command line options
348 * ********************************************************************
351 while ((c
= getopt(argc
, argv
,
352 "?Aa:b:B:Cc:D:d:GhIMnO:R:r:Ss:tV:vY:zZ")) != EOF
) {
356 * Not a public interface: This disables attribute checking.
357 * It speeds up installation a little bit.
364 * Public interface: Define an installation administration
365 * file, admin, to be used in place of the default
366 * administration file. The token none overrides the use
367 * of any admin file, and thus forces interaction with the
368 * user. Unless a full path name is given, pkgadd first
369 * looks in the current working directory for the
370 * administration file. If the specified administration
371 * file is not in the current working directory, pkgadd
372 * looks in the /var/sadm/install/admin directory for the
373 * administration file.
376 admnfile
= flex_device(optarg
, 0);
380 * Not a public interface: control block size given to
381 * pkginstall - block size used in read()/write() loop;
382 * default is st_blksize from stat() of source file.
385 if (optarg
[0] == '-') {
389 rw_block_size
= optarg
;
393 * Not a public interface: location where package executables
394 * can be found - default is /usr/sadm/install/bin.
397 if (optarg
[0] == '-') {
401 if (!path_valid(optarg
)) {
402 progerr(ERR_PATH
, optarg
);
405 if (isdir(optarg
) != 0) {
407 progerr(ERR_CANNOT_USE_DIR
, optarg
, p
);
414 * Not a public interface: This disables checksum tests on
415 * the source files. It speeds up installation a little bit.
422 * Not a public interface: This allows designation of a
423 * continuation file. It is the same format as a dryrun file
424 * but it is used to take up where the dryrun left off.
427 pkgcontsrc
= flex_device(optarg
, 0);
431 * Not a public interface: This allows designation of a
432 * dryrun file. This pkgadd will create dryrun files
433 * in the directory provided.
436 if (optarg
[0] == '-') {
440 pkgdrtarg
= flex_device(optarg
, 0);
444 * Public interface: Install or copy a package from
445 * device. device can be a full path name to a directory
446 * or the identifiers for tape, floppy disk, or removable
447 * disk - for example, /var/tmp or /floppy/floppy_name.
448 * It can also be a device alias - for example,
449 * /floppy/floppy0, or a datastream created by pkgtrans.
452 if (optarg
[0] == '-') {
456 if (!path_valid(optarg
)) {
457 progerr(ERR_PATH
, optarg
);
462 device
= flex_device(optarg
, 1);
466 * Public interface: install package in global zone only.
469 globalZoneOnly
= B_TRUE
;
473 * Not a public interface: Enable hollow package support. When
474 * specified, for any package that has SUNW_PKG_HOLLOW=true:
475 * Do not calculate and verify package size against target.
476 * Do not run any package procedure or class action scripts.
477 * Do not create any target directories.
478 * Do not perform any script locking.
479 * Do not install any components of any package.
480 * Do not output any status or database update messages.
483 set_depend_pkginfo_DB(B_TRUE
);
487 * Not a public interface: Informs scripts that this is
488 * an initial install by setting the environment parameter
489 * PKG_INIT_INSTALL=TRUE for all scripts. They may use it as
490 * they see fit, safe in the knowledge that the target
491 * filesystem is tabula rasa.
498 * Public interface: Instruct pkgadd not to use the
499 * $root_path/etc/vfstab file for determining the client's
500 * mount points. This option assumes the mount points are
501 * correct on the server and it behaves consistently with
502 * Solaris 2.5 and earlier releases.
509 * Not a public interface: the -O option allows the behavior
510 * of the package tools to be modified. Recognized options:
512 * ---> enable debugging output
514 * ---> add zone name to appropriate messages
516 * ---> act as though in global zone with no non-global zones
517 * -> enable-hollow-package-support
518 * ---> Enable hollow package support. When specified, for any
519 * ---> package that has SUNW_PKG_HOLLOW=true:
520 * ---> Do not calculate and verify package size against target
521 * ---> Do not run any package procedure or class action scripts
522 * ---> Do not create any target directories
523 * ---> Do not perform any script locking
524 * ---> Do not install any components of any package
525 * ---> Do not output any status or database update messages
526 * -> zonelist="<names...>"
527 * ---> add package to space/colon separated list of zones only
531 for (p
= strtok(optarg
, ","); p
!= (char *)NULL
;
532 p
= strtok(NULL
, ",")) {
534 if (strcmp(p
, "debug") == 0) {
535 /* set debug flag/enable debug output */
537 (void) echoDebugSetFlag(debugFlag
);
539 /* debug info on arguments to pkgadd */
540 for (n
= 0; n
< argc
&& argv
[n
]; n
++) {
541 echoDebug(DBG_ARG
, n
, argv
[n
]);
548 "enable-hollow-package-support") == 0) {
549 set_depend_pkginfo_DB(B_TRUE
);
553 if (strcmp(p
, "addzonename") == 0) {
554 quitSetZoneName(z_get_zonename());
558 if (strcmp(p
, "nozones") == 0) {
563 if (strncmp(p
, "zonelist=", 9) == 0) {
565 * If colons used as separators,
576 if (z_set_zone_spec(p
+ 9) == -1)
578 usedZoneList
= B_TRUE
;
582 progerr(ERR_INVALID_O_OPTION
, p
);
588 * Public interface: installation occurs in
589 * non-interactive mode. Suppress output of the list of
590 * installed files. The default mode is interactive.
594 (void) echoSetFlag(B_FALSE
);
598 * Public interface: Define the full path name of a
599 * directory to use as the root_path. All files,
600 * including package system information files, are
601 * relocated to a directory tree starting in the specified
602 * root_path. The root_path may be specified when
603 * installing to a client from a server (for example,
604 * /export/root/client1).
607 if (optarg
[0] == '-') {
611 /* determine the real path specified */
613 n
= resolvepath(optarg
, Rpath
, sizeof (Rpath
)-1);
615 /* use supplied path if not resolvable */
618 (void) strlcpy(Rpath
, optarg
, sizeof (Rpath
));
620 /* null terminate string */
624 /* set the alternative root path */
626 if (!set_inst_root(Rpath
)) {
627 progerr(ERR_ROOT_CMD
);
633 * Public interface: Identify a file or directory which
634 * contains output from a previous pkgask(1M)
635 * session. This file supplies the interaction responses
636 * that would be requested by the package in interactive
637 * mode. response must be a full pathname.
640 if (optarg
[0] == '-') {
644 respfile
= flex_device(optarg
, 2);
645 if (isdir(respfile
) == 0)
650 * Not a public interface: suppress copyright notice being
651 * output during installation.
658 * Public interface: Write the package into the directory
659 * spool instead of installing it. The default directory
660 * for spooled packages is /var/sadm/pkg.
663 spoolDir
= flex_device(optarg
, 1);
667 * Not a public interface: disable save spool area creation;
668 * suppress the creation and population of the package save
669 * spool area (var/sadm/pkg/PKG/save/pspool/PKG).
676 * Public interface: Specify an alternative fs_file to map
677 * the client's file systems. For example, used in
678 * situations where the $root_path/etc/vfstab file is
679 * non-existent or unreliable. Informs the pkginstall
680 * portion to mount up a client filesystem based upon the
681 * supplied vfstab-like file of stable format.
684 vfstab_file
= flex_device(optarg
, 2);
689 * Public interface: Trace all of the scripts that get
690 * executed by pkgadd, located in the pkginst/install
691 * directory. This option is used for debugging the
692 * procedural and non-procedural scripts
699 * Public interface: Install packages based on the value
700 * of the CATEGORY parameter stored in the package's
701 * pkginfo(4) file. All packages on the source medium
702 * whose CATEGORY matches one of the specified categories
703 * will be selected for installation or spooling. Install
704 * packages that contain the same CATEGORY as the one
705 * provided on the command line.
708 if (optarg
[0] == '-') {
712 catg_arg
= strdup(optarg
);
714 if ((category
= get_categories(catg_arg
)) == NULL
) {
715 progerr(ERR_CAT_INV
, catg_arg
);
717 } else if (is_not_valid_length(category
)) {
718 progerr(ERR_CAT_LNGTH
);
724 * Not a public interface: perform fresh install from
725 * package save spool area. When set, the package contents
726 * are installed from the package spool save area instead
727 * of from the package root area, so that the original
728 * source packages are not required to install the
729 * package. If the -h option is also specified and the
730 * package is hollow, then this option is ignored. When -z
732 * - Editable files are installed from the package instance
734 * - Volatile files are installed from the package instance
736 * - Executable and data files are installed from the final
737 * installed location as specified in the pkgmap file.
738 * - Installation scripts are run from the package spool
746 * unrecognized option
756 * ********************************************************************
757 * validate command line options
758 * ********************************************************************
761 /* set "debug echo" flag according to setting of "-O debug" option */
763 (void) echoDebugSetFlag(debugFlag
);
765 /* output entry debugging information */
767 if (z_running_in_global_zone()) {
768 echoDebug(DBG_ENTRY_IN_GZ
, prog_full_name
);
770 echoDebug(DBG_ENTRY_IN_LZ
, prog_full_name
, getzoneid(),
775 * Later, it may be decided to pursue this ability to continue to an
776 * actual installation based only on the dryrun data. At this time,
780 if (pkgcontsrc
&& !pkgdrtarg
) {
781 progerr(ERR_NO_LIVE_MODE
);
786 /* ignore -G option if not used in the global zone */
788 if (!z_running_in_global_zone()) {
789 globalZoneOnly
= B_FALSE
;
792 /* if zonelist used, must be in global zone */
794 if (usedZoneList
&& !z_running_in_global_zone()) {
795 progerr(ERR_Z_USED_IN_NONGLOBAL_ZONE
);
799 /* -G and zonelist cannot be used together */
801 if (globalZoneOnly
&& usedZoneList
) {
802 progerr(ERR_GZ_USED_TOGETHER
);
807 /* -s cannot be used with either -G or zonelist */
809 if (spoolDir
!= NULL
) {
810 if (globalZoneOnly
) {
811 progerr(ERR_SPOOLDIR_USED_WITH_G
);
816 progerr(ERR_SPOOLDIR_USED_WITH_Z
);
820 if (strcmp(spoolDir
, "/var/sadm/pkg") == 0) {
821 progerr(ERR_SPOOLDIR_CANNOT_BE_SYS
, "/var/sadm/pkg");
827 /* pkgask does not support the same options as pkgadd */
829 if (askflag
&& spoolDir
) {
830 progerr(ERR_PKGASK_AND_SPOOLDIR
);
835 if (askflag
&& nointeract
) {
836 progerr(ERR_PKGASK_AND_NOINTERACT
);
841 /* cannot use response file/not-interactive and spool-to directory */
843 if (spoolDir
&& nointeract
) {
844 progerr(ERR_SPOOLDIR_AND_NOINTERACT
);
849 if (spoolDir
&& respfile
) {
850 progerr(ERR_SPOOLDIR_AND_RESPFILE
);
856 /* Verify supplied zone list valid for the target */
857 if (z_verify_zone_spec() == -1)
860 /* -z zonelist=global is logically the same as -G */
861 if (z_global_only() && z_running_in_global_zone())
862 globalZoneOnly
= B_TRUE
;
866 * hook SIGINT and SIGHUP interrupts into quit.c's trap handler
869 /* hold SIGINT/SIGHUP interrupts */
871 (void) sighold(SIGHUP
);
872 (void) sighold(SIGINT
);
874 /* connect quit.c:trap() to SIGINT */
876 nact
.sa_handler
= quitGetTrapHandler();
877 nact
.sa_flags
= SA_RESTART
;
878 (void) sigemptyset(&nact
.sa_mask
);
880 (void) sigaction(SIGINT
, &nact
, &oact
);
882 /* connect quit.c:trap() to SIGHUP */
884 nact
.sa_handler
= quitGetTrapHandler();
885 nact
.sa_flags
= SA_RESTART
;
886 (void) sigemptyset(&nact
.sa_mask
);
888 (void) sigaction(SIGHUP
, &nact
, &oact
);
890 /* release hold on signals */
892 (void) sigrelse(SIGHUP
);
893 (void) sigrelse(SIGINT
);
896 * This function is in the libadm library; it sets:
897 * -> get_PKGLOC() = <install_root>/var/sadm/pkg
898 * -> get_PKGADM() = <install_root>/var/sadm/install
899 * -> pkgdir = <install_root>/var/sadm/pkg
900 * -> pkg_install_root = <install_root>
901 * This controls operations of libadm functions such as:
902 * -> pkginfofind, pkginfopen, fpkgparam, pkgparam, get_PKGLOC,
903 * -> get_PKGADM, get_install_root
906 set_PKGpaths(get_inst_root());
907 echoDebug(DBG_PKGADD_PKGPATHS
,
908 get_PKGLOC() ? get_PKGLOC() : "",
909 get_PKGADM() ? get_PKGADM() : "");
912 * This function is in the libinst library; it reads the specified
913 * admin(4) file and, using fpkgparam(), sets the global "adm" structure
914 * values to match what is in the specified admin file.
917 echoDebug(DBG_PKGADD_ADMINFILE
, admnfile
? admnfile
: "");
918 setadminFile(admnfile
);
921 * if running in the global zone, and non-global zones exist, then
922 * enable hollow package support so that any packages that are marked
923 * SUNW_PKG_HOLLOW=true will be correctly installed in non-global zones
924 * when added directly in the global zone by the global zone admin.
927 if (is_depend_pkginfo_DB()) {
928 echoDebug(DBG_PKGADD_HOLLOW_ENABLED
);
929 } else if ((z_running_in_global_zone() == B_TRUE
) &&
930 (z_non_global_zones_exist() == B_TRUE
)) {
931 echoDebug(DBG_PKGADD_ENABLING_HOLLOW
);
932 set_depend_pkginfo_DB(B_TRUE
);
935 /* if no device, get and validate default device */
937 if (device
== NULL
) {
938 device
= devattr("spool", "pathname");
939 if (device
== NULL
) {
940 progerr(ERR_NODEVICE
);
946 /* must be root if not directing results to spool directory */
948 if ((getuid() != 0) && (spoolDir
== NULL
)) {
949 progerr(ERR_NOT_ROOT
, prog
);
954 * process response file argument
958 echoDebug(DBG_PKGADD_RESPFILE
,
959 respfile
, respdir
? respdir
: "");
961 if (respfile
[0] != '/') {
962 progerr(ERR_RSP_FILE_NOTFULLPATH
, respfile
);
966 if (respdir
== NULL
) {
968 if (access(respfile
, F_OK
) == 0) {
969 progerr(ERR_NORESP
, respfile
);
973 } else if (access(respfile
, F_OK
) != 0) {
974 progerr(ERR_ACCRESP
, respfile
);
979 } else if (askflag
) {
980 progerr(ERR_RSP_FILE_NOT_GIVEN
);
986 /* establish temporary directory to use */
988 if ((tmpdir
= getenv("TMPDIR")) == NULL
) {
989 /* use default - no override specified */
993 echoDebug(DBG_PKGADD_TMPDIR
, tmpdir
);
996 * See if user wants this to be handled as an old style pkg.
997 * NOTE : the ``exception_pkg()'' stuff is to be used only
998 * through on495. This function comes out for on1095. See
999 * PSARC 1993-546. -- JST
1002 if (getenv("NONABI_SCRIPTS") != NULL
) {
1007 * See if the user wants to process symlinks consistent with
1011 if (getenv("PKG_NONABI_SYMLINKS") != NULL
) {
1016 * See if the user wants the package name length restricted.
1019 abiPtr
= getenv("PKG_ABI_NAMELENGTH");
1020 if (abiPtr
&& strncasecmp(abiPtr
, "TRUE", 4) == 0) {
1025 * validate the package source device - return pkgdev info that
1026 * describes the package source device.
1029 if (devtype(device
, &pkgdev
)) {
1030 progerr(ERR_BAD_DEVICE
, device
);
1036 * If writing the packages into a spool directory instead of
1037 * installing the packages, open the package datastream and
1038 * invoke pkgtrans to perform the conversion and exit.
1041 if (spoolDir
!= (char *)NULL
) {
1045 echoDebug(DBG_INSTALLING_TO_SPOOL
, spoolDir
);
1047 b
= open_package_datastream(argc
, argv
, spoolDir
, device
,
1048 &repeat
, &ids_name
, tmpdir
,
1051 quitSetIdsName(ids_name
);
1054 progerr(ERR_CANNOT_OPEN_PKG_STREAM
, PSTR(device
));
1058 n
= pkgtrans(device
, spoolDir
, &argv
[optind
], 0);
1064 * error if there are packages on the command line and a category
1068 if ((optind
< argc
) && (catg_arg
!= NULL
)) {
1069 progerr(ERR_PKGS_AND_CAT_PKGADD
);
1076 * ********************************************************************
1077 * main package processing "loop"
1078 * ********************************************************************
1082 quitSetIdsName(ids_name
);
1086 char **pkglist
; /* points to array of pkgs */
1089 * open next package data stream
1092 b
= open_package_datastream(argc
, argv
, spoolDir
, device
,
1093 &repeat
, &ids_name
, tmpdir
,
1096 quitSetIdsName(ids_name
);
1099 echoDebug(ERR_CANNOT_OPEN_PKG_STREAM
, PSTR(device
));
1104 * package source data stream open - get the package list
1107 b
= get_package_list(&pkglist
, argv
, catg_arg
, category
,
1111 echoDebug(DBG_CANNOT_GET_PKGLIST
);
1113 progerr(ERR_NOPKGS
, pkgdev
.dirname
);
1119 * count the number of packages to install
1120 * NOTE: npkgs is a global variable that is referenced by quit.c
1121 * when error messages are generated - it is referenced directly
1122 * by the other functions called below...
1125 for (npkgs
= 0; pkglist
[npkgs
] != (char *)NULL
; /* void */) {
1126 echoDebug(DBG_PKG_SELECTED
, npkgs
, pkglist
[npkgs
]);
1130 /* output number of packages to be added */
1132 echoDebug(DBG_NUM_PKGS_TO_ADD
, npkgs
);
1135 * if pkgask and response container is a file (not a directory),
1136 * and there is more than one package to install, then it is an
1137 * error - too many packages to install when response container
1141 if ((askflag
!= 0) && (respdir
== (char *)NULL
) &&
1143 progerr(ERR_TOO_MANY_PKGS
);
1149 * package list generated - add packages
1152 b
= add_packages(pkglist
, ids_name
, repeat
,
1153 altBinDir
, device
, noZones
);
1156 * close open input data stream (source package) if left open.
1160 echoDebug(DBG_CLOSING_STREAM
, ids_name
,
1161 PSTR(pkgdev
.dirname
));
1163 rrmdir(pkgdev
.dirname
);
1165 quitSetIdsName(ids_name
);
1169 * continue with next sequence of packages if continue set
1177 * not continuing - quit with 0 exit code
1188 * *****************************************************************************
1189 * static internal (private) functions
1190 * *****************************************************************************
1194 * Name: pkgZoneCheckInstall
1195 * Description: Invoke pkginstall in a specified zone to perform a preinstall
1196 * check of the a single package in the specified zone
1197 * Arguments: a_zoneName - pointer to string representing the name of the
1198 * zone to check install the package in.
1199 * a_zoneState - current state of the zone; must be mounted or
1201 * a_idsName - pointer to string representing the data stream
1202 * device (input data stream) containing the package to
1203 * be check installed.
1204 * a_altBinDir - pointer to string representing an alternative
1205 * binary location directory to pass to pkginstall.
1206 * If this is == NULL no alternative binary location is
1207 * passed to pkginstall.
1208 * a_adminFile - pointer to string representing the admin
1209 * file to pass to pkginstall when installing the package.
1210 * If this is == NULL no admin file is given to pkginstall.
1211 * a_stdoutPath - pointer to string representing the local path
1212 * into which all output written by pkginstall to stdout
1214 * If this is == NULL stdout is redirected to /dev/null
1215 * a_tmpzn - B_TRUE when this zone is booted by the package
1216 * command or B_FALSE if it was running before.
1217 * Returns: int (see ckreturn() function for details)
1219 * 1 - package operation failed (fatal error)
1220 * 2 - non-fatal error (warning)
1221 * 3 - user selected quit (operation interrupted)
1222 * 4 - admin settings prevented operation
1223 * 5 - interaction required and -n (non-interactive) specified
1224 * "10" will be added to indicate "immediate reboot required"
1225 * "20" will be added to indicate "reboot after install required"
1229 pkgZoneCheckInstall(char *a_zoneName
, zone_state_t a_zoneState
,
1230 char *a_idsName
, char *a_altBinDir
, char *a_adminFile
,
1231 char *a_stdoutPath
, boolean_t a_tmpzn
)
1235 char adminfd_path
[PATH_MAX
];
1236 char path
[PATH_MAX
];
1237 char pkgstreamfd_path
[PATH_MAX
];
1243 /* entry assertions */
1245 assert(a_zoneName
!= (char *)NULL
);
1246 assert(*a_zoneName
!= '\0');
1248 /* entry debugging info */
1250 echoDebug(DBG_PKGZONECHECKINSTALL_ENTRY
);
1251 echoDebug(DBG_PKGZONECHECKINSTALL_ARGS
, a_zoneName
, PSTR(pkginst
),
1252 PSTR(pkgdev
.dirname
), PSTR(pkgdev
.mount
), PSTR(pkgdev
.bdevice
),
1253 a_zoneState
== ZONE_STATE_MOUNTED
? "/a" : "/",
1254 PSTR(a_idsName
), PSTR(a_adminFile
), PSTR(a_stdoutPath
));
1256 /* generate full path to 'phatinstall' to run in zone */
1258 (void) snprintf(path
, sizeof (path
), "%s/pkginstall",
1259 "/usr/sadm/install/bin");
1261 /* start at first file descriptor */
1266 * generate argument list for call to pkginstall
1269 /* start at argument 0 */
1273 /* first argument is always: full path to executable */
1275 arg
[nargs
++] = path
;
1278 * second argument is always: pass -O debug to pkginstall: debug mode
1280 if (debugFlag
== B_TRUE
) {
1281 arg
[nargs
++] = "-O";
1282 arg
[nargs
++] = "debug";
1285 /* pkgadd -G: pass -G to pkginstall */
1287 if (globalZoneOnly
== B_TRUE
) {
1288 arg
[nargs
++] = "-G";
1291 /* pkgadd -b dir: pass -b to pkginstall */
1293 if (a_altBinDir
!= (char *)NULL
) {
1294 arg
[nargs
++] = "-b";
1295 arg
[nargs
++] = a_altBinDir
;
1298 /* pkgadd -C: pass -C to pkginstall: disable checksum */
1300 if (disableChecksum
) {
1301 arg
[nargs
++] = "-C";
1304 /* pkgadd -A: pass -A to pkginstall: disable attribute checking */
1306 if (disableAttributes
) {
1307 arg
[nargs
++] = "-A";
1311 * NONABI_SCRIPTS defined: pass -o to pkginstall; refers to a
1312 * pkg requiring operator interaction during a procedure script
1313 * (common before on1093)
1317 arg
[nargs
++] = "-o";
1321 * PKG_NONABI_SYMLINKS defined: pass -y to pkginstall; process
1322 * symlinks consistent with old behavior
1326 arg
[nargs
++] = "-y";
1330 * PKG_ABI_NAMELENGTH defined: pass -e to pkginstall; causes
1331 * package name length to be restricted
1334 if (ABI_namelength
) {
1335 arg
[nargs
++] = "-e";
1338 /* pkgadd -S: pass -S to pkginstall: suppress copyright notices */
1340 arg
[nargs
++] = "-S";
1342 /* pkgadd -M: pass -M to pkginstall: dont mount client file systems */
1344 arg
[nargs
++] = "-M";
1346 /* pkgadd -v: pass -v to pkginstall: never trace scripts */
1348 /* if running pkgask, pass -i to pkginstall: running pkgask */
1354 /* pass "-O enable-hollow-package-support" */
1356 if (is_depend_pkginfo_DB()) {
1357 arg
[nargs
++] = "-O";
1358 arg
[nargs
++] = "enable-hollow-package-support";
1361 /* check is always in non-interactive mode */
1363 arg
[nargs
++] = "-n";
1365 /* pkgadd -a admin: pass -a admin to pkginstall in zone: admin file */
1369 fd
= openLocal(a_adminFile
, O_RDONLY
, tmpdir
);
1371 progerr(ERR_CANNOT_COPY_LOCAL
, a_adminFile
,
1372 errno
, strerror(errno
));
1375 (void) snprintf(adminfd_path
, sizeof (adminfd_path
),
1376 "/proc/self/fd/%d", fd
);
1378 arg
[nargs
++] = "-a";
1379 arg
[nargs
++] = adminfd_path
;
1382 /* pkgadd -R root: pass -R /a to pkginstall when zone is mounted */
1384 if (a_zoneState
== ZONE_STATE_MOUNTED
) {
1385 arg
[nargs
++] = "-R";
1386 arg
[nargs
++] = "/a";
1389 /* pass -N to pkginstall: program name to report */
1391 arg
[nargs
++] = "-N";
1392 arg
[nargs
++] = get_prog_name();
1394 /* pass "-O preinstallcheck" */
1396 arg
[nargs
++] = "-O";
1397 arg
[nargs
++] = "preinstallcheck";
1399 /* add "-O addzonename" */
1401 arg
[nargs
++] = "-O";
1402 arg
[nargs
++] = "addzonename";
1405 * add parent zone info/type
1408 p
= z_get_zonename();
1409 if ((p
!= NULL
) && (*p
!= '\0')) {
1410 char zn
[MAXPATHLEN
];
1411 (void) snprintf(zn
, sizeof (zn
),
1412 "parent-zone-name=%s", p
);
1413 arg
[nargs
++] = "-O";
1414 arg
[nargs
++] = strdup(zn
);
1417 /* current zone type */
1419 arg
[nargs
++] = "-O";
1420 if (z_running_in_global_zone() == B_TRUE
) {
1421 char zn
[MAXPATHLEN
];
1422 (void) snprintf(zn
, sizeof (zn
),
1423 "parent-zone-type=%s",
1424 TAG_VALUE_GLOBAL_ZONE
);
1425 arg
[nargs
++] = strdup(zn
);
1427 char zn
[MAXPATHLEN
];
1428 (void) snprintf(zn
, sizeof (zn
),
1429 "parent-zone-type=%s",
1430 TAG_VALUE_NONGLOBAL_ZONE
);
1431 arg
[nargs
++] = strdup(zn
);
1434 /* Add the pkgserv options */
1435 arg
[nargs
++] = "-O";
1436 arg
[nargs
++] = pkgmodeargument(a_tmpzn
? RUN_ONCE
: pkgservergetmode());
1438 /* add in the package stream file */
1440 if (a_idsName
!= NULL
) {
1442 fd
= openLocal(a_idsName
, O_RDONLY
, tmpdir
);
1444 progerr(ERR_STREAM_UNAVAILABLE
, a_idsName
,
1445 pkginst
, strerror(errno
));
1448 (void) snprintf(pkgstreamfd_path
, sizeof (pkgstreamfd_path
),
1449 "/proc/self/fd/%d", fd
);
1451 arg
[nargs
++] = pkgstreamfd_path
;
1453 progerr(ERR_PKGZONEINSTALL_NO_STREAM
);
1457 /* add package instance name */
1459 arg
[nargs
++] = pkginst
;
1461 /* terminate the argument list */
1463 arg
[nargs
++] = NULL
;
1466 * run the appropriate pkginstall command in the specified zone
1469 if (debugFlag
== B_TRUE
) {
1470 echoDebug(DBG_ZONE_EXEC_ENTER
, a_zoneName
, arg
[0]);
1471 for (n
= 0; arg
[n
]; n
++) {
1472 echoDebug(DBG_ARG
, n
, arg
[n
]);
1476 /* terminate file descriptor list */
1480 /* exec command in zone */
1482 n
= z_zone_exec(a_zoneName
, path
, arg
, a_stdoutPath
, (char *)NULL
, fds
);
1484 echoDebug(DBG_ZONE_EXEC_EXIT
, a_zoneName
, arg
[0], n
,
1485 PSTR(a_stdoutPath
));
1488 * close any files that were opened for use by the
1489 * /proc/self/fd interface so they could be passed to programs
1490 * via the z_zone_exec() interface
1493 for (; maxfds
> 0; maxfds
--) {
1494 (void) close(fds
[maxfds
-1]);
1497 /* return results of pkginstall in zone execution */
1503 * Name: pkgZoneInstall
1504 * Description: Invoke pkginstall in a specified zone to perform an install
1505 * of a single package in the specified zone
1506 * Arguments: a_zoneName - pointer to string representing the name of the
1507 * zone to install the package in.
1508 * a_zoneState - current state of the zone; must be mounted or
1510 * a_idsName - pointer to string representing the data stream
1511 * device (input data stream) containing the package to
1513 * a_altBinDir - pointer to string representing an alternative
1514 * binary location directory to pass to pkginstall.
1515 * If this is == NULL no alternative binary location is
1516 * passed to pkginstall.
1517 * a_adminFile - pointer to string representing the admin
1518 * file to pass to pkginstall when installing the package.
1519 * If this is == NULL no admin file is given to pkginstall.
1520 * a_stdoutPath - pointer to string representing the local path
1521 * into which all output written by pkginstall to stdout
1523 * If this is == NULL stdout is redirected to /dev/null
1524 * a_tmpzn - B_TRUE when this zone is booted by the package
1525 * command or B_FALSE if it was running before.
1526 * Returns: int (see ckreturn() function for details)
1528 * 1 - package operation failed (fatal error)
1529 * 2 - non-fatal error (warning)
1530 * 3 - user selected quit (operation interrupted)
1531 * 4 - admin settings prevented operation
1532 * 5 - interaction required and -n (non-interactive) specified
1533 * "10" will be added to indicate "immediate reboot required"
1534 * "20" will be added to indicate "reboot after install required"
1538 pkgZoneInstall(char *a_zoneName
, zone_state_t a_zoneState
, char *a_idsName
,
1539 char *a_altBinDir
, char *a_adminFile
, boolean_t a_tmpzn
)
1543 char adminfd_path
[PATH_MAX
];
1544 char path
[PATH_MAX
];
1545 char pkgstreamfd_path
[PATH_MAX
];
1546 char respfilefd_path
[PATH_MAX
];
1552 /* entry assertions */
1554 assert(a_zoneName
!= (char *)NULL
);
1555 assert(*a_zoneName
!= '\0');
1557 /* entry debugging info */
1559 echoDebug(DBG_PKGZONEINSTALL_ENTRY
);
1560 echoDebug(DBG_PKGZONEINSTALL_ARGS
, a_zoneName
, PSTR(pkginst
),
1561 PSTR(pkgdev
.dirname
), PSTR(pkgdev
.mount
), PSTR(pkgdev
.bdevice
),
1562 a_zoneState
== ZONE_STATE_MOUNTED
? "/a" : "", PSTR(a_idsName
),
1565 /* generate path to pkginstall */
1567 (void) snprintf(path
, sizeof (path
), "%s/pkginstall", PKGBIN
);
1569 /* start at first file descriptor */
1574 * generate argument list for call to pkginstall
1577 /* start at argument 0 */
1581 /* first argument is path to executable */
1583 arg
[nargs
++] = path
;
1586 * second argument is always: pass -O debug to pkginstall: debug mode
1588 if (debugFlag
== B_TRUE
) {
1589 arg
[nargs
++] = "-O";
1590 arg
[nargs
++] = "debug";
1593 /* pkgadd -G: pass -G to pkginstall */
1595 if (globalZoneOnly
== B_TRUE
) {
1596 arg
[nargs
++] = "-G";
1599 /* pkgadd -b dir: pass -b to pkginstall in zone */
1601 if (a_altBinDir
!= (char *)NULL
) {
1602 arg
[nargs
++] = "-b";
1603 arg
[nargs
++] = a_altBinDir
;
1606 /* pkgadd -B blocksize: pass -B to pkginstall in zone */
1608 if (rw_block_size
!= NULL
) {
1609 arg
[nargs
++] = "-B";
1610 arg
[nargs
++] = rw_block_size
;
1613 /* pkgadd -C: pass -C to pkgadd in zone: disable checksum */
1615 if (disableChecksum
) {
1616 arg
[nargs
++] = "-C";
1619 /* pkgadd -A: pass -A to pkgadd in zone: disable attribute checking */
1621 if (disableAttributes
) {
1622 arg
[nargs
++] = "-A";
1625 /* pkgadd -S: pass -S to pkgadd in zone: suppress copyright notices */
1627 arg
[nargs
++] = "-S";
1629 /* pkgadd -I: pass -I to pkgadd in zone: initial install */
1632 arg
[nargs
++] = "-I";
1635 /* pkgadd -M: pass -M to pkgadd in zone: dont mount client file sys */
1637 arg
[nargs
++] = "-M";
1639 /* pkgadd -v: pass -v to pkgadd in zone: trace scripts */
1642 arg
[nargs
++] = "-v";
1645 /* pkgadd -z: pass -z to pkgadd in zone fresh inst from pkg save area */
1647 if (saveSpoolInstall
) {
1648 arg
[nargs
++] = "-z";
1651 /* pass "-O enable-hollow-package-support" */
1653 if (is_depend_pkginfo_DB()) {
1654 arg
[nargs
++] = "-O";
1655 arg
[nargs
++] = "enable-hollow-package-support";
1658 /* pkgadd -t pass -t to pkgadd in zone disable save spool area create */
1660 if (disableSaveSpool
) {
1661 arg
[nargs
++] = "-t";
1664 /* if running pkgask, pass -i to pkgadd in zone: running pkgask */
1667 echo(MSG_BYPASSING_ZONE
, a_zoneName
);
1672 * pkgadd -n (not pkgask): pass -n to pkginstall: noninteractive mode
1674 if (nointeract
&& !askflag
) {
1675 arg
[nargs
++] = "-n";
1678 /* pkgadd -a admin: pass -a admin to pkginstall in zone: admin file */
1682 fd
= openLocal(a_adminFile
, O_RDONLY
, tmpdir
);
1684 progerr(ERR_CANNOT_COPY_LOCAL
, a_adminFile
,
1685 errno
, strerror(errno
));
1688 (void) snprintf(adminfd_path
, sizeof (adminfd_path
),
1689 "/proc/self/fd/%d", fd
);
1691 arg
[nargs
++] = "-a";
1692 arg
[nargs
++] = adminfd_path
;
1695 /* pkgadd -R root: pass -R /a to pkginstall when zone is mounted */
1696 if (a_zoneState
== ZONE_STATE_MOUNTED
) {
1697 arg
[nargs
++] = "-R";
1698 arg
[nargs
++] = "/a";
1702 * pkgadd -D arg: pass -D dryrun to pkginstall in zone: dryrun
1706 arg
[nargs
++] = "-D";
1707 arg
[nargs
++] = pkgdrtarg
;
1711 * pkgadd -c cont: pass -c cont to pkginstall in zone: continuation
1715 arg
[nargs
++] = "-c";
1716 arg
[nargs
++] = pkgcontsrc
;
1719 /* pkgadd -r resp: pass -r resp to pkginstall in zone: response file */
1723 fd
= openLocal(respfile
, O_RDONLY
, tmpdir
);
1725 progerr(ERR_CANNOT_COPY_LOCAL
, a_adminFile
,
1726 errno
, strerror(errno
));
1729 (void) snprintf(respfilefd_path
,
1730 sizeof (respfilefd_path
),
1731 "/proc/self/fd/%d", fd
);
1733 arg
[nargs
++] = "-r";
1734 arg
[nargs
++] = respfilefd_path
;
1737 /* add "-O addzonename" */
1739 arg
[nargs
++] = "-O";
1740 arg
[nargs
++] = "addzonename";
1743 * add parent zone info/type
1746 p
= z_get_zonename();
1747 if ((p
!= NULL
) && (*p
!= '\0')) {
1748 char zn
[MAXPATHLEN
];
1749 (void) snprintf(zn
, sizeof (zn
),
1750 "parent-zone-name=%s", p
);
1751 arg
[nargs
++] = "-O";
1752 arg
[nargs
++] = strdup(zn
);
1755 /* current zone type */
1757 arg
[nargs
++] = "-O";
1758 if (z_running_in_global_zone() == B_TRUE
) {
1759 char zn
[MAXPATHLEN
];
1760 (void) snprintf(zn
, sizeof (zn
),
1761 "parent-zone-type=%s",
1762 TAG_VALUE_GLOBAL_ZONE
);
1763 arg
[nargs
++] = strdup(zn
);
1765 char zn
[MAXPATHLEN
];
1766 (void) snprintf(zn
, sizeof (zn
),
1767 "parent-zone-type=%s",
1768 TAG_VALUE_NONGLOBAL_ZONE
);
1769 arg
[nargs
++] = strdup(zn
);
1772 /* Add the pkgserv options */
1773 arg
[nargs
++] = "-O";
1774 arg
[nargs
++] = pkgmodeargument(a_tmpzn
? RUN_ONCE
: pkgservergetmode());
1776 /* add in the package stream file */
1778 if (a_idsName
!= NULL
) {
1780 fd
= openLocal(a_idsName
, O_RDONLY
, tmpdir
);
1782 progerr(ERR_STREAM_UNAVAILABLE
, a_idsName
,
1783 pkginst
, strerror(errno
));
1786 (void) snprintf(pkgstreamfd_path
, sizeof (pkgstreamfd_path
),
1787 "/proc/self/fd/%d", fd
);
1789 arg
[nargs
++] = pkgstreamfd_path
;
1791 progerr(ERR_PKGZONEINSTALL_NO_STREAM
);
1795 /* add package instance name */
1797 arg
[nargs
++] = pkginst
;
1799 /* terminate the argument list */
1801 arg
[nargs
++] = NULL
;
1804 * run the appropriate pkginstall command in the specified zone
1807 if (debugFlag
== B_TRUE
) {
1808 echoDebug(DBG_ZONE_EXEC_ENTER
, a_zoneName
, arg
[0]);
1809 for (n
= 0; arg
[n
]; n
++) {
1810 echoDebug(DBG_ARG
, n
, arg
[n
]);
1814 /* terminate file descriptor list */
1818 /* exec command in zone */
1820 n
= z_zone_exec(a_zoneName
, path
, arg
, (char *)NULL
, (char *)NULL
, fds
);
1822 echoDebug(DBG_ZONE_EXEC_EXIT
, a_zoneName
, arg
[0], n
, "");
1825 * close any files that were opened for use by the
1826 * /proc/self/fd interface so they could be passed to programs
1827 * via the z_zone_exec() interface
1830 for (; maxfds
> 0; maxfds
--) {
1831 (void) close(fds
[maxfds
-1]);
1834 /* return results of pkginstall in zone execution */
1841 * Description: Invoke pkginstall in the current zone to perform an install
1842 * of a single package to the current zone or standalone system
1843 * Arguments: a_altRoot - pointer to string representing the alternative
1844 * root to use for the install
1845 * a_idsName - pointer to string representing the data stream
1846 * device (input data stream) containing the package to
1848 * a_pkgDir - pointer to string representing the path to the
1849 * directory containing the package
1850 * a_altBinDir - pointer to string representing location of the
1851 * pkginstall executable to run. If not NULL, then pass
1852 * the path specified to the -b option to pkginstall.
1853 * Returns: int (see ckreturn() function for details)
1855 * 1 - package operation failed (fatal error)
1856 * 2 - non-fatal error (warning)
1857 * 3 - user selected quit (operation interrupted)
1858 * 4 - admin settings prevented operation
1859 * 5 - interaction required and -n (non-interactive) specified
1860 * "10" will be added to indicate "immediate reboot required"
1861 * "20" will be added to indicate "reboot after install required"
1862 * NOTE: Both a_idsName and a_pkgDir are used to determine where the
1863 * package to be installed is located. If a_idsName is != NULL
1864 * then it must be the path to a device containing a package
1865 * stream that contains the package to be installed. If a_idsName
1866 * is == NULL then a_pkgDir must contain a full path to a directory
1867 * that contains the package to be installed.
1871 pkgInstall(char *a_altRoot
, char *a_idsName
, char *a_pkgDir
, char *a_altBinDir
)
1875 char path
[PATH_MAX
];
1879 /* entry debugging info */
1881 echoDebug(DBG_PKGINSTALL_ENTRY
);
1882 echoDebug(DBG_PKGINSTALL_ARGS
, PSTR(pkginst
), PSTR(pkgdev
.dirname
),
1883 PSTR(pkgdev
.mount
), PSTR(pkgdev
.bdevice
), PSTR(a_altRoot
),
1884 PSTR(a_idsName
), PSTR(a_pkgDir
));
1886 /* generate full path to 'pkginstall' to run in zone */
1888 (void) snprintf(path
, sizeof (path
), "%s/pkginstall",
1889 a_altBinDir
== (char *)NULL
? PKGBIN
: a_altBinDir
);
1891 * generate argument list for call to pkginstall
1894 /* start at argument 0 */
1898 /* first argument is path to executable */
1900 arg
[nargs
++] = path
;
1903 * second argument is always: pass -O debug to pkginstall: debug mode
1905 if (debugFlag
== B_TRUE
) {
1906 arg
[nargs
++] = "-O";
1907 arg
[nargs
++] = "debug";
1910 arg
[nargs
++] = "-O";
1911 arg
[nargs
++] = pkgmodeargument(pkgservergetmode());
1914 * pkgadd -G: pass -G to pkginstall if:
1915 * - the -G option is specified on the pkgadd command line
1916 * - this package is marked 'this zone only':
1917 * -- package has SUNW_PKG_THISZONE=true, or
1918 * -- package has a request script
1919 * Setting -G for pkginstall causes pkginstall to install the package
1920 * in the target zone. If running in the global zone, will install the
1921 * package and mark the package as installed "in the global zone only".
1922 * If running in a non-global zone, will just install the package.
1925 if (globalZoneOnly
== B_TRUE
) {
1926 arg
[nargs
++] = "-G";
1927 } else if (pkgPackageIsThisZone(pkginst
) == B_TRUE
) {
1928 arg
[nargs
++] = "-G";
1931 /* pkgadd -b dir: pass -b to pkginstall */
1933 if (a_altBinDir
!= (char *)NULL
) {
1934 arg
[nargs
++] = "-b";
1935 arg
[nargs
++] = a_altBinDir
;
1938 /* pkgadd -B blocksize: pass -B to pkginstall */
1940 if (rw_block_size
!= NULL
) {
1941 arg
[nargs
++] = "-B";
1942 arg
[nargs
++] = rw_block_size
;
1945 /* pkgadd -C: pass -C to pkginstall: disable checksum */
1947 if (disableChecksum
) {
1948 arg
[nargs
++] = "-C";
1951 /* pkgadd -A: pass -A to pkginstall: disable attribute checking */
1953 if (disableAttributes
) {
1954 arg
[nargs
++] = "-A";
1958 * NONABI_SCRIPTS defined: pass -o to pkginstall; refers to a
1959 * pkg requiring operator interaction during a procedure script
1960 * (common before on1093)
1964 arg
[nargs
++] = "-o";
1968 * PKG_NONABI_SYMLINKS defined: pass -y to pkginstall; process
1969 * symlinks consistent with old behavior
1973 arg
[nargs
++] = "-y";
1977 * PKG_ABI_NAMELENGTH defined: pass -e to pkginstall; causes
1978 * package name length to be restricted
1981 if (ABI_namelength
) {
1982 arg
[nargs
++] = "-e";
1985 /* pkgadd -S: pass -S to pkginstall: suppress copyright notices */
1987 if (suppressCopyright
) {
1988 arg
[nargs
++] = "-S";
1991 /* pkgadd -I: pass -I to pkginstall: initial install being performed */
1994 arg
[nargs
++] = "-I";
1997 /* pkgadd -M: pass -M to pkginstall: dont mount client file systems */
1999 if (no_map_client
) {
2000 arg
[nargs
++] = "-M";
2003 /* pkgadd -v: pass -v to pkginstall: trace scripts */
2006 arg
[nargs
++] = "-v";
2009 /* pkgadd -z: pass -z to pkginstall: fresh install from pkg save area */
2011 if (saveSpoolInstall
) {
2012 arg
[nargs
++] = "-z";
2016 * if running in a non-global zone and the 'hollow' attribute is
2017 * passed in, then pass -h to pkginstall so that it knows how to
2018 * handle hollow packages for this local zone.
2021 if (!z_running_in_global_zone() && is_depend_pkginfo_DB()) {
2022 arg
[nargs
++] = "-h";
2025 /* pkgadd -t: pass -t to pkginstall: disable save spool area creation */
2027 if (disableSaveSpool
) {
2028 arg
[nargs
++] = "-t";
2031 /* if running pkgask, pass -i to pkginstall: running pkgask */
2034 arg
[nargs
++] = "-i";
2037 /* pkgadd -n (not pkgask): pass -n to pkginstall: noninteractive mode */
2039 if (nointeract
&& !askflag
) {
2040 arg
[nargs
++] = "-n";
2043 /* pkgadd -a admin: pass -a admin to pkginstall: admin file */
2046 arg
[nargs
++] = "-a";
2047 arg
[nargs
++] = admnfile
;
2050 /* pkgadd -D dryrun: pass -D dryrun to pkginstall: dryrun mode/file */
2053 arg
[nargs
++] = "-D";
2054 arg
[nargs
++] = pkgdrtarg
;
2057 /* pkgadd -c cont: pass -c cont to pkginstall: continuation file */
2060 arg
[nargs
++] = "-c";
2061 arg
[nargs
++] = pkgcontsrc
;
2064 /* pkgadd -V vfstab: pass -V vfstab to pkginstall: alternate vfstab */
2067 arg
[nargs
++] = "-V";
2068 arg
[nargs
++] = vfstab_file
;
2071 /* pkgadd -r resp: pass -r resp to pkginstall: response file */
2074 arg
[nargs
++] = "-r";
2075 arg
[nargs
++] = respfile
;
2078 /* pkgadd -R root: pass -R root to pkginstall: alternative root */
2080 if (a_altRoot
&& *a_altRoot
) {
2081 arg
[nargs
++] = "-R";
2082 arg
[nargs
++] = a_altRoot
;
2086 * If input data stream is available,
2087 * - add: -d ids_name -p number_of_parts
2089 * - add: -d device -m mount [-f type]
2092 if (a_idsName
!= NULL
) {
2093 arg
[nargs
++] = "-d";
2094 arg
[nargs
++] = a_idsName
;
2095 arg
[nargs
++] = "-p";
2097 ds_putinfo(buffer
, sizeof (buffer
));
2098 arg
[nargs
++] = buffer
;
2099 } else if (pkgdev
.mount
!= NULL
) {
2100 arg
[nargs
++] = "-d";
2101 arg
[nargs
++] = pkgdev
.bdevice
;
2102 arg
[nargs
++] = "-m";
2103 arg
[nargs
++] = pkgdev
.mount
;
2104 if (pkgdev
.fstyp
!= NULL
) {
2105 arg
[nargs
++] = "-f";
2106 arg
[nargs
++] = pkgdev
.fstyp
;
2111 * add parent zone info/type
2114 p
= z_get_zonename();
2115 if ((p
!= NULL
) && (*p
!= '\0')) {
2116 char zn
[MAXPATHLEN
];
2117 (void) snprintf(zn
, sizeof (zn
),
2118 "parent-zone-name=%s", p
);
2119 arg
[nargs
++] = "-O";
2120 arg
[nargs
++] = strdup(zn
);
2123 /* current zone type */
2125 arg
[nargs
++] = "-O";
2126 if (z_running_in_global_zone() == B_TRUE
) {
2127 char zn
[MAXPATHLEN
];
2128 (void) snprintf(zn
, sizeof (zn
),
2129 "parent-zone-type=%s",
2130 TAG_VALUE_GLOBAL_ZONE
);
2131 arg
[nargs
++] = strdup(zn
);
2133 char zn
[MAXPATHLEN
];
2134 (void) snprintf(zn
, sizeof (zn
),
2135 "parent-zone-type=%s",
2136 TAG_VALUE_NONGLOBAL_ZONE
);
2137 arg
[nargs
++] = strdup(zn
);
2140 /* pass -N to pkginstall: program name to report */
2142 arg
[nargs
++] = "-N";
2143 arg
[nargs
++] = get_prog_name();
2145 /* add package directory name */
2147 arg
[nargs
++] = a_pkgDir
;
2149 /* add package instance name */
2151 arg
[nargs
++] = pkginst
;
2153 /* terminate the argument list */
2155 arg
[nargs
++] = NULL
;
2158 * run the appropriate pkginstall command in the specified zone
2161 if (debugFlag
== B_TRUE
) {
2162 echoDebug(DBG_ZONE_EXEC_ENTER
, "global", arg
[0]);
2163 for (n
= 0; arg
[n
]; n
++) {
2164 echoDebug(DBG_ARG
, n
, arg
[n
]);
2168 /* execute pkginstall command */
2170 n
= pkgexecv(NULL
, NULL
, NULL
, NULL
, arg
);
2172 /* return results of pkginstall execution */
2178 * function to clear out any exisiting error return conditions that may have
2179 * been set by previous calls to ckreturn()
2184 admnflag
= 0; /* != 0 if any pkg op admin setting failure (4) */
2185 doreboot
= 0; /* != 0 if reboot required after installation (>= 10) */
2186 failflag
= 0; /* != 0 if fatal error has occurred (1) */
2187 intrflag
= 0; /* != 0 if user selected quit (3) */
2188 ireboot
= 0; /* != 0 if immediate reboot required (>= 20) */
2189 nullflag
= 0; /* != 0 if admin interaction required (5) */
2190 warnflag
= 0; /* != 0 if non-fatal error has occurred (2) */
2191 interrupted
= 0; /* last pkg op was quit (1,2,3,4,5) */
2192 needconsult
= 0; /* essential ask admin now (1,2,3,5) */
2196 * function which checks the indicated return value
2197 * and indicates disposition of installation
2200 ckreturn(int retcode
)
2203 * entry debugging info
2206 echoDebug(DBG_PKGADD_CKRETURN
, retcode
, PSTR(pkginst
));
2208 /* reset needconsult so it only reflects this call to ckreturn */
2212 case 0: /* successful */
2215 break; /* empty case */
2217 case 1: /* package operation failed (fatal error) */
2225 case 2: /* non-fatal error (warning) */
2233 case 3: /* user selected quit; operation interrupted */
2241 case 4: /* admin settings prevented operation */
2248 case 5: /* administration: interaction req (no -n) */
2263 if (retcode
>= 20) {
2265 } else if (retcode
>= 10) {
2273 char *prog
= get_prog_name();
2276 (void) fprintf(stderr
, ERR_USAGE_PKGASK
, prog
);
2277 } else if (z_running_in_global_zone() == B_FALSE
) {
2278 (void) fprintf(stderr
, ERR_USAGE_PKGADD_NONGLOBALZONE
,
2281 (void) fprintf(stderr
, ERR_USAGE_PKGADD_GLOBALZONE
,
2287 * Name: check_applicability
2288 * Description: determine if a package is installable in this zone; that is,
2289 * does the scope of install conflict with existing installation
2290 * or can the package be installed
2291 * Arguments: a_packageDir - [RO, *RO] - (char *)
2292 * Pointer to string representing the directory where the
2293 * package is located
2294 * a_pkgInst - [RO, *RO] - (char *)
2295 * Pointer to string representing the name of the package
2297 * a_rootPath - [RO, *RO] - (char *)
2298 * Pointer to string representing path to the root of the
2299 * file system where the package is to be installed - this
2300 * is usually the same as the "-R" argument to pkgadd
2301 * a_flags - [RO, *RO] - (CAF_T)
2302 * Flags set by the caller to indicate the conditions
2303 * under which the package is to be installed:
2304 * CAF_IN_GLOBAL_ZONE - in global zone
2305 * CAF_SCOPE_GLOBAL - -G specified
2306 * CAF_SCOPE_NONGLOBAL - -Z specified
2307 * Returns: boolean_t
2308 * B_TRUE - the package can be installed
2309 * B_FALSE - the package can not be installed
2313 check_applicability(char *a_packageDir
, char *a_pkgInst
, char *a_rootPath
,
2318 boolean_t all_zones
; /* pkg is "all zones" only */
2319 boolean_t in_gz_only
; /* pkg installed in global zone only */
2320 boolean_t is_hollow
; /* pkg is "hollow" */
2321 boolean_t pkg_installed
; /* pkg is installed */
2322 boolean_t this_zone
; /* pkg is "this zone" only */
2323 boolean_t reqfile_found
= B_FALSE
;
2324 char instPkg
[PKGSIZ
+1]; /* installed pkg instance nam */
2325 char instPkgPath
[PATH_MAX
]; /* installed pkg toplevel dir */
2326 char pkginfoPath
[PATH_MAX
]; /* pkg 2 install pkginfo file */
2327 char pkgmapPath
[PATH_MAX
]; /* pkg 2 install pkgmap file */
2328 char pkgpath
[PATH_MAX
]; /* pkg 2 install toplevel dir */
2330 char line
[LINE_MAX
];
2332 /* entry assertions */
2334 assert(a_packageDir
!= (char *)NULL
);
2335 assert(*a_packageDir
!= '\0');
2336 assert(a_pkgInst
!= (char *)NULL
);
2337 assert(*a_pkgInst
!= '\0');
2339 /* normalize root path */
2341 if (a_rootPath
== (char *)NULL
) {
2345 /* entry debugging info */
2347 echoDebug(DBG_CHECKAPP_ENTRY
);
2348 echoDebug(DBG_CHECKAPP_ARGS
, a_pkgInst
, a_packageDir
, a_rootPath
);
2351 * calculate paths to various objects
2354 /* path to package to be installed top level (main) directory */
2356 len
= snprintf(pkgpath
, sizeof (pkgpath
), "%s/%s", a_packageDir
,
2358 if (len
> sizeof (pkgpath
)) {
2359 progerr(ERR_CREATE_PATH_2
, a_packageDir
, a_pkgInst
);
2363 /* error if package top level directory does not exist */
2365 if (isdir(pkgpath
) != 0) {
2366 progerr(ERR_NO_PKGDIR
, pkgpath
, a_pkgInst
, strerror(errno
));
2370 /* path to pkginfo file within the package to be installed */
2372 len
= snprintf(pkginfoPath
, sizeof (pkginfoPath
), "%s/pkginfo",
2374 if (len
> sizeof (pkginfoPath
)) {
2375 progerr(ERR_CREATE_PATH_2
, pkgpath
, "pkginfo");
2379 /* path to highest instance of package currently installed */
2381 pkgLocateHighestInst(instPkgPath
, sizeof (instPkgPath
),
2382 instPkg
, sizeof (instPkg
), a_rootPath
, a_pkgInst
);
2385 * gather information from this package's pkginfo file
2388 pkginfoFP
= fopen(pkginfoPath
, "r");
2390 if (pkginfoFP
== (FILE *)NULL
) {
2391 progerr(ERR_NO_PKG_INFOFILE
, a_pkgInst
, pkginfoPath
,
2396 /* determine "HOLLOW" setting for this package */
2398 is_hollow
= pkginfoParamTruth(pkginfoFP
, PKG_HOLLOW_VARIABLE
,
2401 /* determine "ALLZONES" setting for this package */
2403 all_zones
= pkginfoParamTruth(pkginfoFP
, PKG_ALLZONES_VARIABLE
,
2406 /* determine "THISZONE" setting for this package */
2408 this_zone
= pkginfoParamTruth(pkginfoFP
, PKG_THISZONE_VARIABLE
,
2411 /* close pkginfo file */
2413 (void) fclose(pkginfoFP
);
2416 * If request file is not found, it may be in the datastream which
2417 * is not yet unpacked. Check in the pkgmap file.
2419 if (isfile(pkgpath
, REQUEST_FILE
) != 0) {
2421 /* path to pkgmap file within the package to be installed */
2422 (void) snprintf(pkgmapPath
, sizeof (pkgmapPath
), "%s/pkgmap",
2425 pkgmapFP
= fopen(pkgmapPath
, "r");
2427 if (pkgmapFP
== NULL
) {
2428 progerr(ERR_NO_PKG_MAPFILE
, a_pkgInst
,
2429 pkgmapPath
, strerror(errno
));
2433 while (fgets(line
, LINE_MAX
, pkgmapFP
) != NULL
) {
2434 if (strstr(line
, " i request") != NULL
) {
2435 reqfile_found
= B_TRUE
;
2439 (void) fclose(pkgmapFP
);
2441 reqfile_found
= B_TRUE
;
2445 * If this package is not marked for installation in this zone only,
2446 * check to see if this package has a request script. If this package
2447 * does have a request script, then mark the package for installation
2448 * in this zone only. Any package with a request script cannot be
2449 * installed outside of the zone the pkgadd command is being run in,
2450 * nor can such a package be installed as part of a new zone install.
2451 * A new zone install must be non-interactive, which is required
2452 * by all packages integrated into the Solaris WOS.
2455 if ((!this_zone
) && (reqfile_found
)) {
2456 if (a_flags
& CAF_IN_GLOBAL_ZONE
) {
2457 echoDebug(DBG_CHECKAPP_THISZONE_REQUEST
, a_pkgInst
);
2463 * If this package is already installed, see if the current installation
2464 * of the package has a request file - if it does, then act as though
2465 * the current package to be added has a request file - install the
2466 * package in the current zone only.
2469 if ((!this_zone
) && (instPkgPath
[0] != '\0') &&
2470 (isfile(instPkgPath
, REQUEST_FILE
) == 0)) {
2471 if (a_flags
& CAF_IN_GLOBAL_ZONE
) {
2472 echoDebug(DBG_CHECKAPP_THISZONE_INSTREQ
,
2473 a_pkgInst
, instPkg
);
2478 /* gather information from the global zone only file */
2480 in_gz_only
= B_FALSE
;
2481 if (a_flags
& CAF_IN_GLOBAL_ZONE
) {
2482 in_gz_only
= pkgIsPkgInGzOnly(a_rootPath
, a_pkgInst
);
2485 /* determine if this package is currently installed */
2487 pkg_installed
= pkginfoIsPkgInstalled((struct pkginfo
**)NULL
,
2491 * verify package applicability based on information gathered,
2492 * and validate the three SUNW_PKG_ options:
2494 * -----------|--------------|-------------|-------------|-----------
2495 * - - - - - -| GLOBAL ZONE -| GLOBAL ZONE | LOCAL ZONE | LOCAL ZONE
2496 * - - - - - -| - - pkgadd - | pkgadd -G | pkgadd | pkgadd -G
2497 * ----1------|--------------|-------------|-------------|------------
2498 * ALLZONES f | add to gz | add to gz | add to ls | add to ls
2499 * HOLLOW f | current lz | not to curr | only - - - -| only - - -
2500 * THISZONE f | futr lz - - -| or futr lz | - - - - - - | - - - - - -
2501 * ----2------|--------------|-------------|-------------|------------
2502 * ALLZONES T | add to gz | operation | operation | operation
2503 * HOLLOW f | current lz | not allowed | not allowed | not allowed
2504 * THISZONE f | future lz | - - - - - - | - - - - - - | - - - - - -
2505 * ----3------|--------------|-------------|-------------|------------
2506 * ALLZONES T | add to gz | operation | operation | operation
2507 * HOLLOW T | pkg db only | not allowed | not allowed | not allowed
2508 * THISZONE f | curr/futr lz | - - - - - - | - - - - - - | - - - - - -
2509 * ----4------|--------------|-------------|-------------|------------
2510 * ALLZONES T | bad option | bad option | bad option | bad option
2511 * HOLLOW * | combo - - - -| combo - - - | combo - - - | combo - -
2512 * THISZONE T | - - - - - - -|- - - - - - -|- - - - - - -|- - - - - -
2513 * ----5------|--------------|-------------|-------------|------------
2514 * ALLZONES f | bad option | bad option | bad option | bad option
2515 * HOLLOW T | combo - - - -| combo - - - | combo - - - | combo - - -
2516 * THISZONE * | - - - - - - -| - - - - - - | - - - - - - | - - - - - -
2517 * ----6------|--------------|-------------|-------------|------------
2518 * ALLZONES f | add to gz | add to gz | add to lz | add to lz
2519 * HOLLOW f | not current | not current | only - - - | only - - -
2520 * THISZONE T | or future lz | or futr lz | - - - - - - | - - - - - -
2521 * -----------|--------------|-------------|-------------|-----------
2524 /* pkg "all zones" && "this zone" (#4) */
2526 if (all_zones
&& this_zone
) {
2527 progerr(ERR_ALLZONES_AND_THISZONE
, a_pkgInst
,
2528 PKG_ALLZONES_VARIABLE
, PKG_THISZONE_VARIABLE
);
2532 /* pkg "!all zones" && "hollow" (#5) */
2534 if ((!all_zones
) && is_hollow
) {
2535 progerr(ERR_NOW_ALLZONES_AND_HOLLOW
, a_pkgInst
,
2536 PKG_ALLZONES_VARIABLE
, PKG_HOLLOW_VARIABLE
);
2540 /* pkg ALLZONES=true && -Z specified */
2542 if (all_zones
&& (a_flags
& CAF_SCOPE_NONGLOBAL
)) {
2543 progerr(ERR_ALLZONES_AND_Z_USED
, a_pkgInst
);
2547 /* pkg ALLZONES=true & not running in global zone (#2/#3) */
2549 if (all_zones
&& (!(a_flags
& CAF_IN_GLOBAL_ZONE
))) {
2550 progerr(ERR_ALLZONES_AND_IN_LZ
, a_pkgInst
);
2554 /* pkg "in gz only" & pkg "NOT installed" */
2556 if (in_gz_only
&& (!pkg_installed
)) {
2557 /* MAKE A WARNING */
2558 echo(ERR_IN_GZ_AND_NOT_INSTALLED
, a_pkgInst
,
2559 pkgGetGzOnlyPath());
2562 /* pkg ALLZONES=true & pkg "in gz only" & pkg "is installed" */
2564 if (all_zones
&& in_gz_only
&& pkg_installed
) {
2565 progerr(ERR_IN_GZ_AND_ALLZONES_AND_INSTALLED
, a_pkgInst
);
2569 /* pkg ALLZONES=true && -G specified (#2/#3) */
2571 if (all_zones
&& (a_flags
& CAF_SCOPE_GLOBAL
)) {
2572 progerr(ERR_ALLZONES_AND_G_USED
, a_pkgInst
);
2576 /* pkg "!this zone" && "in gz only" & -G not specified */
2578 if ((!this_zone
) && in_gz_only
&& (!(a_flags
& CAF_SCOPE_GLOBAL
))) {
2579 progerr(ERR_IN_GZ_AND_NO_G_USED
, a_pkgInst
);
2583 /* pkg "NOT in gz only" & -Z specified */
2585 if ((!in_gz_only
) && (a_flags
& CAF_SCOPE_NONGLOBAL
)) {
2586 progerr(ERR_NOT_IN_GZ_AND_Z_USED
, a_pkgInst
);
2590 /* pkg "this zone" && -Z specified */
2592 if (this_zone
&& (a_flags
& CAF_SCOPE_NONGLOBAL
)) {
2593 progerr(ERR_THISZONE_AND_Z_USED
, PKG_THISZONE_VARIABLE
,
2599 * If this package is marked 'this zone only', then mark the package
2600 * as "add to this zone only". This is referenced by the various
2601 * add_package_... functions to determine if the package should be
2602 * added to the current zone, or to all zones, depending on the
2603 * zone in which the command is being run.
2607 pkgAddThisZonePackage(a_pkgInst
);
2614 * Name: create_zone_adminfile
2615 * Description: Given a zone temporary directory and optionally an existing
2616 * administration file, generate an administration file that
2617 * can be used to perform "non-interactive" operations in a
2619 * Arguments: r_zoneAdminFile - pointer to handle that will contain a
2620 * string representing the path to the temporary
2621 * administration file created - this must be NULL
2622 * before the first call to this function - on
2623 * subsequent calls if the pointer is NOT null then
2624 * the existing string will NOT be overwritten.
2625 * a_zoneTempDir - pointer to string representing the path
2626 * to the zone temporary directory to create the
2627 * temporary administration file in
2628 * a_admnfile - pointer to string representing the path to
2629 * an existing "user" administration file - the
2630 * administration file created will contain the
2631 * settings contained in this file, modified as
2632 * appropriate to supress any interaction;
2633 * If this is == NULL then the administration file
2634 * created will not contain any extra settings
2636 * NOTE: Any string returned is placed in new storage for the
2637 * calling method. The caller must use 'free' to dispose
2638 * of the storage once the string is no longer needed.
2639 * NOTE: On any error this function will call 'quit(1)'
2643 create_zone_adminfile(char **r_zoneAdminFile
, char *a_zoneTempDir
,
2648 /* entry assertions */
2650 assert(r_zoneAdminFile
!= (char **)NULL
);
2651 assert(a_zoneTempDir
!= (char *)NULL
);
2652 assert(*a_zoneTempDir
!= '\0');
2654 /* entry debugging info */
2656 echoDebug(DBG_CREATE_ZONE_ADMINFILE
, a_zoneTempDir
, PSTR(a_admnfile
));
2658 /* if temporary name already exists, do not overwrite */
2660 if (*r_zoneAdminFile
!= (char *)NULL
) {
2664 /* create temporary name */
2666 *r_zoneAdminFile
= tempnam(a_zoneTempDir
, "zadmn");
2667 b
= z_create_zone_admin_file(*r_zoneAdminFile
, a_admnfile
);
2669 progerr(ERR_CREATE_TMPADMIN
, *r_zoneAdminFile
,
2675 echoDebug(DBG_CREATED_ZONE_ADMINFILE
, *r_zoneAdminFile
);
2679 * Name: create_zone_tempdir
2680 * Description: Given a system temporary directory, create a "zone" specific
2681 * temporary directory and return the path to the directory
2683 * Arguments: r_zoneTempDir - pointer to handle that will contain a
2684 * string representing the path to the temporary
2685 * directory created - this must be NULL before the
2686 * first call to this function - on subsequent calls
2687 * if the pointer is NOT null then the existing string
2688 * will NOT be overwritten.
2689 * a_zoneTempDir - pointer to string representing the path
2690 * to the system temporary directory to create the
2691 * temporary zone directory in
2693 * NOTE: Any string returned is placed in new storage for the
2694 * calling method. The caller must use 'free' to dispose
2695 * of the storage once the string is no longer needed.
2696 * NOTE: On any error this function will call 'quit(1)'
2697 * NOTE: This function calls "quitSetZoneTmpdir" on success to
2698 * register the directory created with quit() so that the
2699 * directory will be automatically deleted on exit.
2703 create_zone_tempdir(char **r_zoneTempDir
, char *a_tmpdir
)
2707 /* entry assertions */
2709 assert(r_zoneTempDir
!= (char **)NULL
);
2710 assert(a_tmpdir
!= (char *)NULL
);
2711 assert(*a_tmpdir
!= '\0');
2713 /* entry debugging info */
2715 echoDebug(DBG_CREATE_ZONE_TEMPDIR
, a_tmpdir
);
2717 /* if temporary directory already exists, do not overwrite */
2719 if (*r_zoneTempDir
!= (char *)NULL
) {
2723 /* create temporary directory */
2725 b
= setup_temporary_directory(r_zoneTempDir
, a_tmpdir
, "ztemp");
2727 progerr(ERR_ZONETEMPDIR
, a_tmpdir
, strerror(errno
));
2732 /* register with quit() so directory is removed on exit */
2734 quitSetZoneTmpdir(*r_zoneTempDir
);
2736 /* exit debugging info */
2738 echoDebug(DBG_CREATED_ZONE_TEMPDIR
, *r_zoneTempDir
);
2742 * Name: continue_installation
2743 * Description: Called from within a loop that is installing packages,
2744 * this function examines various global variables and decides
2745 * whether or not to ask an appropriate question, and wait for
2746 * and appropriate reply.
2747 * Arguments: <<global variables>>
2748 * Returns: B_TRUE - continue processing with next package
2749 * B_FALSE - do not continue processing with next package
2753 continue_installation(void)
2755 char ans
[MAX_INPUT
];
2758 /* return TRUE if not interrupted */
2765 * process interrupted - determine whether or not to continue
2768 /* output appropriate interrupted message */
2771 echo(npkgs
== 1 ? MSG_1MORE_PROC
: MSG_MORE_PROC
, npkgs
);
2773 echo(npkgs
== 1 ? MSG_1MORE_INST
: MSG_MORE_INST
, npkgs
);
2776 /* if running with no interaction (-n) do not ask question */
2779 /* if admin required return 'dont continue' */
2787 /* interaction possible: ask question */
2790 n
= ckyorn(ans
, NULL
, NULL
, NULL
, ASK_CONTINUE_ADD
);
2796 if (strchr("yY", *ans
) == NULL
) {
2803 * package can be in a number of formats:
2804 * - file containing package stream (pkgadd -d file [pkgs])
2805 * - directory containing packages (pkgadd -d /dir [pkgs])
2806 * - device containing packages (pkgadd -d diskette1 [pkgs])
2807 * non-global zones can be passed open files and strings as arguments
2808 * - for file containing package stream
2809 * -- the stream can be passed directly to the non-global zone
2811 * -- convert packages to datastream to pass to the non-global zone
2817 unpack_and_check_packages(char **a_pkgList
, char *a_idsName
, char *a_packageDir
)
2819 int savenpkgs
= npkgs
;
2823 /* entry assertions */
2825 assert(a_pkgList
!= (char **)NULL
);
2827 /* entry debugging info */
2829 echoDebug(DBG_UNPACKCHECK_ENTRY
);
2830 echoDebug(DBG_UNPACKCHECK_ARGS
, PSTR(a_idsName
), PSTR(a_packageDir
));
2833 * set flags for applicability check
2836 /* determine if running in the global zone */
2838 if (z_running_in_global_zone() == B_TRUE
) {
2839 flags
|= CAF_IN_GLOBAL_ZONE
;
2844 if (globalZoneOnly
== B_TRUE
) {
2845 flags
|= CAF_SCOPE_GLOBAL
;
2849 * for each package to install:
2850 * - if packages from datastream, unpack package into package dir
2851 * - check applicability of installing package on this system/zone
2854 for (i
= 0; (pkginst
= a_pkgList
[i
]) != NULL
; i
++) {
2855 if (a_idsName
!= (char *)NULL
) {
2856 /* create stream out of package if not already one */
2857 if (unpack_package_from_stream(a_idsName
, pkginst
,
2858 a_packageDir
) == B_FALSE
) {
2859 progerr(ERR_CANNOT_UNPACK_PKGSTRM
,
2860 PSTR(pkginst
), PSTR(a_idsName
),
2861 PSTR(a_packageDir
));
2867 echoDebug(DBG_PKG_IN_DIR
, pkginst
, a_packageDir
);
2870 /* check package applicability */
2871 if (check_applicability(a_packageDir
,
2872 pkginst
, get_inst_root(), flags
) == B_FALSE
) {
2873 progerr(ERR_PKG_NOT_INSTALLABLE
, pkginst
);
2886 * B_TRUE - package list generated
2887 * B_FALSE - failed to generate package list
2888 * Will call quit(n) on fatal error.
2892 get_package_list(char ***r_pkgList
, char **a_argv
, char *a_categories
,
2893 char **a_categoryList
, char *a_idsName
, int *r_repeat
)
2897 /* entry assertions */
2899 assert(r_repeat
!= (int *)NULL
);
2901 /* entry debugging info */
2903 echoDebug(DBG_GETPKGLIST_ENTRY
);
2904 echoDebug(DBG_GETPKGLIST_ARGS
, PSTR(a_idsName
), PSTR(pkgdev
.dirname
),
2908 * get the list of the packages to add
2911 n
= pkgGetPackageList(r_pkgList
, a_argv
, optind
, a_categories
,
2912 a_categoryList
, &pkgdev
);
2915 case -1: /* no packages found */
2916 echoDebug(DBG_PKGLIST_NONFOUND
, PSTR(a_idsName
),
2920 case 0: /* packages found */
2923 default: /* "quit" error */
2924 echoDebug(DBG_PKGLIST_ERROR
, PSTR(a_idsName
),
2930 /* order package list if input data stream specified */
2933 ds_order(*r_pkgList
);
2940 * Name: install_in_one_zone
2941 * Description: Install a single package in a single zone
2942 * Arguments: a_zoneName - pointer to string representing the name of the
2943 * zone to install the package into.
2944 * a_idsName - pointer to string representing the data stream
2945 * device (input data stream) containing the package to
2947 * If this is == NULL the package is assumed to be
2948 * spooled in the zone temporary directory.
2949 * a_zoneAdminFile - pointer to string representing the admin
2950 * file to pass to pkginstall when installing the package.
2951 * If this is == NULL no admin file is given to pkginstall.
2952 * a_zoneTempDir - pointer to string representing the temporary
2953 * directory in which spooled packages can be found if
2954 * a_idsName is == NULL.
2955 * a_altBinDir - pointer to string representing an alternative
2956 * binary location directory to pass to pkginstall.
2957 * If this is == NULL no alternative binary location is
2958 * passed to pkginstall.
2959 * a_scratchName - pointer to string representing the name of the
2960 * scratch zone to use for installation.
2961 * a_zoneState - state of the zone; must be mounted or running.
2962 * a_tmpzn - B_TRUE when this zone is booted by the package
2963 * command or B_FALSE if it was running before.
2965 * NOTE: As a side effect, "ckreturn" is called on the result returned
2966 * from running 'pkginstall' in the zone; this sets several global
2967 * variables which allows the caller to determine the result of
2968 * the installation operation.
2972 install_in_one_zone(char *a_zoneName
, char *a_idsName
,
2973 char *a_zoneAdminFile
, char *a_zoneTempDir
,
2974 char *a_altBinDir
, zone_state_t a_zoneState
, boolean_t a_tmpzn
)
2976 char zoneStreamName
[PATH_MAX
] = {'\0'};
2979 /* entry assertions */
2981 assert(a_zoneName
!= (char *)NULL
);
2982 assert(*a_zoneName
!= '\0');
2984 /* entry debugging info */
2986 echoDebug(DBG_INSTINONEZONE_ENTRY
);
2987 echoDebug(DBG_INSTINONEZONE_ARGS
, a_zoneName
, PSTR(a_idsName
),
2988 PSTR(a_zoneAdminFile
), PSTR(a_zoneTempDir
),
2991 /* echo operation to perform to stdout */
2993 echo(MSG_INSTALL_PKG_IN_ZONE
, pkginst
, a_zoneName
);
2995 /* determine path to the package stream */
2997 if (a_idsName
== (char *)NULL
) {
2998 /* locate temp stream created earlier */
2999 (void) snprintf(zoneStreamName
, sizeof (zoneStreamName
),
3000 "%s/%s.dstream", a_zoneTempDir
, pkginst
);
3002 /* use stream passed in on command line */
3003 (void) snprintf(zoneStreamName
, sizeof (zoneStreamName
),
3007 echoDebug(DBG_INSTALL_IN_ZONE
, pkginst
, a_zoneName
, zoneStreamName
);
3009 n
= pkgZoneInstall(a_zoneName
, a_zoneState
, zoneStreamName
,
3010 a_altBinDir
, a_zoneAdminFile
, a_tmpzn
);
3012 /* set success/fail condition variables */
3016 /* exit debugging info */
3018 echoDebug(DBG_INSTALL_FLAG_VALUES
, "after install", admnflag
, doreboot
,
3019 failflag
, interrupted
, intrflag
, ireboot
, needconsult
,
3020 nullflag
, warnflag
);
3024 * Name: install_in_zones
3025 * Description: Install a single package in the zones that are running from
3027 * Arguments: a_zlst - list of zones to install the package into
3028 * a_idsName - pointer to string representing the data stream
3029 * device (input data stream) containing the package to
3031 * If this is == NULL the package is assumed to be
3032 * spooled in the zone temporary directory.
3033 * a_altBinDir - pointer to string representing an alternative
3034 * binary location directory to pass to pkginstall.
3035 * If this is == NULL no alternative binary location is
3036 * passed to pkginstall.
3037 * a_zoneAdminFile - pointer to string representing the admin
3038 * file to pass to pkginstall when installing the package.
3039 * If this is == NULL no admin file is given to pkginstall.
3040 * a_zoneTempDir - pointer to string representing the temporary
3041 * directory in which spooled packages can be found if
3042 * a_idsName is == NULL.
3046 install_in_zones(zoneList_t a_zlst
, char *a_idsName
, char *a_altBinDir
,
3047 char *a_zoneAdminFile
, char *a_zoneTempDir
)
3051 int zonesSkipped
= 0;
3054 /* entry assertions */
3056 assert(a_zlst
!= (zoneList_t
)NULL
);
3058 /* entry debugging info */
3060 echoDebug(DBG_INSTALLINZONES_ENTRY
);
3061 echoDebug(DBG_INSTALLINZONES_ARGS
, PSTR(a_idsName
),
3062 PSTR(a_zoneAdminFile
), PSTR(a_zoneTempDir
));
3064 /* process each zone in the list */
3067 (zoneName
= z_zlist_get_zonename(a_zlst
, zoneIndex
)) != NULL
;
3070 /* skip the zone if it is NOT running */
3072 zst
= z_zlist_get_current_state(a_zlst
, zoneIndex
);
3073 if (zst
!= ZONE_STATE_RUNNING
&& zst
!= ZONE_STATE_MOUNTED
) {
3075 echoDebug(DBG_SKIPPING_ZONE
, zoneName
);
3079 /* install the package in this zone */
3081 install_in_one_zone(z_zlist_get_scratch(a_zlst
, zoneIndex
),
3082 a_idsName
, a_zoneAdminFile
, a_zoneTempDir
, a_altBinDir
,
3086 return (zonesSkipped
);
3090 * Name: boot_and_install_in_zones
3091 * Description: Install a single package in the zones that are NOT running from
3092 * a list of zones - each zone is booted, the package installed,
3093 * and the zone is halted
3094 * Arguments: a_zlst - list of zones to install the package into
3095 * a_idsName - pointer to string representing the data stream
3096 * device (input data stream) containing the package to
3098 * If this is == NULL the package is assumed to be
3099 * spooled in the zone temporary directory.
3100 * a_altBinDir - pointer to string representing an alternative
3101 * binary location directory to pass to pkginstall.
3102 * If this is == NULL no alternative binary location is
3103 * passed to pkginstall.
3104 * a_zoneAdminFile - pointer to string representing the admin
3105 * file to pass to pkginstall when installing the package.
3106 * If this is == NULL no admin file is given to pkginstall.
3107 * a_zoneTempDir - pointer to string representing the temporary
3108 * directory in which spooled packages can be found if
3109 * a_idsName is == NULL.
3113 boot_and_install_in_zones(zoneList_t a_zlst
, char *a_idsName
, char *a_altBinDir
,
3114 char *a_zoneAdminFile
, char *a_zoneTempDir
)
3119 int zonesSkipped
= 0;
3122 /* entry assertions */
3124 assert(a_zlst
!= (zoneList_t
)NULL
);
3126 /* entry debugging info */
3128 echoDebug(DBG_BOOTINSTALLINZONES_ENTRY
);
3129 echoDebug(DBG_BOOTINSTALLINZONES_ARGS
, PSTR(a_idsName
),
3130 PSTR(a_zoneAdminFile
), PSTR(a_zoneTempDir
));
3132 /* process each zone in the list */
3135 (zoneName
= z_zlist_get_zonename(a_zlst
, zoneIndex
)) != NULL
;
3138 /* skip the zone if it IS running */
3140 zst
= z_zlist_get_current_state(a_zlst
, zoneIndex
);
3141 if (zst
== ZONE_STATE_RUNNING
|| zst
== ZONE_STATE_MOUNTED
) {
3142 echoDebug(DBG_SKIPPING_ZONE_BOOT
, zoneName
);
3146 /* skip the zone if it is NOT bootable */
3148 if (z_zlist_is_zone_runnable(a_zlst
, zoneIndex
) == B_FALSE
) {
3149 echo(MSG_SKIPPING_ZONE_NOT_RUNNABLE
, zoneName
);
3150 echoDebug(DBG_SKIPPING_ZONE_NOT_RUNNABLE
, zoneName
);
3154 /* mount up the zone */
3156 echo(MSG_BOOTING_ZONE
, zoneName
);
3157 echoDebug(DBG_BOOTING_ZONE
, zoneName
);
3159 b
= z_zlist_change_zone_state(a_zlst
, zoneIndex
,
3160 ZONE_STATE_MOUNTED
);
3162 progerr(ERR_CANNOT_BOOT_ZONE
, zoneName
);
3163 /* set fatal error return condition */
3169 /* install the package in this zone */
3171 install_in_one_zone(z_zlist_get_scratch(a_zlst
, zoneIndex
),
3172 a_idsName
, a_zoneAdminFile
, a_zoneTempDir
, a_altBinDir
,
3173 ZONE_STATE_MOUNTED
, B_TRUE
);
3175 /* restore original state of zone */
3177 echo(MSG_RESTORE_ZONE_STATE
, zoneName
);
3178 echoDebug(DBG_RESTORE_ZONE_STATE
, zoneName
);
3180 b
= z_zlist_restore_zone_state(a_zlst
, zoneIndex
);
3183 return (zonesSkipped
);
3187 * Name: pkginstall_check_in_one_zone
3188 * Description: Do a pre install check of a single package in a single zone
3189 * Arguments: a_zoneName - pointer to string representing the name of the
3190 * zone to check install the package in.
3191 * a_idsName - pointer to string representing the data stream
3192 * device (input data stream) containing the package to
3193 * be check installed.
3194 * If this is == NULL the package is assumed to be
3195 * spooled in the zone temporary directory.
3196 * a_zoneAdminFile - pointer to string representing the admin
3197 * file to pass to pkginstall when installing the package.
3198 * If this is == NULL no admin file is given to pkginstall.
3199 * a_zoneTempDir - pointer to string representing the temporary
3200 * directory in which spooled packages can be found if
3201 * a_idsName is == NULL.
3202 * a_altBinDir - pointer to string representing an alternative
3203 * binary location directory to pass to pkginstall.
3204 * If this is == NULL no alternative binary location is
3205 * passed to pkginstall.
3206 * a_scratchName - pointer to string representing the name of the
3207 * scratch zone to use for installation.
3208 * a_zoneState - state of the zone; must be mounted or running.
3209 * a_tmpzn - B_TRUE when this zone is booted by the package
3210 * command or B_FALSE if it was running before.
3212 * NOTE: As a side effect, "ckreturn" is called on the result returned
3213 * from running 'pkginstall' in the zone; this sets several global
3214 * variables which allows the caller to determine the result of
3215 * the pre installation check operation.
3219 pkginstall_check_in_one_zone(char *a_zoneName
,
3220 char *a_idsName
, char *a_zoneAdminFile
, char *a_zoneTempDir
,
3221 char *a_altBinDir
, char *a_scratchName
, zone_state_t a_zoneState
,
3224 char preinstallcheckPath
[PATH_MAX
+1];
3225 char zoneStreamName
[PATH_MAX
] = {'\0'};
3228 echo(MSG_CHECKINSTALL_PKG_IN_ZONE
, pkginst
, a_zoneName
);
3229 echoDebug(MSG_CHECKINSTALL_PKG_IN_ZONE
, pkginst
, a_zoneName
);
3231 (void) snprintf(preinstallcheckPath
, sizeof (preinstallcheckPath
),
3232 "%s/%s.%s.preinstallcheck.txt", a_zoneTempDir
, pkginst
,
3235 if (a_idsName
== (char *)NULL
) {
3236 /* locate temporary stream created earlier */
3237 (void) snprintf(zoneStreamName
, sizeof (zoneStreamName
),
3238 "%s/%s.dstream", a_zoneTempDir
, pkginst
);
3240 (void) snprintf(zoneStreamName
, sizeof (zoneStreamName
),
3244 echoDebug(DBG_CHECKINSTALL_IN_ZONE
, pkginst
, a_zoneName
,
3247 n
= pkgZoneCheckInstall(a_scratchName
, a_zoneState
, zoneStreamName
,
3248 a_altBinDir
, a_zoneAdminFile
, preinstallcheckPath
, a_tmpzn
);
3250 /* set success/fail condition variables */
3254 echoDebug(DBG_INSTALL_FLAG_VALUES
, "after preinstall check",
3255 admnflag
, doreboot
, failflag
, interrupted
, intrflag
,
3256 ireboot
, needconsult
, nullflag
, warnflag
);
3260 * Name: pkginstall_check_in_zones
3261 * Description: Check installation of a single package in the zones that
3262 * are running from a list of zones
3263 * Arguments: a_zlst - list of zones to check install the package
3264 * a_idsName - pointer to string representing the data stream
3265 * device (input data stream) containing the package to
3266 * be check installed.
3267 * If this is == NULL the package is assumed to be
3268 * spooled in the zone temporary directory.
3269 * a_altBinDir - pointer to string representing an alternative
3270 * binary location directory to pass to pkginstall.
3271 * If this is == NULL no alternative binary location is
3272 * passed to pkginstall.
3273 * a_zoneAdminFile - pointer to string representing the admin
3274 * file to pass to pkginstall when checking the installing
3276 * If this is == NULL no admin file is given to pkginstall.
3277 * a_zoneTempDir - pointer to string representing the temporary
3278 * directory in which spooled packages can be found if
3279 * a_idsName is == NULL.
3283 pkginstall_check_in_zones(zoneList_t a_zlst
, char *a_idsName
, char *a_altBinDir
,
3284 char *a_zoneAdminFile
, char *a_zoneTempDir
)
3288 int zonesSkipped
= 0;
3292 (zoneName
= z_zlist_get_zonename(a_zlst
, zoneIndex
)) != NULL
;
3295 zst
= z_zlist_get_current_state(a_zlst
, zoneIndex
);
3296 if (zst
!= ZONE_STATE_RUNNING
&& zst
!= ZONE_STATE_MOUNTED
) {
3298 echoDebug(DBG_SKIPPING_ZONE
, zoneName
);
3302 pkginstall_check_in_one_zone(zoneName
, a_idsName
,
3303 a_zoneAdminFile
, a_zoneTempDir
, a_altBinDir
,
3304 z_zlist_get_scratch(a_zlst
, zoneIndex
), zst
, B_FALSE
);
3307 return (zonesSkipped
);
3311 * Name: boot_and_pkginstall_check_in_zones
3312 * Description: Check installation of a single package in the zones that
3313 * are NOT running from a list of zones - each zone is booted,
3314 * the package installation is checked, and the zone is halted.
3315 * Arguments: a_zlst - list of zones to install the package into
3316 * a_idsName - pointer to string representing the data stream
3317 * device (input data stream) containing the package to
3318 * be check installed.
3319 * If this is == NULL the package is assumed to be
3320 * spooled in the zone temporary directory.
3321 * a_altBinDir - pointer to string representing an alternative
3322 * binary location directory to pass to pkginstall.
3323 * If this is == NULL no alternative binary location is
3324 * passed to pkginstall.
3325 * a_zoneAdminFile - pointer to string representing the admin
3326 * file to pass to pkginstall when check installing the
3328 * If this is == NULL no admin file is given to pkginstall.
3329 * a_zoneTempDir - pointer to string representing the temporary
3330 * directory in which spooled packages can be found if
3331 * a_idsName is == NULL.
3335 boot_and_pkginstall_check_in_zones(zoneList_t a_zlst
, char *a_idsName
,
3336 char *a_altBinDir
, char *a_zoneAdminFile
, char *a_zoneTempDir
)
3339 int zonesSkipped
= 0;
3344 /* entry assertions */
3346 assert(a_zlst
!= (zoneList_t
)NULL
);
3348 /* entry debugging info */
3350 echoDebug(DBG_BOOTCHECKINSTALLINZONES_ENTRY
);
3351 echoDebug(DBG_BOOTCHECKINSTALLINZONES_ARGS
, PSTR(a_idsName
),
3352 PSTR(a_zoneAdminFile
), PSTR(a_zoneTempDir
));
3354 /* process each zone in the list */
3357 (zoneName
= z_zlist_get_zonename(a_zlst
, zoneIndex
)) != NULL
;
3360 /* skip the zone if it IS running */
3362 zst
= z_zlist_get_current_state(a_zlst
, zoneIndex
);
3363 if (zst
== ZONE_STATE_RUNNING
|| zst
== ZONE_STATE_MOUNTED
) {
3364 echoDebug(DBG_SKIPPING_ZONE_BOOT
, zoneName
);
3368 /* skip the zone if it is NOT bootable */
3370 if (z_zlist_is_zone_runnable(a_zlst
, zoneIndex
) == B_FALSE
) {
3371 echo(MSG_SKIPPING_ZONE_NOT_RUNNABLE
, zoneName
);
3372 echoDebug(DBG_SKIPPING_ZONE_NOT_RUNNABLE
, zoneName
);
3376 /* mount up the zone */
3378 echo(MSG_BOOTING_ZONE
, zoneName
);
3379 echoDebug(DBG_BOOTING_ZONE
, zoneName
);
3381 b
= z_zlist_change_zone_state(a_zlst
, zoneIndex
,
3382 ZONE_STATE_MOUNTED
);
3384 progerr(ERR_CANNOT_BOOT_ZONE
, zoneName
);
3385 /* set fatal error return condition */
3391 /* pre-installation check of the package in this zone */
3393 pkginstall_check_in_one_zone(zoneName
, a_idsName
,
3394 a_zoneAdminFile
, a_zoneTempDir
, a_altBinDir
,
3395 z_zlist_get_scratch(a_zlst
, zoneIndex
),
3396 ZONE_STATE_MOUNTED
, B_TRUE
);
3398 /* restore original state of zone */
3400 echo(MSG_RESTORE_ZONE_STATE
, zoneName
);
3401 echoDebug(DBG_RESTORE_ZONE_STATE
, zoneName
);
3403 b
= z_zlist_restore_zone_state(a_zlst
, zoneIndex
);
3406 return (zonesSkipped
);
3410 * Function: add_packages_in_global_with_zones
3411 * Description: call this function to add a list of packages in the global zone
3412 * when one or more non-global zones exist
3414 * B_TRUE to process next data stream
3419 add_packages_in_global_with_zones(char **a_pkgList
,
3420 char *a_idsName
, int a_repeat
, char *a_altBinDir
,
3421 char *a_device
, zoneList_t a_zlst
)
3423 static char *zoneTempDir
= (char *)NULL
;
3424 static char *zoneAdminFile
= (char *)NULL
;
3428 char instdir
[PATH_MAX
];
3429 char respfile_path
[PATH_MAX
];
3430 char zoneStreamName
[PATH_MAX
] = {'\0'};
3433 int savenpkgs
= npkgs
;
3435 boolean_t globalPresent
;
3437 /* entry assertions */
3439 assert(a_pkgList
!= (char **)NULL
);
3440 assert(a_zlst
!= (zoneList_t
)NULL
);
3442 echoDebug(DBG_ADDPACKAGES_GZ_W_LZ_ENTRY
);
3443 echoDebug(DBG_ADDPACKAGES_GZ_W_LZ_ARGS
, npkgs
,
3444 PSTR(a_idsName
), a_repeat
, PSTR(a_device
));
3446 /* create temporary directory for use by zone operations */
3448 create_zone_tempdir(&zoneTempDir
, tmpdir
);
3450 /* create hands off settings admin file for use in a non-global zone */
3452 create_zone_adminfile(&zoneAdminFile
, zoneTempDir
, admnfile
);
3454 /* determine directory where packages can be found */
3456 if (a_idsName
== (char *)NULL
) {
3457 /* no stream - directory containing packages provided */
3458 packageDir
= pkgdev
.dirname
;
3460 packageDir
= zoneTempDir
;
3463 /* unpack and check all packages */
3465 b
= unpack_and_check_packages(a_pkgList
, a_idsName
, packageDir
);
3471 * if the packages are contained in a directory, convert the
3472 * packages into individual streams because pkgZoneInstall is only able
3473 * to pass a stream to the non-global zone's pkginstall command.
3474 * After this code is executed:
3475 * if the original input was a datastream:
3476 * -> that datastream has been unpacked into "instdir"
3477 * if the original input was a directory with packages in it:
3478 * -> those packages have been placed into a single datastream
3481 if (a_idsName
== (char *)NULL
) {
3482 for (i
= 0; (pkginst
= a_pkgList
[i
]) != NULL
; i
++) {
3485 /* package is not a stream - create one */
3487 (void) snprintf(zoneStreamName
, sizeof (zoneStreamName
),
3488 "%s/%s.dstream", zoneTempDir
, pkginst
);
3490 echoDebug(DBG_CONVERTING_PKG
, packageDir
, pkginst
,
3493 /* set up list of packages to be this package only */
3496 pkgs
[1] = (char *)NULL
;
3498 n
= pkgtrans(packageDir
, zoneStreamName
, pkgs
,
3499 PT_SILENT
|PT_ODTSTREAM
);
3501 progerr(ERR_CANNOT_CONVERT_PKGSTRM
,
3502 pkginst
, packageDir
, zoneStreamName
);
3511 * Phase I - run collect dependency information for all packages for all
3512 * zones - this involves running pkginstall with the "preinstallcheck"
3513 * option which causes all dependency checks to be performed without
3514 * actually doing the installation of the packages. This information is
3515 * gathered in the zone temporary directory and is used later to present
3516 * the dependency check results to the system administrator depending
3517 * on the administration settings.
3520 for (i
= 0; (pkginst
= a_pkgList
[i
]) != NULL
; i
++) {
3522 /* reset interrupted flag before calling pkginstall */
3524 interrupted
= 0; /* last action was NOT quit */
3527 * if this package is marked "install in this zone only", then
3528 * do not check dependencies in any other zone
3531 if (pkgPackageIsThisZone(pkginst
) == B_TRUE
) {
3532 echoDebug(DBG_VERIFY_SKIP_THISZONE
, pkginst
);
3538 * if operation failed in global zone do not propagate
3539 * to any non-global zones
3542 if (interrupted
!= 0) {
3543 echo(MSG_CHECKINSTALL_INTERRUPT_B4_Z
, pkginst
);
3544 echoDebug(MSG_CHECKINSTALL_INTERRUPT_B4_Z
, pkginst
);
3548 echoDebug(DBG_INSTALL_FLAG_VALUES
, "after pkginstall",
3549 admnflag
, doreboot
, failflag
, interrupted
, intrflag
,
3550 ireboot
, needconsult
, nullflag
, warnflag
);
3553 * call pkginstall to verify this package for all non-global
3554 * zones that are currently booted
3557 zonesSkipped
= pkginstall_check_in_zones(a_zlst
, a_idsName
,
3558 a_altBinDir
, admnfile
, zoneTempDir
);
3561 * if any zones were skipped (becuase they are not currently
3562 * booted), boot each zone one at a time and call pkginstall
3563 * to verify this package for each such non-global zone
3566 if (zonesSkipped
> 0) {
3567 echoDebug(DBG_ZONES_SKIPPED
, zonesSkipped
);
3570 boot_and_pkginstall_check_in_zones(a_zlst
,
3571 a_idsName
, a_altBinDir
, admnfile
,
3574 if (zonesSkipped
> 0) {
3575 progerr(ERR_INSTALL_ZONES_SKIPPED
,
3584 * At this point, all of the dependency information has been gathered
3585 * and is ready to be analyzed. This function processes all of that
3586 * dependency information and presents the results to the system
3587 * administrator, depending on the current administration settings.
3590 i
= preinstall_verify(a_pkgList
, a_zlst
, zoneTempDir
);
3592 /* dependency checks failed - exit */
3599 * reset all error return condition variables that may have been
3600 * set during package installation dependency checking so that they
3601 * do not reflect on the success/failure of the actual package
3602 * installation operations
3608 * At this point, all of the dependency checking is completed, and
3609 * the installation of the packages can proceed. Install each package
3610 * one at a time, starting with the global zone, and the for each
3611 * non-global zone that is booted, and then for each non-global zone
3612 * that is not currently booted.
3615 globalPresent
= z_on_zone_spec(GLOBAL_ZONENAME
);
3617 for (i
= 0; (pkginst
= a_pkgList
[i
]) != NULL
; i
++) {
3619 * if immediate reboot required from last package and this is
3620 * not 'pkgask' then suspend installation of remaining packages
3623 if ((ireboot
!= 0) && (askflag
== 0)) {
3624 ptext(stderr
, MSG_SUSPEND_ADD
, pkginst
);
3629 * handle interrupt if the previous pkginstall was interrupted
3632 if (continue_installation() == B_FALSE
) {
3637 * if pkgask, handle response file creation:
3638 * - if the response file is a directory, then create a path to
3639 * -- a package instance within the response file directory.
3640 * - If the response file is NOT a directory, if more than one
3641 * -- package is to be installed.
3644 if ((askflag
!= 0) && (respdir
!= (char *)NULL
)) {
3645 (void) snprintf(respfile_path
, sizeof (respfile_path
),
3646 "%s/%s", respdir
, pkginst
);
3647 respfile
= respfile_path
;
3650 echo(MSG_PROC_INST
, pkginst
, a_device
);
3653 * If we're installing another package in the same
3654 * session, the second through nth pkginstall, must
3655 * continue from where the prior one left off. For this
3656 * reason, the continuation feature (implied by the
3657 * nature of the command) is used for the remaining
3661 if ((i
== 1) && (pkgdrtarg
!= (char *)NULL
)) {
3662 pkgcontsrc
= pkgdrtarg
;
3665 if (globalPresent
) {
3667 * call pkginstall for this package for the global zone
3670 echo(MSG_INSTALLING_PKG_IN_GZ
, pkginst
);
3672 /* reset interrupted flag before calling pkginstall */
3674 interrupted
= 0; /* last action was NOT quit */
3676 n
= pkgInstall(get_inst_root(), NULL
, packageDir
,
3679 /* set success/fail condition variables */
3684 * if operation failed in global zone do not propagate
3685 * to any non-global zones
3688 if (interrupted
!= 0) {
3689 echo(MSG_INSTALL_INTERRUPT_B4_ZONES
, pkginst
);
3690 echoDebug(MSG_INSTALL_INTERRUPT_B4_ZONES
,
3697 * if this package is marked "install in this zone only",
3698 * then only need to install the package in the global zone;
3699 * skip installation in any non-global zones.
3702 if (pkgPackageIsThisZone(pkginst
) == B_TRUE
) {
3703 echoDebug(DBG_INSTALL_SKIP_THISZONE
, pkginst
);
3708 echoDebug(DBG_INSTALL_FLAG_VALUES
, "install in running zones",
3709 admnflag
, doreboot
, failflag
, interrupted
, intrflag
,
3710 ireboot
, needconsult
, nullflag
, warnflag
);
3712 /* install package in currently booted zones */
3714 zonesSkipped
= install_in_zones(a_zlst
, a_idsName
, a_altBinDir
,
3715 zoneAdminFile
, zoneTempDir
);
3717 /* install package in zones that are not currently booted */
3719 if (zonesSkipped
> 0) {
3720 echoDebug(DBG_ZONES_SKIPPED
, zonesSkipped
);
3722 zonesSkipped
= boot_and_install_in_zones(a_zlst
,
3723 a_idsName
, a_altBinDir
, zoneAdminFile
,
3726 if (zonesSkipped
> 0) {
3727 progerr(ERR_INSTALL_ZONES_SKIPPED
,
3733 * package completely installed - remove any temporary stream
3734 * of the package that might have been created
3737 if (a_idsName
== (char *)NULL
) {
3738 /* locate temporary stream created earlier */
3739 (void) snprintf(zoneStreamName
, sizeof (zoneStreamName
),
3740 "%s/%s.dstream", zoneTempDir
, pkginst
);
3741 /* remove stream - no longer needed */
3742 echoDebug(DBG_REMOVING_DSTREAM_PKGDIR
, zoneStreamName
,
3744 (void) remove(zoneStreamName
);
3746 /* remove package - no longer needed */
3747 if (snprintf(instdir
, sizeof (instdir
), "%s/%s",
3748 zoneTempDir
, pkginst
) >= PATH_MAX
) {
3749 progerr(ERR_CANNOT_CREATE_PKGPATH
, tmpdir
);
3752 echoDebug(DBG_REMOVING_PKG_TMPDIR
, instdir
, pkginst
);
3753 (void) remove(instdir
);
3756 /* decrement number of packages left to install */
3761 * if no packages left to install, unmount package source
3762 * device if appropriate
3765 if ((npkgs
<= 0) && (pkgdev
.mount
|| a_idsName
)) {
3768 echoDebug(DBG_UNMOUNTING_DEV
,
3769 PSTR(pkgdev
.mount
));
3770 (void) pkgumount(&pkgdev
);
3776 * all packages in the package list have been installed.
3777 * Continue with installation if:
3778 * -- immediate reboot is NOT required
3779 * -- there are more packages to install
3780 * -- the package source is a path to a file
3781 * else return do NOT continue.
3784 if ((ireboot
== 0) && (a_repeat
!= 0) &&
3785 (pkgdev
.pathname
== (char *)NULL
)) {
3789 /* return 'dont continue' */
3795 * Function: add_packages_in_nonglobal_zone
3796 * Description: call this function to add a list of packages in a non-global
3799 * B_TRUE to process next data stream
3804 add_packages_in_nonglobal_zone(char **a_pkgList
,
3805 char *a_idsName
, int a_repeat
, char *a_altBinDir
, char *a_device
)
3807 static char *zoneTempDir
= (char *)NULL
;
3810 char respfile_path
[PATH_MAX
];
3814 int savenpkgs
= npkgs
;
3816 /* entry assertions */
3818 assert(a_pkgList
!= (char **)NULL
);
3820 /* entry debugging info */
3822 echoDebug(DBG_ADDPACKAGES_LZ_ENTRY
);
3823 echoDebug(DBG_ADDPACKAGES_LZ_ARGS
, npkgs
, PSTR(a_idsName
),
3824 a_repeat
, PSTR(a_device
));
3826 /* create temporary directory for use by zone operations */
3828 create_zone_tempdir(&zoneTempDir
, tmpdir
);
3831 * package can be in a number of formats:
3832 * - file containing package stream (pkgadd -d file [pkgs])
3833 * - directory containing packages (pkgadd -d /dir [pkgs])
3834 * - device containing packages (pkgadd -d diskette1 [pkgs])
3835 * non-global zones can be passed open file drescriptors and
3836 * strings as arguments
3837 * - for file containing package stream
3838 * -- the stream can be passed directly to the non-global zone
3840 * -- convert packages to datastream to pass to the non-global zone
3844 /* determine directory where packages can be found */
3846 if (a_idsName
== (char *)NULL
) {
3847 /* no stream - directory containing packages provided */
3848 packageDir
= pkgdev
.dirname
;
3850 packageDir
= zoneTempDir
;
3853 b
= unpack_and_check_packages(a_pkgList
, a_idsName
, packageDir
);
3859 * this is the main loop where all of the packages (as listed in the
3860 * package list) are added one at a time.
3863 for (i
= 0; (pkginst
= a_pkgList
[i
]) != NULL
; i
++) {
3870 * this is the main loop where all of the packages (as listed in the
3871 * package list) are added one at a time.
3874 for (i
= 0; (pkginst
= a_pkgList
[i
]) != NULL
; i
++) {
3876 * if immediate reboot required from last package and this is
3877 * not 'pkgask' then suspend installation of remaining packages
3880 if ((ireboot
!= 0) && (askflag
== 0)) {
3881 ptext(stderr
, MSG_SUSPEND_ADD
, pkginst
);
3886 * handle interrupt if the previous pkginstall was interrupted
3889 if (continue_installation() == B_FALSE
) {
3894 * if pkgask, handle response file creation:
3895 * - if the response file is a directory, then create a path to
3896 * -- a package instance within the response file directory.
3897 * - If the response file is NOT a directory, if more than one
3898 * -- package is to be installed.
3901 if ((askflag
!= 0) && (respdir
!= (char *)NULL
)) {
3902 (void) snprintf(respfile_path
, sizeof (respfile_path
),
3903 "%s/%s", respdir
, pkginst
);
3904 respfile
= respfile_path
;
3907 echo(MSG_PROC_INST
, pkginst
, a_device
);
3910 * If we're installing another package in the same
3911 * session, the second through nth pkginstall, must
3912 * continue from where the prior one left off. For this
3913 * reason, the continuation feature (implied by the
3914 * nature of the command) is used for the remaining
3918 if ((i
== 1) && (pkgdrtarg
!= (char *)NULL
)) {
3919 pkgcontsrc
= pkgdrtarg
;
3922 /* reset interrupted flag before calling pkginstall */
3924 interrupted
= 0; /* last action was NOT quit */
3926 /* call pkginstall for this package */
3928 n
= pkgInstall(get_inst_root(), NULL
,
3929 packageDir
, a_altBinDir
);
3931 /* set success/fail condition variables */
3935 /* decrement number of packages left to install */
3940 * if no packages left to install, unmount package source
3941 * device if appropriate
3944 if ((npkgs
<= 0) && (pkgdev
.mount
|| a_idsName
)) {
3947 (void) pkgumount(&pkgdev
);
3953 * all packages in the package list have been installed.
3954 * Continue with installation if:
3955 * -- immediate reboot is NOT required
3956 * -- there are more packages to install
3957 * -- the package source is a path to a file
3958 * else return do NOT continue.
3961 if ((ireboot
== 0) && (a_repeat
!= 0) &&
3962 (pkgdev
.pathname
== (char *)NULL
)) {
3966 /* return 'dont continue' */
3972 * Function: add_packages_in_global_no_zones
3973 * Description: call this function to add a list of packages in the global zone
3974 * when no non-global zones exist
3976 * B_TRUE to process next data stream
3981 add_packages_in_global_no_zones(char **a_pkgList
,
3982 char *a_idsName
, int a_repeat
, char *a_altBinDir
, char *a_device
)
3986 char respfile_path
[PATH_MAX
];
3989 /* entry assertions */
3991 assert(a_pkgList
!= (char **)NULL
);
3993 echoDebug(DBG_ADDPACKAGES_GZ_NO_LZ_ENTRY
);
3994 echoDebug(DBG_ADDPACKAGES_GZ_NO_LZ_ARGS
, npkgs
,
3995 PSTR(a_idsName
), a_repeat
, PSTR(a_device
));
3998 * set flags for applicability check
4001 /* in the global zone */
4003 flags
|= CAF_IN_GLOBAL_ZONE
;
4007 if (globalZoneOnly
== B_TRUE
) {
4008 flags
|= CAF_SCOPE_GLOBAL
;
4012 * this is the main loop where all of the packages (as listed in the
4013 * package list) are added one at a time.
4016 for (i
= 0; (pkginst
= a_pkgList
[i
]) != NULL
; i
++) {
4018 * if immediate reboot required from last package and this is
4019 * not 'pkgask' then suspend installation of remaining packages
4022 if ((ireboot
!= 0) && (askflag
== 0)) {
4023 ptext(stderr
, MSG_SUSPEND_ADD
, pkginst
);
4028 * handle interrupt if the previous pkginstall was interrupted
4031 if (continue_installation() == B_FALSE
) {
4036 * check package applicability to install in this context
4039 if (check_applicability(pkgdev
.dirname
,
4040 pkginst
, get_inst_root(), flags
) == B_FALSE
) {
4041 progerr(ERR_PKG_NOT_APPLICABLE
, pkginst
);
4046 * if pkgask, handle response file creation:
4047 * - if the response file is a directory, then create a path to
4048 * -- a package instance within the response file directory.
4049 * - If the response file is NOT a directory, if more than one
4050 * -- package is to be installed.
4053 if ((askflag
!= 0) && (respdir
!= (char *)NULL
)) {
4054 (void) snprintf(respfile_path
, sizeof (respfile_path
),
4055 "%s/%s", respdir
, pkginst
);
4056 respfile
= respfile_path
;
4059 echo(MSG_PROC_INST
, pkginst
, a_device
);
4062 * If we're installing another package in the same
4063 * session, the second through nth pkginstall, must
4064 * continue from where the prior one left off. For this
4065 * reason, the continuation feature (implied by the
4066 * nature of the command) is used for the remaining
4070 if ((i
== 1) && (pkgdrtarg
!= (char *)NULL
)) {
4071 pkgcontsrc
= pkgdrtarg
;
4074 /* reset interrupted flag before calling pkginstall */
4076 interrupted
= 0; /* last action was NOT quit */
4078 /* call pkginstall for this package */
4080 n
= pkgInstall(get_inst_root(), a_idsName
,
4081 pkgdev
.dirname
, a_altBinDir
);
4083 /* set success/fail condition variables */
4087 /* decrement number of packages left to install */
4092 * if no packages left to install, unmount package source
4093 * device if appropriate
4096 if ((npkgs
<= 0) && (pkgdev
.mount
|| a_idsName
)) {
4099 (void) pkgumount(&pkgdev
);
4105 * all packages in the package list have been installed.
4106 * Continue with installation if:
4107 * -- immediate reboot is NOT required
4108 * -- there are more packages to install
4109 * -- the package source is a path to a file
4110 * else return do NOT continue.
4113 if ((ireboot
== 0) && (a_repeat
!= 0) &&
4114 (pkgdev
.pathname
== (char *)NULL
)) {
4118 /* return 'dont continue' */
4125 * B_TRUE to process next data stream
4130 add_packages(char **a_pkgList
,
4131 char *a_idsName
, int a_repeat
, char *a_altBinDir
, char *a_device
,
4132 boolean_t a_noZones
)
4137 /* entry assertions */
4139 assert(a_pkgList
!= (char **)NULL
);
4141 echoDebug(DBG_ADDPACKAGES_ENTRY
);
4142 echoDebug(DBG_ADDPACKAGES_ARGS
, npkgs
, PSTR(a_idsName
),
4143 a_repeat
, PSTR(a_altBinDir
), PSTR(a_device
));
4146 * if running in the global zone AND one or more non-global
4147 * zones exist, add packages in a 'zones aware' manner, else
4148 * add packages in the standard 'non-zones aware' manner.
4151 if ((a_noZones
== B_FALSE
) && (z_running_in_global_zone() == B_FALSE
)) {
4152 /* in non-global zone */
4154 echoDebug(DBG_IN_LZ
);
4156 b
= z_lock_this_zone(ZLOCKS_PKG_ADMIN
);
4158 progerr(ERR_CANNOT_LOCK_THIS_ZONE
);
4159 /* set fatal error return condition */
4164 b
= add_packages_in_nonglobal_zone(a_pkgList
, a_idsName
,
4165 a_repeat
, a_altBinDir
, a_device
);
4167 (void) z_unlock_this_zone(ZLOCKS_ALL
);
4172 /* running in the global zone */
4174 b
= z_non_global_zones_exist();
4175 if ((a_noZones
== B_FALSE
) && (b
== B_TRUE
) &&
4176 (globalZoneOnly
== B_FALSE
)) {
4178 echoDebug(DBG_IN_GZ_WITH_LZ
);
4180 /* error if -V specified - what to use in non-global zone? */
4183 progerr(ERR_V_USED_WITH_GZS
);
4187 /* get a list of all non-global zones */
4188 zlst
= z_get_nonglobal_zone_list();
4189 if (zlst
== (zoneList_t
)NULL
) {
4190 progerr(ERR_CANNOT_GET_ZONE_LIST
);
4194 /* need to lock all of the zones */
4196 quitSetZonelist(zlst
);
4197 b
= z_lock_zones(zlst
, ZLOCKS_PKG_ADMIN
);
4199 z_free_zone_list(zlst
);
4200 progerr(ERR_CANNOT_LOCK_ZONES
);
4201 /* set fatal error return condition */
4206 /* add packages to all zones */
4208 b
= add_packages_in_global_with_zones(a_pkgList
,
4209 a_idsName
, a_repeat
, a_altBinDir
, a_device
, zlst
);
4211 /* unlock all zones */
4213 (void) z_unlock_zones(zlst
, ZLOCKS_ALL
);
4214 quitSetZonelist((zoneList_t
)NULL
);
4216 /* free list of all non-global zones */
4218 z_free_zone_list(zlst
);
4223 /* in global zone no non-global zones */
4225 echoDebug(DBG_IN_GZ_NO_LZ
);
4227 b
= z_lock_this_zone(ZLOCKS_PKG_ADMIN
);
4229 progerr(ERR_CANNOT_LOCK_THIS_ZONE
);
4230 /* set fatal error return condition */
4235 b
= add_packages_in_global_no_zones(a_pkgList
, a_idsName
,
4236 a_repeat
, a_altBinDir
, a_device
);
4238 (void) z_unlock_this_zone(ZLOCKS_ALL
);