9765 pkgadd has no Z option
[unleashed.git] / usr / src / cmd / svr4pkg / pkgadd / main.c
blob4f05b2831846710a57c62f926809280da8868418
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
23 * Copyright (c) 2018 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.
43 * System includes
46 #include <stdio.h>
47 #include <limits.h>
48 #include <stdlib.h>
49 #include <unistd.h>
50 #include <string.h>
51 #include <fcntl.h>
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #include <signal.h>
55 #include <errno.h>
56 #include <pkgdev.h>
57 #include <pkginfo.h>
58 #include <pkglocs.h>
59 #include <locale.h>
60 #include <libintl.h>
61 #include <pkgtrans.h>
62 #include <assert.h>
65 * consolidation pkg command library includes
67 #include <pkglib.h>
69 #include <instzones_api.h>
72 * local pkg command library includes
74 #include <install.h>
75 #include <libinst.h>
76 #include <libadm.h>
77 #include <messages.h>
81 * pkgadd local includes
84 #include "quit.h"
87 * imported global variables/functions
90 /* check.c */
91 extern int preinstall_verify(char **a_pkgList, zoneList_t a_zlst,
92 char *a_zoneTempDir);
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.
99 extern int ckquit;
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"
189 #endif
191 /* printable string - if string is null results in ??? */
193 #define PSTR(STR) (((STR) == (char *)NULL) ? "???" : (STR))
195 #define MAX_FDS 20
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,
211 boolean_t a_tmpzn);
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,
216 char *a_tmpdir);
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,
220 boolean_t a_tmpzn);
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,
228 char *a_altBinDir);
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,
233 boolean_t a_tmpzn);
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,
250 zoneList_t a_zlst);
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,
256 CAF_T a_flags);
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 * *****************************************************************************
270 * Name: main
271 * Description: main entry point for pkgadd/pkgask
272 * Returns: int
273 * 0 Successful completion
274 * 1 Fatal error.
275 * 2 Warning.
276 * 3 Interruption.
277 * 4 Administration.
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
280 * as appropriate:
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;
291 char *abiPtr;
292 char *altBinDir = (char *)NULL;
293 char *catg_arg = NULL;
294 char *device = NULL; /* dev pkg stored on */
295 char *p;
296 char *q;
297 char *prog;
298 char *prog_full_name = NULL;
299 char *spoolDir = NULL; /* specified with -s */
300 char Rpath[PATH_MAX+1] = {'\0'};
301 int c;
302 int n;
303 int repeat;
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);
323 /* set sane umask */
325 (void) umask(0022);
327 /* tell quit which ckreturn function to call */
329 quitSetCkreturnFunc(&ckreturn);
331 /* initially no source "device" */
333 device = NULL;
335 /* reset npkgs (used as pkg remaining count in quit.c) */
337 npkgs = 0;
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:z")) != EOF) {
353 switch (c) {
356 * Not a public interface: This disables attribute checking.
357 * It speeds up installation a little bit.
359 case 'A':
360 disableAttributes++;
361 break;
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.
375 case 'a':
376 admnfile = flex_device(optarg, 0);
377 break;
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.
384 case 'B':
385 if (optarg[0] == '-') {
386 usage();
387 quit(1);
389 rw_block_size = optarg;
390 break;
393 * Not a public interface: location where package executables
394 * can be found - default is /usr/sadm/install/bin.
396 case 'b':
397 if (optarg[0] == '-') {
398 usage();
399 quit(1);
401 if (!path_valid(optarg)) {
402 progerr(ERR_PATH, optarg);
403 quit(1);
405 if (isdir(optarg) != 0) {
406 p = strerror(errno);
407 progerr(ERR_CANNOT_USE_DIR, optarg, p);
408 quit(1);
410 altBinDir = optarg;
411 break;
414 * Not a public interface: This disables checksum tests on
415 * the source files. It speeds up installation a little bit.
417 case 'C':
418 disableChecksum++;
419 break;
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.
426 case 'c':
427 pkgcontsrc = flex_device(optarg, 0);
428 break;
431 * Not a public interface: This allows designation of a
432 * dryrun file. This pkgadd will create dryrun files
433 * in the directory provided.
435 case 'D':
436 if (optarg[0] == '-') {
437 usage();
438 quit(1);
440 pkgdrtarg = flex_device(optarg, 0);
441 break;
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.
451 case 'd':
452 if (optarg[0] == '-') {
453 usage();
454 quit(1);
456 if (!path_valid(optarg)) {
457 progerr(ERR_PATH, optarg);
458 quit(1);
459 /* NOTREACHED */
462 device = flex_device(optarg, 1);
463 break;
466 * Public interface: install package in global zone only.
468 case 'G':
469 globalZoneOnly = B_TRUE;
470 break;
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.
482 case 'h':
483 set_depend_pkginfo_DB(B_TRUE);
484 break;
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.
493 case 'I':
494 init_install++;
495 break;
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.
504 case 'M':
505 no_map_client = 1;
506 break;
509 * Not a public interface: the -O option allows the behavior
510 * of the package tools to be modified. Recognized options:
511 * -> debug
512 * ---> enable debugging output
513 * -> addzonename
514 * ---> add zone name to appropriate messages
515 * -> nozones
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
530 case 'O':
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 */
536 debugFlag = B_TRUE;
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]);
544 continue;
547 if (strcmp(p,
548 "enable-hollow-package-support") == 0) {
549 set_depend_pkginfo_DB(B_TRUE);
550 continue;
553 if (strcmp(p, "addzonename") == 0) {
554 quitSetZoneName(z_get_zonename());
555 continue;
558 if (strcmp(p, "nozones") == 0) {
559 noZones = B_TRUE;
560 continue;
563 if (strncmp(p, "zonelist=", 9) == 0) {
565 * If colons used as separators,
566 * convert to spaces.
568 q = p + 9;
569 while (*q != '\0') {
570 if (*q == ':') {
571 *q = ' ';
573 q++;
576 if (z_set_zone_spec(p + 9) == -1)
577 quit(1);
578 usedZoneList = B_TRUE;
579 continue;
582 progerr(ERR_INVALID_O_OPTION, p);
583 continue;
585 break;
588 * Public interface: installation occurs in
589 * non-interactive mode. Suppress output of the list of
590 * installed files. The default mode is interactive.
592 case 'n':
593 nointeract++;
594 (void) echoSetFlag(B_FALSE);
595 break;
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).
606 case 'R':
607 if (optarg[0] == '-') {
608 usage();
609 quit(1);
611 /* determine the real path specified */
613 n = resolvepath(optarg, Rpath, sizeof (Rpath)-1);
615 /* use supplied path if not resolvable */
617 if (n == -1) {
618 (void) strlcpy(Rpath, optarg, sizeof (Rpath));
619 } else {
620 /* null terminate string */
621 Rpath[n] = '\0';
624 /* set the alternative root path */
626 if (!set_inst_root(Rpath)) {
627 progerr(ERR_ROOT_CMD);
628 exit(1);
630 break;
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.
639 case 'r':
640 if (optarg[0] == '-') {
641 usage();
642 quit(1);
644 respfile = flex_device(optarg, 2);
645 if (isdir(respfile) == 0)
646 respdir = respfile;
647 break;
650 * Not a public interface: suppress copyright notice being
651 * output during installation.
653 case 'S':
654 suppressCopyright++;
655 break;
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.
662 case 's':
663 spoolDir = flex_device(optarg, 1);
664 break;
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).
671 case 't':
672 disableSaveSpool++;
673 break;
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.
683 case 'V':
684 vfstab_file = flex_device(optarg, 2);
685 no_map_client = 0;
686 break;
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
694 case 'v':
695 pkgverbose++;
696 break;
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.
707 case 'Y':
708 if (optarg[0] == '-') {
709 usage();
710 quit(1);
712 catg_arg = strdup(optarg);
714 if ((category = get_categories(catg_arg)) == NULL) {
715 progerr(ERR_CAT_INV, catg_arg);
716 exit(1);
717 } else if (is_not_valid_length(category)) {
718 progerr(ERR_CAT_LNGTH);
719 exit(1);
721 break;
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
731 * is specified:
732 * - Editable files are installed from the package instance
733 * save area.
734 * - Volatile files are installed from the package instance
735 * save area.
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
739 * save area.
741 case 'z':
742 saveSpoolInstall++;
743 break;
746 * unrecognized option
749 default:
750 usage();
751 return (1);
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);
769 } else {
770 echoDebug(DBG_ENTRY_IN_LZ, prog_full_name, getzoneid(),
771 z_get_zonename());
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,
777 * it is too risky.
780 if (pkgcontsrc && !pkgdrtarg) {
781 progerr(ERR_NO_LIVE_MODE);
782 usage();
783 return (1);
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);
796 return (1);
799 /* -G and zonelist cannot be used together */
801 if (globalZoneOnly && usedZoneList) {
802 progerr(ERR_GZ_USED_TOGETHER);
803 usage();
804 return (1);
807 /* -s cannot be used with either -G or zonelist */
809 if (spoolDir != NULL) {
810 if (globalZoneOnly) {
811 progerr(ERR_SPOOLDIR_USED_WITH_G);
812 usage();
813 return (1);
815 if (usedZoneList) {
816 progerr(ERR_SPOOLDIR_USED_WITH_Z);
817 usage();
818 return (1);
820 if (strcmp(spoolDir, "/var/sadm/pkg") == 0) {
821 progerr(ERR_SPOOLDIR_CANNOT_BE_SYS, "/var/sadm/pkg");
822 usage();
823 return (1);
827 /* pkgask does not support the same options as pkgadd */
829 if (askflag && spoolDir) {
830 progerr(ERR_PKGASK_AND_SPOOLDIR);
831 usage();
832 return (1);
835 if (askflag && nointeract) {
836 progerr(ERR_PKGASK_AND_NOINTERACT);
837 usage();
838 return (1);
841 /* cannot use response file/not-interactive and spool-to directory */
843 if (spoolDir && nointeract) {
844 progerr(ERR_SPOOLDIR_AND_NOINTERACT);
845 usage();
846 return (1);
849 if (spoolDir && respfile) {
850 progerr(ERR_SPOOLDIR_AND_RESPFILE);
851 usage();
852 return (1);
855 if (usedZoneList) {
856 /* Verify supplied zone list valid for the target */
857 if (z_verify_zone_spec() == -1)
858 return (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);
941 quit(1);
942 /* NOTREACHED */
946 /* must be root if not directing results to spool directory */
948 if ((getuid() != 0) && (spoolDir == NULL)) {
949 progerr(ERR_NOT_ROOT, prog);
950 exit(1);
954 * process response file argument
957 if (respfile) {
958 echoDebug(DBG_PKGADD_RESPFILE,
959 respfile, respdir ? respdir : "");
961 if (respfile[0] != '/') {
962 progerr(ERR_RSP_FILE_NOTFULLPATH, respfile);
963 quit(1);
964 /* NOTREACHED */
966 if (respdir == NULL) {
967 if (askflag) {
968 if (access(respfile, F_OK) == 0) {
969 progerr(ERR_NORESP, respfile);
970 quit(1);
971 /* NOTREACHED */
973 } else if (access(respfile, F_OK) != 0) {
974 progerr(ERR_ACCRESP, respfile);
975 quit(1);
976 /* NOTREACHED */
979 } else if (askflag) {
980 progerr(ERR_RSP_FILE_NOT_GIVEN);
981 usage();
982 quit(1);
983 /* NOTREACHED */
986 /* establish temporary directory to use */
988 if ((tmpdir = getenv("TMPDIR")) == NULL) {
989 /* use default - no override specified */
990 tmpdir = P_tmpdir;
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) {
1003 old_pkg = 1;
1007 * See if the user wants to process symlinks consistent with
1008 * the old behavior.
1011 if (getenv("PKG_NONABI_SYMLINKS") != NULL) {
1012 old_symlinks = 1;
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) {
1021 ABI_namelength = 1;
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);
1031 quit(1);
1032 /* NOTREACHED */
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) {
1042 boolean_t b;
1043 int n;
1045 echoDebug(DBG_INSTALLING_TO_SPOOL, spoolDir);
1047 b = open_package_datastream(argc, argv, spoolDir, device,
1048 &repeat, &ids_name, tmpdir,
1049 &pkgdev, optind);
1051 quitSetIdsName(ids_name);
1053 if (b != B_TRUE) {
1054 progerr(ERR_CANNOT_OPEN_PKG_STREAM, PSTR(device));
1055 quit(1);
1058 n = pkgtrans(device, spoolDir, &argv[optind], 0);
1059 quit(n);
1060 /* NOTREACHED */
1064 * error if there are packages on the command line and a category
1065 * was specified
1068 if ((optind < argc) && (catg_arg != NULL)) {
1069 progerr(ERR_PKGS_AND_CAT_PKGADD);
1070 usage();
1071 quit(1);
1072 /* NOTREACHED */
1076 * ********************************************************************
1077 * main package processing "loop"
1078 * ********************************************************************
1081 ids_name = NULL;
1082 quitSetIdsName(ids_name);
1084 for (;;) {
1085 boolean_t b;
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,
1094 &pkgdev, optind);
1096 quitSetIdsName(ids_name);
1098 if (b == B_FALSE) {
1099 echoDebug(ERR_CANNOT_OPEN_PKG_STREAM, PSTR(device));
1100 continue;
1104 * package source data stream open - get the package list
1107 b = get_package_list(&pkglist, argv, catg_arg, category,
1108 ids_name, &repeat);
1110 if (b == B_FALSE) {
1111 echoDebug(DBG_CANNOT_GET_PKGLIST);
1113 progerr(ERR_NOPKGS, pkgdev.dirname);
1114 quit(1);
1115 /* NOTREACHED */
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]);
1127 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
1138 * is a file.
1141 if ((askflag != 0) && (respdir == (char *)NULL) &&
1142 (npkgs > 1)) {
1143 progerr(ERR_TOO_MANY_PKGS);
1144 quit(1);
1145 /* NOTREACHED */
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.
1159 if (ids_name) {
1160 echoDebug(DBG_CLOSING_STREAM, ids_name,
1161 PSTR(pkgdev.dirname));
1162 (void) ds_close(1);
1163 rrmdir(pkgdev.dirname);
1164 ids_name = NULL;
1165 quitSetIdsName(ids_name);
1169 * continue with next sequence of packages if continue set
1172 if (b == B_TRUE) {
1173 continue;
1177 * not continuing - quit with 0 exit code
1180 quit(0);
1181 /* NOTREACHED */
1184 /* NOTREACHED */
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
1200 * running.
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
1213 * is stored.
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)
1218 * 0 - success
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"
1228 static int
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)
1233 char *arg[MAXARGS];
1234 char *p;
1235 char adminfd_path[PATH_MAX];
1236 char path[PATH_MAX];
1237 char pkgstreamfd_path[PATH_MAX];
1238 int fds[MAX_FDS];
1239 int maxfds;
1240 int n;
1241 int nargs;
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 */
1263 maxfds = 0;
1266 * generate argument list for call to pkginstall
1269 /* start at argument 0 */
1271 nargs = 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)
1316 if (old_pkg) {
1317 arg[nargs++] = "-o";
1321 * PKG_NONABI_SYMLINKS defined: pass -y to pkginstall; process
1322 * symlinks consistent with old behavior
1325 if (old_symlinks) {
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 */
1350 if (askflag) {
1351 return (0);
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 */
1367 if (a_adminFile) {
1368 int fd;
1369 fd = openLocal(a_adminFile, O_RDONLY, tmpdir);
1370 if (fd < 0) {
1371 progerr(ERR_CANNOT_COPY_LOCAL, a_adminFile,
1372 errno, strerror(errno));
1373 return (1);
1375 (void) snprintf(adminfd_path, sizeof (adminfd_path),
1376 "/proc/self/fd/%d", fd);
1377 fds[maxfds++] = 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);
1426 } else {
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) {
1441 int fd;
1442 fd = openLocal(a_idsName, O_RDONLY, tmpdir);
1443 if (fd < 0) {
1444 progerr(ERR_STREAM_UNAVAILABLE, a_idsName,
1445 pkginst, strerror(errno));
1446 quit(1);
1448 (void) snprintf(pkgstreamfd_path, sizeof (pkgstreamfd_path),
1449 "/proc/self/fd/%d", fd);
1450 fds[maxfds++] = fd;
1451 arg[nargs++] = pkgstreamfd_path;
1452 } else {
1453 progerr(ERR_PKGZONEINSTALL_NO_STREAM);
1454 quit(1);
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 */
1478 fds[maxfds] = -1;
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 */
1499 return (n);
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
1509 * running.
1510 * a_idsName - pointer to string representing the data stream
1511 * device (input data stream) containing the package to
1512 * be installed.
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
1522 * is stored.
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)
1527 * 0 - success
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"
1537 static int
1538 pkgZoneInstall(char *a_zoneName, zone_state_t a_zoneState, char *a_idsName,
1539 char *a_altBinDir, char *a_adminFile, boolean_t a_tmpzn)
1541 char *arg[MAXARGS];
1542 char *p;
1543 char adminfd_path[PATH_MAX];
1544 char path[PATH_MAX];
1545 char pkgstreamfd_path[PATH_MAX];
1546 char respfilefd_path[PATH_MAX];
1547 int fds[MAX_FDS];
1548 int maxfds;
1549 int n;
1550 int nargs;
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),
1563 a_adminFile);
1565 /* generate path to pkginstall */
1567 (void) snprintf(path, sizeof (path), "%s/pkginstall", PKGBIN);
1569 /* start at first file descriptor */
1571 maxfds = 0;
1574 * generate argument list for call to pkginstall
1577 /* start at argument 0 */
1579 nargs = 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 */
1631 if (init_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 */
1641 if (pkgverbose) {
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 */
1666 if (askflag) {
1667 echo(MSG_BYPASSING_ZONE, a_zoneName);
1668 return (0);
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 */
1680 if (a_adminFile) {
1681 int fd;
1682 fd = openLocal(a_adminFile, O_RDONLY, tmpdir);
1683 if (fd < 0) {
1684 progerr(ERR_CANNOT_COPY_LOCAL, a_adminFile,
1685 errno, strerror(errno));
1686 return (1);
1688 (void) snprintf(adminfd_path, sizeof (adminfd_path),
1689 "/proc/self/fd/%d", fd);
1690 fds[maxfds++] = 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
1703 * mode/file
1705 if (pkgdrtarg) {
1706 arg[nargs++] = "-D";
1707 arg[nargs++] = pkgdrtarg;
1711 * pkgadd -c cont: pass -c cont to pkginstall in zone: continuation
1712 * file
1714 if (pkgcontsrc) {
1715 arg[nargs++] = "-c";
1716 arg[nargs++] = pkgcontsrc;
1719 /* pkgadd -r resp: pass -r resp to pkginstall in zone: response file */
1721 if (respfile) {
1722 int fd;
1723 fd = openLocal(respfile, O_RDONLY, tmpdir);
1724 if (fd < 0) {
1725 progerr(ERR_CANNOT_COPY_LOCAL, a_adminFile,
1726 errno, strerror(errno));
1727 return (1);
1729 (void) snprintf(respfilefd_path,
1730 sizeof (respfilefd_path),
1731 "/proc/self/fd/%d", fd);
1732 fds[maxfds++] = 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);
1764 } else {
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) {
1779 int fd;
1780 fd = openLocal(a_idsName, O_RDONLY, tmpdir);
1781 if (fd < 0) {
1782 progerr(ERR_STREAM_UNAVAILABLE, a_idsName,
1783 pkginst, strerror(errno));
1784 quit(1);
1786 (void) snprintf(pkgstreamfd_path, sizeof (pkgstreamfd_path),
1787 "/proc/self/fd/%d", fd);
1788 fds[maxfds++] = fd;
1789 arg[nargs++] = pkgstreamfd_path;
1790 } else {
1791 progerr(ERR_PKGZONEINSTALL_NO_STREAM);
1792 quit(1);
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 */
1816 fds[maxfds] = -1;
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 */
1836 return (n);
1840 * Name: pkgInstall
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
1847 * be installed.
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)
1854 * 0 - success
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.
1870 static int
1871 pkgInstall(char *a_altRoot, char *a_idsName, char *a_pkgDir, char *a_altBinDir)
1873 char *arg[MAXARGS];
1874 char *p;
1875 char path[PATH_MAX];
1876 char buffer[256];
1877 int n, nargs;
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 */
1896 nargs = 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)
1963 if (old_pkg) {
1964 arg[nargs++] = "-o";
1968 * PKG_NONABI_SYMLINKS defined: pass -y to pkginstall; process
1969 * symlinks consistent with old behavior
1972 if (old_symlinks) {
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 */
1993 if (init_install) {
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 */
2005 if (pkgverbose) {
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 */
2033 if (askflag) {
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 */
2045 if (admnfile) {
2046 arg[nargs++] = "-a";
2047 arg[nargs++] = admnfile;
2050 /* pkgadd -D dryrun: pass -D dryrun to pkginstall: dryrun mode/file */
2052 if (pkgdrtarg) {
2053 arg[nargs++] = "-D";
2054 arg[nargs++] = pkgdrtarg;
2057 /* pkgadd -c cont: pass -c cont to pkginstall: continuation file */
2059 if (pkgcontsrc) {
2060 arg[nargs++] = "-c";
2061 arg[nargs++] = pkgcontsrc;
2064 /* pkgadd -V vfstab: pass -V vfstab to pkginstall: alternate vfstab */
2066 if (vfstab_file) {
2067 arg[nargs++] = "-V";
2068 arg[nargs++] = vfstab_file;
2071 /* pkgadd -r resp: pass -r resp to pkginstall: response file */
2073 if (respfile) {
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
2088 * else,
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";
2096 ds_close(1);
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);
2132 } else {
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 */
2174 return (n);
2178 * function to clear out any exisiting error return conditions that may have
2179 * been set by previous calls to ckreturn()
2181 static void
2182 resetreturn()
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
2199 static void
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 */
2209 needconsult = 0;
2211 switch (retcode) {
2212 case 0: /* successful */
2213 case 10:
2214 case 20:
2215 break; /* empty case */
2217 case 1: /* package operation failed (fatal error) */
2218 case 11:
2219 case 21:
2220 failflag++;
2221 interrupted++;
2222 needconsult++;
2223 break;
2225 case 2: /* non-fatal error (warning) */
2226 case 12:
2227 case 22:
2228 warnflag++;
2229 interrupted++;
2230 needconsult++;
2231 break;
2233 case 3: /* user selected quit; operation interrupted */
2234 case 13:
2235 case 23:
2236 intrflag++;
2237 interrupted++;
2238 needconsult++;
2239 break;
2241 case 4: /* admin settings prevented operation */
2242 case 14:
2243 case 24:
2244 admnflag++;
2245 interrupted++;
2246 break;
2248 case 5: /* administration: interaction req (no -n) */
2249 case 15:
2250 case 25:
2251 nullflag++;
2252 interrupted++;
2253 needconsult++;
2254 break;
2256 default:
2257 failflag++;
2258 interrupted++;
2259 needconsult++;
2260 return;
2263 if (retcode >= 20) {
2264 ireboot++;
2265 } else if (retcode >= 10) {
2266 doreboot++;
2270 static void
2271 usage(void)
2273 char *prog = get_prog_name();
2275 if (askflag) {
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,
2279 prog, prog);
2280 } else {
2281 (void) fprintf(stderr, ERR_USAGE_PKGADD_GLOBALZONE,
2282 prog, prog);
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
2296 * to check
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 * Returns: boolean_t
2307 * B_TRUE - the package can be installed
2308 * B_FALSE - the package can not be installed
2311 static boolean_t
2312 check_applicability(char *a_packageDir, char *a_pkgInst, char *a_rootPath,
2313 CAF_T a_flags)
2315 FILE *pkginfoFP;
2316 FILE *pkgmapFP;
2317 boolean_t all_zones; /* pkg is "all zones" only */
2318 boolean_t in_gz_only; /* pkg installed in global zone only */
2319 boolean_t is_hollow; /* pkg is "hollow" */
2320 boolean_t pkg_installed; /* pkg is installed */
2321 boolean_t this_zone; /* pkg is "this zone" only */
2322 boolean_t reqfile_found = B_FALSE;
2323 char instPkg[PKGSIZ+1]; /* installed pkg instance nam */
2324 char instPkgPath[PATH_MAX]; /* installed pkg toplevel dir */
2325 char pkginfoPath[PATH_MAX]; /* pkg 2 install pkginfo file */
2326 char pkgmapPath[PATH_MAX]; /* pkg 2 install pkgmap file */
2327 char pkgpath[PATH_MAX]; /* pkg 2 install toplevel dir */
2328 int len;
2329 char line[LINE_MAX];
2331 /* entry assertions */
2333 assert(a_packageDir != (char *)NULL);
2334 assert(*a_packageDir != '\0');
2335 assert(a_pkgInst != (char *)NULL);
2336 assert(*a_pkgInst != '\0');
2338 /* normalize root path */
2340 if (a_rootPath == (char *)NULL) {
2341 a_rootPath = "";
2344 /* entry debugging info */
2346 echoDebug(DBG_CHECKAPP_ENTRY);
2347 echoDebug(DBG_CHECKAPP_ARGS, a_pkgInst, a_packageDir, a_rootPath);
2350 * calculate paths to various objects
2353 /* path to package to be installed top level (main) directory */
2355 len = snprintf(pkgpath, sizeof (pkgpath), "%s/%s", a_packageDir,
2356 a_pkgInst);
2357 if (len > sizeof (pkgpath)) {
2358 progerr(ERR_CREATE_PATH_2, a_packageDir, a_pkgInst);
2359 return (B_FALSE);
2362 /* error if package top level directory does not exist */
2364 if (isdir(pkgpath) != 0) {
2365 progerr(ERR_NO_PKGDIR, pkgpath, a_pkgInst, strerror(errno));
2366 return (B_FALSE);
2369 /* path to pkginfo file within the package to be installed */
2371 len = snprintf(pkginfoPath, sizeof (pkginfoPath), "%s/pkginfo",
2372 pkgpath);
2373 if (len > sizeof (pkginfoPath)) {
2374 progerr(ERR_CREATE_PATH_2, pkgpath, "pkginfo");
2375 return (B_FALSE);
2378 /* path to highest instance of package currently installed */
2380 pkgLocateHighestInst(instPkgPath, sizeof (instPkgPath),
2381 instPkg, sizeof (instPkg), a_rootPath, a_pkgInst);
2384 * gather information from this package's pkginfo file
2387 pkginfoFP = fopen(pkginfoPath, "r");
2389 if (pkginfoFP == (FILE *)NULL) {
2390 progerr(ERR_NO_PKG_INFOFILE, a_pkgInst, pkginfoPath,
2391 strerror(errno));
2392 return (B_FALSE);
2395 /* determine "HOLLOW" setting for this package */
2397 is_hollow = pkginfoParamTruth(pkginfoFP, PKG_HOLLOW_VARIABLE,
2398 "true", B_FALSE);
2400 /* determine "ALLZONES" setting for this package */
2402 all_zones = pkginfoParamTruth(pkginfoFP, PKG_ALLZONES_VARIABLE,
2403 "true", B_FALSE);
2405 /* determine "THISZONE" setting for this package */
2407 this_zone = pkginfoParamTruth(pkginfoFP, PKG_THISZONE_VARIABLE,
2408 "true", B_FALSE);
2410 /* close pkginfo file */
2412 (void) fclose(pkginfoFP);
2415 * If request file is not found, it may be in the datastream which
2416 * is not yet unpacked. Check in the pkgmap file.
2418 if (isfile(pkgpath, REQUEST_FILE) != 0) {
2420 /* path to pkgmap file within the package to be installed */
2421 (void) snprintf(pkgmapPath, sizeof (pkgmapPath), "%s/pkgmap",
2422 pkgpath);
2424 pkgmapFP = fopen(pkgmapPath, "r");
2426 if (pkgmapFP == NULL) {
2427 progerr(ERR_NO_PKG_MAPFILE, a_pkgInst,
2428 pkgmapPath, strerror(errno));
2429 return (B_FALSE);
2432 while (fgets(line, LINE_MAX, pkgmapFP) != NULL) {
2433 if (strstr(line, " i request") != NULL) {
2434 reqfile_found = B_TRUE;
2435 break;
2438 (void) fclose(pkgmapFP);
2439 } else {
2440 reqfile_found = B_TRUE;
2444 * If this package is not marked for installation in this zone only,
2445 * check to see if this package has a request script. If this package
2446 * does have a request script, then mark the package for installation
2447 * in this zone only. Any package with a request script cannot be
2448 * installed outside of the zone the pkgadd command is being run in,
2449 * nor can such a package be installed as part of a new zone install.
2450 * A new zone install must be non-interactive, which is required
2451 * by all packages integrated into the Solaris WOS.
2454 if ((!this_zone) && (reqfile_found)) {
2455 if (a_flags & CAF_IN_GLOBAL_ZONE) {
2456 echoDebug(DBG_CHECKAPP_THISZONE_REQUEST, a_pkgInst);
2458 this_zone = B_TRUE;
2462 * If this package is already installed, see if the current installation
2463 * of the package has a request file - if it does, then act as though
2464 * the current package to be added has a request file - install the
2465 * package in the current zone only.
2468 if ((!this_zone) && (instPkgPath[0] != '\0') &&
2469 (isfile(instPkgPath, REQUEST_FILE) == 0)) {
2470 if (a_flags & CAF_IN_GLOBAL_ZONE) {
2471 echoDebug(DBG_CHECKAPP_THISZONE_INSTREQ,
2472 a_pkgInst, instPkg);
2474 this_zone = B_TRUE;
2477 /* gather information from the global zone only file */
2479 in_gz_only = B_FALSE;
2480 if (a_flags & CAF_IN_GLOBAL_ZONE) {
2481 in_gz_only = pkgIsPkgInGzOnly(a_rootPath, a_pkgInst);
2484 /* determine if this package is currently installed */
2486 pkg_installed = pkginfoIsPkgInstalled((struct pkginfo **)NULL,
2487 a_pkgInst);
2490 * verify package applicability based on information gathered,
2491 * and validate the three SUNW_PKG_ options:
2493 * -----------|--------------|-------------|-------------|-----------
2494 * - - - - - -| GLOBAL ZONE -| GLOBAL ZONE | LOCAL ZONE | LOCAL ZONE
2495 * - - - - - -| - - pkgadd - | pkgadd -G | pkgadd | pkgadd -G
2496 * ----1------|--------------|-------------|-------------|------------
2497 * ALLZONES f | add to gz | add to gz | add to ls | add to ls
2498 * HOLLOW f | current lz | not to curr | only - - - -| only - - -
2499 * THISZONE f | futr lz - - -| or futr lz | - - - - - - | - - - - - -
2500 * ----2------|--------------|-------------|-------------|------------
2501 * ALLZONES T | add to gz | operation | operation | operation
2502 * HOLLOW f | current lz | not allowed | not allowed | not allowed
2503 * THISZONE f | future lz | - - - - - - | - - - - - - | - - - - - -
2504 * ----3------|--------------|-------------|-------------|------------
2505 * ALLZONES T | add to gz | operation | operation | operation
2506 * HOLLOW T | pkg db only | not allowed | not allowed | not allowed
2507 * THISZONE f | curr/futr lz | - - - - - - | - - - - - - | - - - - - -
2508 * ----4------|--------------|-------------|-------------|------------
2509 * ALLZONES T | bad option | bad option | bad option | bad option
2510 * HOLLOW * | combo - - - -| combo - - - | combo - - - | combo - -
2511 * THISZONE T | - - - - - - -|- - - - - - -|- - - - - - -|- - - - - -
2512 * ----5------|--------------|-------------|-------------|------------
2513 * ALLZONES f | bad option | bad option | bad option | bad option
2514 * HOLLOW T | combo - - - -| combo - - - | combo - - - | combo - - -
2515 * THISZONE * | - - - - - - -| - - - - - - | - - - - - - | - - - - - -
2516 * ----6------|--------------|-------------|-------------|------------
2517 * ALLZONES f | add to gz | add to gz | add to lz | add to lz
2518 * HOLLOW f | not current | not current | only - - - | only - - -
2519 * THISZONE T | or future lz | or futr lz | - - - - - - | - - - - - -
2520 * -----------|--------------|-------------|-------------|-----------
2523 /* pkg "all zones" && "this zone" (#4) */
2525 if (all_zones && this_zone) {
2526 progerr(ERR_ALLZONES_AND_THISZONE, a_pkgInst,
2527 PKG_ALLZONES_VARIABLE, PKG_THISZONE_VARIABLE);
2528 return (B_FALSE);
2531 /* pkg "!all zones" && "hollow" (#5) */
2533 if ((!all_zones) && is_hollow) {
2534 progerr(ERR_NOW_ALLZONES_AND_HOLLOW, a_pkgInst,
2535 PKG_ALLZONES_VARIABLE, PKG_HOLLOW_VARIABLE);
2536 return (B_FALSE);
2539 /* pkg ALLZONES=true & not running in global zone (#2/#3) */
2541 if (all_zones && (!(a_flags & CAF_IN_GLOBAL_ZONE))) {
2542 progerr(ERR_ALLZONES_AND_IN_LZ, a_pkgInst);
2543 return (B_FALSE);
2546 /* pkg "in gz only" & pkg "NOT installed" */
2548 if (in_gz_only && (!pkg_installed)) {
2549 /* MAKE A WARNING */
2550 echo(ERR_IN_GZ_AND_NOT_INSTALLED, a_pkgInst,
2551 pkgGetGzOnlyPath());
2554 /* pkg ALLZONES=true & pkg "in gz only" & pkg "is installed" */
2556 if (all_zones && in_gz_only && pkg_installed) {
2557 progerr(ERR_IN_GZ_AND_ALLZONES_AND_INSTALLED, a_pkgInst);
2558 return (B_FALSE);
2561 /* pkg ALLZONES=true && -G specified (#2/#3) */
2563 if (all_zones && (a_flags & CAF_SCOPE_GLOBAL)) {
2564 progerr(ERR_ALLZONES_AND_G_USED, a_pkgInst);
2565 return (B_FALSE);
2568 /* pkg "!this zone" && "in gz only" & -G not specified */
2570 if ((!this_zone) && in_gz_only && (!(a_flags & CAF_SCOPE_GLOBAL))) {
2571 progerr(ERR_IN_GZ_AND_NO_G_USED, a_pkgInst);
2572 return (B_FALSE);
2576 * If this package is marked 'this zone only', then mark the package
2577 * as "add to this zone only". This is referenced by the various
2578 * add_package_... functions to determine if the package should be
2579 * added to the current zone, or to all zones, depending on the
2580 * zone in which the command is being run.
2583 if (this_zone) {
2584 pkgAddThisZonePackage(a_pkgInst);
2587 return (B_TRUE);
2591 * Name: create_zone_adminfile
2592 * Description: Given a zone temporary directory and optionally an existing
2593 * administration file, generate an administration file that
2594 * can be used to perform "non-interactive" operations in a
2595 * non-global zone.
2596 * Arguments: r_zoneAdminFile - pointer to handle that will contain a
2597 * string representing the path to the temporary
2598 * administration file created - this must be NULL
2599 * before the first call to this function - on
2600 * subsequent calls if the pointer is NOT null then
2601 * the existing string will NOT be overwritten.
2602 * a_zoneTempDir - pointer to string representing the path
2603 * to the zone temporary directory to create the
2604 * temporary administration file in
2605 * a_admnfile - pointer to string representing the path to
2606 * an existing "user" administration file - the
2607 * administration file created will contain the
2608 * settings contained in this file, modified as
2609 * appropriate to supress any interaction;
2610 * If this is == NULL then the administration file
2611 * created will not contain any extra settings
2612 * Returns: void
2613 * NOTE: Any string returned is placed in new storage for the
2614 * calling method. The caller must use 'free' to dispose
2615 * of the storage once the string is no longer needed.
2616 * NOTE: On any error this function will call 'quit(1)'
2619 static void
2620 create_zone_adminfile(char **r_zoneAdminFile, char *a_zoneTempDir,
2621 char *a_admnfile)
2623 boolean_t b;
2625 /* entry assertions */
2627 assert(r_zoneAdminFile != (char **)NULL);
2628 assert(a_zoneTempDir != (char *)NULL);
2629 assert(*a_zoneTempDir != '\0');
2631 /* entry debugging info */
2633 echoDebug(DBG_CREATE_ZONE_ADMINFILE, a_zoneTempDir, PSTR(a_admnfile));
2635 /* if temporary name already exists, do not overwrite */
2637 if (*r_zoneAdminFile != (char *)NULL) {
2638 return;
2641 /* create temporary name */
2643 *r_zoneAdminFile = tempnam(a_zoneTempDir, "zadmn");
2644 b = z_create_zone_admin_file(*r_zoneAdminFile, a_admnfile);
2645 if (b == B_FALSE) {
2646 progerr(ERR_CREATE_TMPADMIN, *r_zoneAdminFile,
2647 strerror(errno));
2648 quit(1);
2649 /* NOTREACHED */
2652 echoDebug(DBG_CREATED_ZONE_ADMINFILE, *r_zoneAdminFile);
2656 * Name: create_zone_tempdir
2657 * Description: Given a system temporary directory, create a "zone" specific
2658 * temporary directory and return the path to the directory
2659 * created.
2660 * Arguments: r_zoneTempDir - pointer to handle that will contain a
2661 * string representing the path to the temporary
2662 * directory created - this must be NULL before the
2663 * first call to this function - on subsequent calls
2664 * if the pointer is NOT null then the existing string
2665 * will NOT be overwritten.
2666 * a_zoneTempDir - pointer to string representing the path
2667 * to the system temporary directory to create the
2668 * temporary zone directory in
2669 * Returns: void
2670 * NOTE: Any string returned is placed in new storage for the
2671 * calling method. The caller must use 'free' to dispose
2672 * of the storage once the string is no longer needed.
2673 * NOTE: On any error this function will call 'quit(1)'
2674 * NOTE: This function calls "quitSetZoneTmpdir" on success to
2675 * register the directory created with quit() so that the
2676 * directory will be automatically deleted on exit.
2679 static void
2680 create_zone_tempdir(char **r_zoneTempDir, char *a_tmpdir)
2682 boolean_t b;
2684 /* entry assertions */
2686 assert(r_zoneTempDir != (char **)NULL);
2687 assert(a_tmpdir != (char *)NULL);
2688 assert(*a_tmpdir != '\0');
2690 /* entry debugging info */
2692 echoDebug(DBG_CREATE_ZONE_TEMPDIR, a_tmpdir);
2694 /* if temporary directory already exists, do not overwrite */
2696 if (*r_zoneTempDir != (char *)NULL) {
2697 return;
2700 /* create temporary directory */
2702 b = setup_temporary_directory(r_zoneTempDir, a_tmpdir, "ztemp");
2703 if (b == B_FALSE) {
2704 progerr(ERR_ZONETEMPDIR, a_tmpdir, strerror(errno));
2705 quit(1);
2706 /* NOTREACHED */
2709 /* register with quit() so directory is removed on exit */
2711 quitSetZoneTmpdir(*r_zoneTempDir);
2713 /* exit debugging info */
2715 echoDebug(DBG_CREATED_ZONE_TEMPDIR, *r_zoneTempDir);
2719 * Name: continue_installation
2720 * Description: Called from within a loop that is installing packages,
2721 * this function examines various global variables and decides
2722 * whether or not to ask an appropriate question, and wait for
2723 * and appropriate reply.
2724 * Arguments: <<global variables>>
2725 * Returns: B_TRUE - continue processing with next package
2726 * B_FALSE - do not continue processing with next package
2729 static boolean_t
2730 continue_installation(void)
2732 char ans[MAX_INPUT];
2733 int n;
2735 /* return TRUE if not interrupted */
2737 if (!interrupted) {
2738 return (B_TRUE);
2742 * process interrupted - determine whether or not to continue
2745 /* output appropriate interrupted message */
2747 if (askflag) {
2748 echo(npkgs == 1 ? MSG_1MORE_PROC : MSG_MORE_PROC, npkgs);
2749 } else {
2750 echo(npkgs == 1 ? MSG_1MORE_INST : MSG_MORE_INST, npkgs);
2753 /* if running with no interaction (-n) do not ask question */
2755 if (nointeract) {
2756 /* if admin required return 'dont continue' */
2757 if (needconsult) {
2758 return (B_FALSE);
2760 ckquit = 1;
2761 return (B_TRUE);
2764 /* interaction possible: ask question */
2766 ckquit = 0;
2767 n = ckyorn(ans, NULL, NULL, NULL, ASK_CONTINUE_ADD);
2768 if (n != 0) {
2769 quit(n);
2770 /* NOTREACHED */
2772 ckquit = 1;
2773 if (strchr("yY", *ans) == NULL) {
2774 return (B_FALSE);
2776 return (B_TRUE);
2780 * package can be in a number of formats:
2781 * - file containing package stream (pkgadd -d file [pkgs])
2782 * - directory containing packages (pkgadd -d /dir [pkgs])
2783 * - device containing packages (pkgadd -d diskette1 [pkgs])
2784 * non-global zones can be passed open files and strings as arguments
2785 * - for file containing package stream
2786 * -- the stream can be passed directly to the non-global zone
2787 * - for directory
2788 * -- convert packages to datastream to pass to the non-global zone
2789 * - for device
2790 * -- ?
2793 static boolean_t
2794 unpack_and_check_packages(char **a_pkgList, char *a_idsName, char *a_packageDir)
2796 int savenpkgs = npkgs;
2797 int i;
2798 CAF_T flags = 0;
2800 /* entry assertions */
2802 assert(a_pkgList != (char **)NULL);
2804 /* entry debugging info */
2806 echoDebug(DBG_UNPACKCHECK_ENTRY);
2807 echoDebug(DBG_UNPACKCHECK_ARGS, PSTR(a_idsName), PSTR(a_packageDir));
2810 * set flags for applicability check
2813 /* determine if running in the global zone */
2815 if (z_running_in_global_zone() == B_TRUE) {
2816 flags |= CAF_IN_GLOBAL_ZONE;
2819 /* set -G flag */
2821 if (globalZoneOnly == B_TRUE) {
2822 flags |= CAF_SCOPE_GLOBAL;
2826 * for each package to install:
2827 * - if packages from datastream, unpack package into package dir
2828 * - check applicability of installing package on this system/zone
2831 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
2832 if (a_idsName != (char *)NULL) {
2833 /* create stream out of package if not already one */
2834 if (unpack_package_from_stream(a_idsName, pkginst,
2835 a_packageDir) == B_FALSE) {
2836 progerr(ERR_CANNOT_UNPACK_PKGSTRM,
2837 PSTR(pkginst), PSTR(a_idsName),
2838 PSTR(a_packageDir));
2840 npkgs = savenpkgs;
2841 return (B_FALSE);
2843 } else {
2844 echoDebug(DBG_PKG_IN_DIR, pkginst, a_packageDir);
2847 /* check package applicability */
2848 if (check_applicability(a_packageDir,
2849 pkginst, get_inst_root(), flags) == B_FALSE) {
2850 progerr(ERR_PKG_NOT_INSTALLABLE, pkginst);
2851 npkgs = savenpkgs;
2852 return (B_FALSE);
2854 npkgs--;
2857 npkgs = savenpkgs;
2858 return (B_TRUE);
2862 * returns:
2863 * B_TRUE - package list generated
2864 * B_FALSE - failed to generate package list
2865 * Will call quit(n) on fatal error.
2868 static boolean_t
2869 get_package_list(char ***r_pkgList, char **a_argv, char *a_categories,
2870 char **a_categoryList, char *a_idsName, int *r_repeat)
2872 int n;
2874 /* entry assertions */
2876 assert(r_repeat != (int *)NULL);
2878 /* entry debugging info */
2880 echoDebug(DBG_GETPKGLIST_ENTRY);
2881 echoDebug(DBG_GETPKGLIST_ARGS, PSTR(a_idsName), PSTR(pkgdev.dirname),
2882 *r_repeat);
2885 * get the list of the packages to add
2888 n = pkgGetPackageList(r_pkgList, a_argv, optind, a_categories,
2889 a_categoryList, &pkgdev);
2891 switch (n) {
2892 case -1: /* no packages found */
2893 echoDebug(DBG_PKGLIST_NONFOUND, PSTR(a_idsName),
2894 pkgdev.dirname);
2895 return (B_FALSE);
2897 case 0: /* packages found */
2898 break;
2900 default: /* "quit" error */
2901 echoDebug(DBG_PKGLIST_ERROR, PSTR(a_idsName),
2902 pkgdev.dirname, n);
2903 quit(n);
2904 /* NOTREACHED */
2907 /* order package list if input data stream specified */
2909 if (a_idsName) {
2910 ds_order(*r_pkgList);
2913 return (B_TRUE);
2917 * Name: install_in_one_zone
2918 * Description: Install a single package in a single zone
2919 * Arguments: a_zoneName - pointer to string representing the name of the
2920 * zone to install the package into.
2921 * a_idsName - pointer to string representing the data stream
2922 * device (input data stream) containing the package to
2923 * be installed.
2924 * If this is == NULL the package is assumed to be
2925 * spooled in the zone temporary directory.
2926 * a_zoneAdminFile - pointer to string representing the admin
2927 * file to pass to pkginstall when installing the package.
2928 * If this is == NULL no admin file is given to pkginstall.
2929 * a_zoneTempDir - pointer to string representing the temporary
2930 * directory in which spooled packages can be found if
2931 * a_idsName is == NULL.
2932 * a_altBinDir - pointer to string representing an alternative
2933 * binary location directory to pass to pkginstall.
2934 * If this is == NULL no alternative binary location is
2935 * passed to pkginstall.
2936 * a_scratchName - pointer to string representing the name of the
2937 * scratch zone to use for installation.
2938 * a_zoneState - state of the zone; must be mounted or running.
2939 * a_tmpzn - B_TRUE when this zone is booted by the package
2940 * command or B_FALSE if it was running before.
2941 * Returns: void
2942 * NOTE: As a side effect, "ckreturn" is called on the result returned
2943 * from running 'pkginstall' in the zone; this sets several global
2944 * variables which allows the caller to determine the result of
2945 * the installation operation.
2948 static void
2949 install_in_one_zone(char *a_zoneName, char *a_idsName,
2950 char *a_zoneAdminFile, char *a_zoneTempDir,
2951 char *a_altBinDir, zone_state_t a_zoneState, boolean_t a_tmpzn)
2953 char zoneStreamName[PATH_MAX] = {'\0'};
2954 int n;
2956 /* entry assertions */
2958 assert(a_zoneName != (char *)NULL);
2959 assert(*a_zoneName != '\0');
2961 /* entry debugging info */
2963 echoDebug(DBG_INSTINONEZONE_ENTRY);
2964 echoDebug(DBG_INSTINONEZONE_ARGS, a_zoneName, PSTR(a_idsName),
2965 PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir),
2966 PSTR(a_altBinDir));
2968 /* echo operation to perform to stdout */
2970 echo(MSG_INSTALL_PKG_IN_ZONE, pkginst, a_zoneName);
2972 /* determine path to the package stream */
2974 if (a_idsName == (char *)NULL) {
2975 /* locate temp stream created earlier */
2976 (void) snprintf(zoneStreamName, sizeof (zoneStreamName),
2977 "%s/%s.dstream", a_zoneTempDir, pkginst);
2978 } else {
2979 /* use stream passed in on command line */
2980 (void) snprintf(zoneStreamName, sizeof (zoneStreamName),
2981 "%s", a_idsName);
2984 echoDebug(DBG_INSTALL_IN_ZONE, pkginst, a_zoneName, zoneStreamName);
2986 n = pkgZoneInstall(a_zoneName, a_zoneState, zoneStreamName,
2987 a_altBinDir, a_zoneAdminFile, a_tmpzn);
2989 /* set success/fail condition variables */
2991 ckreturn(n);
2993 /* exit debugging info */
2995 echoDebug(DBG_INSTALL_FLAG_VALUES, "after install", admnflag, doreboot,
2996 failflag, interrupted, intrflag, ireboot, needconsult,
2997 nullflag, warnflag);
3001 * Name: install_in_zones
3002 * Description: Install a single package in the zones that are running from
3003 * a list of zones
3004 * Arguments: a_zlst - list of zones to install the package into
3005 * a_idsName - pointer to string representing the data stream
3006 * device (input data stream) containing the package to
3007 * be installed.
3008 * If this is == NULL the package is assumed to be
3009 * spooled in the zone temporary directory.
3010 * a_altBinDir - pointer to string representing an alternative
3011 * binary location directory to pass to pkginstall.
3012 * If this is == NULL no alternative binary location is
3013 * passed to pkginstall.
3014 * a_zoneAdminFile - pointer to string representing the admin
3015 * file to pass to pkginstall when installing the package.
3016 * If this is == NULL no admin file is given to pkginstall.
3017 * a_zoneTempDir - pointer to string representing the temporary
3018 * directory in which spooled packages can be found if
3019 * a_idsName is == NULL.
3022 static int
3023 install_in_zones(zoneList_t a_zlst, char *a_idsName, char *a_altBinDir,
3024 char *a_zoneAdminFile, char *a_zoneTempDir)
3026 char *zoneName;
3027 int zoneIndex;
3028 int zonesSkipped = 0;
3029 zone_state_t zst;
3031 /* entry assertions */
3033 assert(a_zlst != (zoneList_t)NULL);
3035 /* entry debugging info */
3037 echoDebug(DBG_INSTALLINZONES_ENTRY);
3038 echoDebug(DBG_INSTALLINZONES_ARGS, PSTR(a_idsName),
3039 PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir));
3041 /* process each zone in the list */
3043 for (zoneIndex = 0;
3044 (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3045 zoneIndex++) {
3047 /* skip the zone if it is NOT running */
3049 zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3050 if (zst != ZONE_STATE_RUNNING && zst != ZONE_STATE_MOUNTED) {
3051 zonesSkipped++;
3052 echoDebug(DBG_SKIPPING_ZONE, zoneName);
3053 continue;
3056 /* install the package in this zone */
3058 install_in_one_zone(z_zlist_get_scratch(a_zlst, zoneIndex),
3059 a_idsName, a_zoneAdminFile, a_zoneTempDir, a_altBinDir,
3060 zst, B_FALSE);
3063 return (zonesSkipped);
3067 * Name: boot_and_install_in_zones
3068 * Description: Install a single package in the zones that are NOT running from
3069 * a list of zones - each zone is booted, the package installed,
3070 * and the zone is halted
3071 * Arguments: a_zlst - list of zones to install the package into
3072 * a_idsName - pointer to string representing the data stream
3073 * device (input data stream) containing the package to
3074 * be installed.
3075 * If this is == NULL the package is assumed to be
3076 * spooled in the zone temporary directory.
3077 * a_altBinDir - pointer to string representing an alternative
3078 * binary location directory to pass to pkginstall.
3079 * If this is == NULL no alternative binary location is
3080 * passed to pkginstall.
3081 * a_zoneAdminFile - pointer to string representing the admin
3082 * file to pass to pkginstall when installing the package.
3083 * If this is == NULL no admin file is given to pkginstall.
3084 * a_zoneTempDir - pointer to string representing the temporary
3085 * directory in which spooled packages can be found if
3086 * a_idsName is == NULL.
3089 static int
3090 boot_and_install_in_zones(zoneList_t a_zlst, char *a_idsName, char *a_altBinDir,
3091 char *a_zoneAdminFile, char *a_zoneTempDir)
3093 boolean_t b;
3094 char *zoneName;
3095 int zoneIndex;
3096 int zonesSkipped = 0;
3097 zone_state_t zst;
3099 /* entry assertions */
3101 assert(a_zlst != (zoneList_t)NULL);
3103 /* entry debugging info */
3105 echoDebug(DBG_BOOTINSTALLINZONES_ENTRY);
3106 echoDebug(DBG_BOOTINSTALLINZONES_ARGS, PSTR(a_idsName),
3107 PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir));
3109 /* process each zone in the list */
3111 for (zoneIndex = 0;
3112 (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3113 zoneIndex++) {
3115 /* skip the zone if it IS running */
3117 zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3118 if (zst == ZONE_STATE_RUNNING || zst == ZONE_STATE_MOUNTED) {
3119 echoDebug(DBG_SKIPPING_ZONE_BOOT, zoneName);
3120 continue;
3123 /* skip the zone if it is NOT bootable */
3125 if (z_zlist_is_zone_runnable(a_zlst, zoneIndex) == B_FALSE) {
3126 echo(MSG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3127 echoDebug(DBG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3128 continue;
3131 /* mount up the zone */
3133 echo(MSG_BOOTING_ZONE, zoneName);
3134 echoDebug(DBG_BOOTING_ZONE, zoneName);
3136 b = z_zlist_change_zone_state(a_zlst, zoneIndex,
3137 ZONE_STATE_MOUNTED);
3138 if (b == B_FALSE) {
3139 progerr(ERR_CANNOT_BOOT_ZONE, zoneName);
3140 /* set fatal error return condition */
3141 ckreturn(1);
3142 zonesSkipped++;
3143 continue;
3146 /* install the package in this zone */
3148 install_in_one_zone(z_zlist_get_scratch(a_zlst, zoneIndex),
3149 a_idsName, a_zoneAdminFile, a_zoneTempDir, a_altBinDir,
3150 ZONE_STATE_MOUNTED, B_TRUE);
3152 /* restore original state of zone */
3154 echo(MSG_RESTORE_ZONE_STATE, zoneName);
3155 echoDebug(DBG_RESTORE_ZONE_STATE, zoneName);
3157 b = z_zlist_restore_zone_state(a_zlst, zoneIndex);
3160 return (zonesSkipped);
3164 * Name: pkginstall_check_in_one_zone
3165 * Description: Do a pre install check of a single package in a single zone
3166 * Arguments: a_zoneName - pointer to string representing the name of the
3167 * zone to check install the package in.
3168 * a_idsName - pointer to string representing the data stream
3169 * device (input data stream) containing the package to
3170 * be check installed.
3171 * If this is == NULL the package is assumed to be
3172 * spooled in the zone temporary directory.
3173 * a_zoneAdminFile - pointer to string representing the admin
3174 * file to pass to pkginstall when installing the package.
3175 * If this is == NULL no admin file is given to pkginstall.
3176 * a_zoneTempDir - pointer to string representing the temporary
3177 * directory in which spooled packages can be found if
3178 * a_idsName is == NULL.
3179 * a_altBinDir - pointer to string representing an alternative
3180 * binary location directory to pass to pkginstall.
3181 * If this is == NULL no alternative binary location is
3182 * passed to pkginstall.
3183 * a_scratchName - pointer to string representing the name of the
3184 * scratch zone to use for installation.
3185 * a_zoneState - state of the zone; must be mounted or running.
3186 * a_tmpzn - B_TRUE when this zone is booted by the package
3187 * command or B_FALSE if it was running before.
3188 * Returns: void
3189 * NOTE: As a side effect, "ckreturn" is called on the result returned
3190 * from running 'pkginstall' in the zone; this sets several global
3191 * variables which allows the caller to determine the result of
3192 * the pre installation check operation.
3195 static void
3196 pkginstall_check_in_one_zone(char *a_zoneName,
3197 char *a_idsName, char *a_zoneAdminFile, char *a_zoneTempDir,
3198 char *a_altBinDir, char *a_scratchName, zone_state_t a_zoneState,
3199 boolean_t a_tmpzn)
3201 char preinstallcheckPath[PATH_MAX+1];
3202 char zoneStreamName[PATH_MAX] = {'\0'};
3203 int n;
3205 echo(MSG_CHECKINSTALL_PKG_IN_ZONE, pkginst, a_zoneName);
3206 echoDebug(MSG_CHECKINSTALL_PKG_IN_ZONE, pkginst, a_zoneName);
3208 (void) snprintf(preinstallcheckPath, sizeof (preinstallcheckPath),
3209 "%s/%s.%s.preinstallcheck.txt", a_zoneTempDir, pkginst,
3210 a_zoneName);
3212 if (a_idsName == (char *)NULL) {
3213 /* locate temporary stream created earlier */
3214 (void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3215 "%s/%s.dstream", a_zoneTempDir, pkginst);
3216 } else {
3217 (void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3218 "%s", a_idsName);
3221 echoDebug(DBG_CHECKINSTALL_IN_ZONE, pkginst, a_zoneName,
3222 zoneStreamName);
3224 n = pkgZoneCheckInstall(a_scratchName, a_zoneState, zoneStreamName,
3225 a_altBinDir, a_zoneAdminFile, preinstallcheckPath, a_tmpzn);
3227 /* set success/fail condition variables */
3229 ckreturn(n);
3231 echoDebug(DBG_INSTALL_FLAG_VALUES, "after preinstall check",
3232 admnflag, doreboot, failflag, interrupted, intrflag,
3233 ireboot, needconsult, nullflag, warnflag);
3237 * Name: pkginstall_check_in_zones
3238 * Description: Check installation of a single package in the zones that
3239 * are running from a list of zones
3240 * Arguments: a_zlst - list of zones to check install the package
3241 * a_idsName - pointer to string representing the data stream
3242 * device (input data stream) containing the package to
3243 * be check installed.
3244 * If this is == NULL the package is assumed to be
3245 * spooled in the zone temporary directory.
3246 * a_altBinDir - pointer to string representing an alternative
3247 * binary location directory to pass to pkginstall.
3248 * If this is == NULL no alternative binary location is
3249 * passed to pkginstall.
3250 * a_zoneAdminFile - pointer to string representing the admin
3251 * file to pass to pkginstall when checking the installing
3252 * of the package.
3253 * If this is == NULL no admin file is given to pkginstall.
3254 * a_zoneTempDir - pointer to string representing the temporary
3255 * directory in which spooled packages can be found if
3256 * a_idsName is == NULL.
3259 static int
3260 pkginstall_check_in_zones(zoneList_t a_zlst, char *a_idsName, char *a_altBinDir,
3261 char *a_zoneAdminFile, char *a_zoneTempDir)
3263 char *zoneName;
3264 int zoneIndex;
3265 int zonesSkipped = 0;
3266 zone_state_t zst;
3268 for (zoneIndex = 0;
3269 (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3270 zoneIndex++) {
3272 zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3273 if (zst != ZONE_STATE_RUNNING && zst != ZONE_STATE_MOUNTED) {
3274 zonesSkipped++;
3275 echoDebug(DBG_SKIPPING_ZONE, zoneName);
3276 continue;
3279 pkginstall_check_in_one_zone(zoneName, a_idsName,
3280 a_zoneAdminFile, a_zoneTempDir, a_altBinDir,
3281 z_zlist_get_scratch(a_zlst, zoneIndex), zst, B_FALSE);
3284 return (zonesSkipped);
3288 * Name: boot_and_pkginstall_check_in_zones
3289 * Description: Check installation of a single package in the zones that
3290 * are NOT running from a list of zones - each zone is booted,
3291 * the package installation is checked, and the zone is halted.
3292 * Arguments: a_zlst - list of zones to install the package into
3293 * a_idsName - pointer to string representing the data stream
3294 * device (input data stream) containing the package to
3295 * be check installed.
3296 * If this is == NULL the package is assumed to be
3297 * spooled in the zone temporary directory.
3298 * a_altBinDir - pointer to string representing an alternative
3299 * binary location directory to pass to pkginstall.
3300 * If this is == NULL no alternative binary location is
3301 * passed to pkginstall.
3302 * a_zoneAdminFile - pointer to string representing the admin
3303 * file to pass to pkginstall when check installing the
3304 * package.
3305 * If this is == NULL no admin file is given to pkginstall.
3306 * a_zoneTempDir - pointer to string representing the temporary
3307 * directory in which spooled packages can be found if
3308 * a_idsName is == NULL.
3311 static int
3312 boot_and_pkginstall_check_in_zones(zoneList_t a_zlst, char *a_idsName,
3313 char *a_altBinDir, char *a_zoneAdminFile, char *a_zoneTempDir)
3315 int zoneIndex;
3316 int zonesSkipped = 0;
3317 char *zoneName;
3318 boolean_t b;
3319 zone_state_t zst;
3321 /* entry assertions */
3323 assert(a_zlst != (zoneList_t)NULL);
3325 /* entry debugging info */
3327 echoDebug(DBG_BOOTCHECKINSTALLINZONES_ENTRY);
3328 echoDebug(DBG_BOOTCHECKINSTALLINZONES_ARGS, PSTR(a_idsName),
3329 PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir));
3331 /* process each zone in the list */
3333 for (zoneIndex = 0;
3334 (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3335 zoneIndex++) {
3337 /* skip the zone if it IS running */
3339 zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3340 if (zst == ZONE_STATE_RUNNING || zst == ZONE_STATE_MOUNTED) {
3341 echoDebug(DBG_SKIPPING_ZONE_BOOT, zoneName);
3342 continue;
3345 /* skip the zone if it is NOT bootable */
3347 if (z_zlist_is_zone_runnable(a_zlst, zoneIndex) == B_FALSE) {
3348 echo(MSG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3349 echoDebug(DBG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3350 continue;
3353 /* mount up the zone */
3355 echo(MSG_BOOTING_ZONE, zoneName);
3356 echoDebug(DBG_BOOTING_ZONE, zoneName);
3358 b = z_zlist_change_zone_state(a_zlst, zoneIndex,
3359 ZONE_STATE_MOUNTED);
3360 if (b == B_FALSE) {
3361 progerr(ERR_CANNOT_BOOT_ZONE, zoneName);
3362 /* set fatal error return condition */
3363 ckreturn(1);
3364 zonesSkipped++;
3365 continue;
3368 /* pre-installation check of the package in this zone */
3370 pkginstall_check_in_one_zone(zoneName, a_idsName,
3371 a_zoneAdminFile, a_zoneTempDir, a_altBinDir,
3372 z_zlist_get_scratch(a_zlst, zoneIndex),
3373 ZONE_STATE_MOUNTED, B_TRUE);
3375 /* restore original state of zone */
3377 echo(MSG_RESTORE_ZONE_STATE, zoneName);
3378 echoDebug(DBG_RESTORE_ZONE_STATE, zoneName);
3380 b = z_zlist_restore_zone_state(a_zlst, zoneIndex);
3383 return (zonesSkipped);
3387 * Function: add_packages_in_global_with_zones
3388 * Description: call this function to add a list of packages in the global zone
3389 * when one or more non-global zones exist
3390 * returns:
3391 * B_TRUE to process next data stream
3392 * B_FALSE to exit
3395 static boolean_t
3396 add_packages_in_global_with_zones(char **a_pkgList,
3397 char *a_idsName, int a_repeat, char *a_altBinDir,
3398 char *a_device, zoneList_t a_zlst)
3400 static char *zoneTempDir = (char *)NULL;
3401 static char *zoneAdminFile = (char *)NULL;
3403 boolean_t b;
3404 char *packageDir;
3405 char instdir[PATH_MAX];
3406 char respfile_path[PATH_MAX];
3407 char zoneStreamName[PATH_MAX] = {'\0'};
3408 int i;
3409 int n;
3410 int savenpkgs = npkgs;
3411 int zonesSkipped;
3412 boolean_t globalPresent;
3414 /* entry assertions */
3416 assert(a_pkgList != (char **)NULL);
3417 assert(a_zlst != (zoneList_t)NULL);
3419 echoDebug(DBG_ADDPACKAGES_GZ_W_LZ_ENTRY);
3420 echoDebug(DBG_ADDPACKAGES_GZ_W_LZ_ARGS, npkgs,
3421 PSTR(a_idsName), a_repeat, PSTR(a_device));
3423 /* create temporary directory for use by zone operations */
3425 create_zone_tempdir(&zoneTempDir, tmpdir);
3427 /* create hands off settings admin file for use in a non-global zone */
3429 create_zone_adminfile(&zoneAdminFile, zoneTempDir, admnfile);
3431 /* determine directory where packages can be found */
3433 if (a_idsName == (char *)NULL) {
3434 /* no stream - directory containing packages provided */
3435 packageDir = pkgdev.dirname;
3436 } else {
3437 packageDir = zoneTempDir;
3440 /* unpack and check all packages */
3442 b = unpack_and_check_packages(a_pkgList, a_idsName, packageDir);
3443 if (b != B_TRUE) {
3444 quit(1);
3448 * if the packages are contained in a directory, convert the
3449 * packages into individual streams because pkgZoneInstall is only able
3450 * to pass a stream to the non-global zone's pkginstall command.
3451 * After this code is executed:
3452 * if the original input was a datastream:
3453 * -> that datastream has been unpacked into "instdir"
3454 * if the original input was a directory with packages in it:
3455 * -> those packages have been placed into a single datastream
3458 if (a_idsName == (char *)NULL) {
3459 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3460 char *pkgs[2];
3462 /* package is not a stream - create one */
3464 (void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3465 "%s/%s.dstream", zoneTempDir, pkginst);
3467 echoDebug(DBG_CONVERTING_PKG, packageDir, pkginst,
3468 zoneStreamName);
3470 /* set up list of packages to be this package only */
3472 pkgs[0] = pkginst;
3473 pkgs[1] = (char *)NULL;
3475 n = pkgtrans(packageDir, zoneStreamName, pkgs,
3476 PT_SILENT|PT_ODTSTREAM);
3477 if (n != 0) {
3478 progerr(ERR_CANNOT_CONVERT_PKGSTRM,
3479 pkginst, packageDir, zoneStreamName);
3480 quit(1);
3482 npkgs--;
3484 npkgs = savenpkgs;
3488 * Phase I - run collect dependency information for all packages for all
3489 * zones - this involves running pkginstall with the "preinstallcheck"
3490 * option which causes all dependency checks to be performed without
3491 * actually doing the installation of the packages. This information is
3492 * gathered in the zone temporary directory and is used later to present
3493 * the dependency check results to the system administrator depending
3494 * on the administration settings.
3497 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3499 /* reset interrupted flag before calling pkginstall */
3501 interrupted = 0; /* last action was NOT quit */
3504 * if this package is marked "install in this zone only", then
3505 * do not check dependencies in any other zone
3508 if (pkgPackageIsThisZone(pkginst) == B_TRUE) {
3509 echoDebug(DBG_VERIFY_SKIP_THISZONE, pkginst);
3510 npkgs--;
3511 continue;
3515 * if operation failed in global zone do not propagate
3516 * to any non-global zones
3519 if (interrupted != 0) {
3520 echo(MSG_CHECKINSTALL_INTERRUPT_B4_Z, pkginst);
3521 echoDebug(MSG_CHECKINSTALL_INTERRUPT_B4_Z, pkginst);
3522 break;
3525 echoDebug(DBG_INSTALL_FLAG_VALUES, "after pkginstall",
3526 admnflag, doreboot, failflag, interrupted, intrflag,
3527 ireboot, needconsult, nullflag, warnflag);
3530 * call pkginstall to verify this package for all non-global
3531 * zones that are currently booted
3534 zonesSkipped = pkginstall_check_in_zones(a_zlst, a_idsName,
3535 a_altBinDir, admnfile, zoneTempDir);
3538 * if any zones were skipped (becuase they are not currently
3539 * booted), boot each zone one at a time and call pkginstall
3540 * to verify this package for each such non-global zone
3543 if (zonesSkipped > 0) {
3544 echoDebug(DBG_ZONES_SKIPPED, zonesSkipped);
3546 zonesSkipped =
3547 boot_and_pkginstall_check_in_zones(a_zlst,
3548 a_idsName, a_altBinDir, admnfile,
3549 zoneTempDir);
3551 if (zonesSkipped > 0) {
3552 progerr(ERR_INSTALL_ZONES_SKIPPED,
3553 zonesSkipped);
3557 npkgs--;
3561 * At this point, all of the dependency information has been gathered
3562 * and is ready to be analyzed. This function processes all of that
3563 * dependency information and presents the results to the system
3564 * administrator, depending on the current administration settings.
3567 i = preinstall_verify(a_pkgList, a_zlst, zoneTempDir);
3568 if (i != 0) {
3569 /* dependency checks failed - exit */
3570 quit(i);
3573 npkgs = savenpkgs;
3576 * reset all error return condition variables that may have been
3577 * set during package installation dependency checking so that they
3578 * do not reflect on the success/failure of the actual package
3579 * installation operations
3582 resetreturn();
3585 * At this point, all of the dependency checking is completed, and
3586 * the installation of the packages can proceed. Install each package
3587 * one at a time, starting with the global zone, and the for each
3588 * non-global zone that is booted, and then for each non-global zone
3589 * that is not currently booted.
3592 globalPresent = z_on_zone_spec(GLOBAL_ZONENAME);
3594 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3596 * if immediate reboot required from last package and this is
3597 * not 'pkgask' then suspend installation of remaining packages
3600 if ((ireboot != 0) && (askflag == 0)) {
3601 ptext(stderr, MSG_SUSPEND_ADD, pkginst);
3602 continue;
3606 * handle interrupt if the previous pkginstall was interrupted
3609 if (continue_installation() == B_FALSE) {
3610 return (B_FALSE);
3614 * if pkgask, handle response file creation:
3615 * - if the response file is a directory, then create a path to
3616 * -- a package instance within the response file directory.
3617 * - If the response file is NOT a directory, if more than one
3618 * -- package is to be installed.
3621 if ((askflag != 0) && (respdir != (char *)NULL)) {
3622 (void) snprintf(respfile_path, sizeof (respfile_path),
3623 "%s/%s", respdir, pkginst);
3624 respfile = respfile_path;
3627 echo(MSG_PROC_INST, pkginst, a_device);
3630 * If we're installing another package in the same
3631 * session, the second through nth pkginstall, must
3632 * continue from where the prior one left off. For this
3633 * reason, the continuation feature (implied by the
3634 * nature of the command) is used for the remaining
3635 * packages.
3638 if ((i == 1) && (pkgdrtarg != (char *)NULL)) {
3639 pkgcontsrc = pkgdrtarg;
3642 if (globalPresent) {
3644 * call pkginstall for this package for the global zone
3647 echo(MSG_INSTALLING_PKG_IN_GZ, pkginst);
3649 /* reset interrupted flag before calling pkginstall */
3651 interrupted = 0; /* last action was NOT quit */
3653 n = pkgInstall(get_inst_root(), NULL, packageDir,
3654 a_altBinDir);
3656 /* set success/fail condition variables */
3658 ckreturn(n);
3661 * if operation failed in global zone do not propagate
3662 * to any non-global zones
3665 if (interrupted != 0) {
3666 echo(MSG_INSTALL_INTERRUPT_B4_ZONES, pkginst);
3667 echoDebug(MSG_INSTALL_INTERRUPT_B4_ZONES,
3668 pkginst);
3669 break;
3674 * if this package is marked "install in this zone only",
3675 * then only need to install the package in the global zone;
3676 * skip installation in any non-global zones.
3679 if (pkgPackageIsThisZone(pkginst) == B_TRUE) {
3680 echoDebug(DBG_INSTALL_SKIP_THISZONE, pkginst);
3681 npkgs--;
3682 continue;
3685 echoDebug(DBG_INSTALL_FLAG_VALUES, "install in running zones",
3686 admnflag, doreboot, failflag, interrupted, intrflag,
3687 ireboot, needconsult, nullflag, warnflag);
3689 /* install package in currently booted zones */
3691 zonesSkipped = install_in_zones(a_zlst, a_idsName, a_altBinDir,
3692 zoneAdminFile, zoneTempDir);
3694 /* install package in zones that are not currently booted */
3696 if (zonesSkipped > 0) {
3697 echoDebug(DBG_ZONES_SKIPPED, zonesSkipped);
3699 zonesSkipped = boot_and_install_in_zones(a_zlst,
3700 a_idsName, a_altBinDir, zoneAdminFile,
3701 zoneTempDir);
3703 if (zonesSkipped > 0) {
3704 progerr(ERR_INSTALL_ZONES_SKIPPED,
3705 zonesSkipped);
3710 * package completely installed - remove any temporary stream
3711 * of the package that might have been created
3714 if (a_idsName == (char *)NULL) {
3715 /* locate temporary stream created earlier */
3716 (void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3717 "%s/%s.dstream", zoneTempDir, pkginst);
3718 /* remove stream - no longer needed */
3719 echoDebug(DBG_REMOVING_DSTREAM_PKGDIR, zoneStreamName,
3720 pkginst);
3721 (void) remove(zoneStreamName);
3722 } else {
3723 /* remove package - no longer needed */
3724 if (snprintf(instdir, sizeof (instdir), "%s/%s",
3725 zoneTempDir, pkginst) >= PATH_MAX) {
3726 progerr(ERR_CANNOT_CREATE_PKGPATH, tmpdir);
3727 quit(1);
3729 echoDebug(DBG_REMOVING_PKG_TMPDIR, instdir, pkginst);
3730 (void) remove(instdir);
3733 /* decrement number of packages left to install */
3735 npkgs--;
3738 * if no packages left to install, unmount package source
3739 * device if appropriate
3742 if ((npkgs <= 0) && (pkgdev.mount || a_idsName)) {
3743 (void) chdir("/");
3744 if (!a_idsName) {
3745 echoDebug(DBG_UNMOUNTING_DEV,
3746 PSTR(pkgdev.mount));
3747 (void) pkgumount(&pkgdev);
3753 * all packages in the package list have been installed.
3754 * Continue with installation if:
3755 * -- immediate reboot is NOT required
3756 * -- there are more packages to install
3757 * -- the package source is a path to a file
3758 * else return do NOT continue.
3761 if ((ireboot == 0) && (a_repeat != 0) &&
3762 (pkgdev.pathname == (char *)NULL)) {
3763 return (B_TRUE);
3766 /* return 'dont continue' */
3768 return (B_FALSE);
3772 * Function: add_packages_in_nonglobal_zone
3773 * Description: call this function to add a list of packages in a non-global
3774 * zone
3775 * returns:
3776 * B_TRUE to process next data stream
3777 * B_FALSE to exit
3780 static boolean_t
3781 add_packages_in_nonglobal_zone(char **a_pkgList,
3782 char *a_idsName, int a_repeat, char *a_altBinDir, char *a_device)
3784 static char *zoneTempDir = (char *)NULL;
3786 char *packageDir;
3787 char respfile_path[PATH_MAX];
3788 int i;
3789 int n;
3790 boolean_t b;
3791 int savenpkgs = npkgs;
3793 /* entry assertions */
3795 assert(a_pkgList != (char **)NULL);
3797 /* entry debugging info */
3799 echoDebug(DBG_ADDPACKAGES_LZ_ENTRY);
3800 echoDebug(DBG_ADDPACKAGES_LZ_ARGS, npkgs, PSTR(a_idsName),
3801 a_repeat, PSTR(a_device));
3803 /* create temporary directory for use by zone operations */
3805 create_zone_tempdir(&zoneTempDir, tmpdir);
3808 * package can be in a number of formats:
3809 * - file containing package stream (pkgadd -d file [pkgs])
3810 * - directory containing packages (pkgadd -d /dir [pkgs])
3811 * - device containing packages (pkgadd -d diskette1 [pkgs])
3812 * non-global zones can be passed open file drescriptors and
3813 * strings as arguments
3814 * - for file containing package stream
3815 * -- the stream can be passed directly to the non-global zone
3816 * - for directory
3817 * -- convert packages to datastream to pass to the non-global zone
3818 * - for device
3821 /* determine directory where packages can be found */
3823 if (a_idsName == (char *)NULL) {
3824 /* no stream - directory containing packages provided */
3825 packageDir = pkgdev.dirname;
3826 } else {
3827 packageDir = zoneTempDir;
3830 b = unpack_and_check_packages(a_pkgList, a_idsName, packageDir);
3831 if (b != B_TRUE) {
3832 quit(1);
3836 * this is the main loop where all of the packages (as listed in the
3837 * package list) are added one at a time.
3840 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3841 npkgs--;
3844 npkgs = savenpkgs;
3847 * this is the main loop where all of the packages (as listed in the
3848 * package list) are added one at a time.
3851 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3853 * if immediate reboot required from last package and this is
3854 * not 'pkgask' then suspend installation of remaining packages
3857 if ((ireboot != 0) && (askflag == 0)) {
3858 ptext(stderr, MSG_SUSPEND_ADD, pkginst);
3859 continue;
3863 * handle interrupt if the previous pkginstall was interrupted
3866 if (continue_installation() == B_FALSE) {
3867 return (B_FALSE);
3871 * if pkgask, handle response file creation:
3872 * - if the response file is a directory, then create a path to
3873 * -- a package instance within the response file directory.
3874 * - If the response file is NOT a directory, if more than one
3875 * -- package is to be installed.
3878 if ((askflag != 0) && (respdir != (char *)NULL)) {
3879 (void) snprintf(respfile_path, sizeof (respfile_path),
3880 "%s/%s", respdir, pkginst);
3881 respfile = respfile_path;
3884 echo(MSG_PROC_INST, pkginst, a_device);
3887 * If we're installing another package in the same
3888 * session, the second through nth pkginstall, must
3889 * continue from where the prior one left off. For this
3890 * reason, the continuation feature (implied by the
3891 * nature of the command) is used for the remaining
3892 * packages.
3895 if ((i == 1) && (pkgdrtarg != (char *)NULL)) {
3896 pkgcontsrc = pkgdrtarg;
3899 /* reset interrupted flag before calling pkginstall */
3901 interrupted = 0; /* last action was NOT quit */
3903 /* call pkginstall for this package */
3905 n = pkgInstall(get_inst_root(), NULL,
3906 packageDir, a_altBinDir);
3908 /* set success/fail condition variables */
3910 ckreturn(n);
3912 /* decrement number of packages left to install */
3914 npkgs--;
3917 * if no packages left to install, unmount package source
3918 * device if appropriate
3921 if ((npkgs <= 0) && (pkgdev.mount || a_idsName)) {
3922 (void) chdir("/");
3923 if (!a_idsName) {
3924 (void) pkgumount(&pkgdev);
3930 * all packages in the package list have been installed.
3931 * Continue with installation if:
3932 * -- immediate reboot is NOT required
3933 * -- there are more packages to install
3934 * -- the package source is a path to a file
3935 * else return do NOT continue.
3938 if ((ireboot == 0) && (a_repeat != 0) &&
3939 (pkgdev.pathname == (char *)NULL)) {
3940 return (B_TRUE);
3943 /* return 'dont continue' */
3945 return (B_FALSE);
3949 * Function: add_packages_in_global_no_zones
3950 * Description: call this function to add a list of packages in the global zone
3951 * when no non-global zones exist
3952 * returns:
3953 * B_TRUE to process next data stream
3954 * B_FALSE to exit
3957 static boolean_t
3958 add_packages_in_global_no_zones(char **a_pkgList,
3959 char *a_idsName, int a_repeat, char *a_altBinDir, char *a_device)
3961 int n;
3962 int i;
3963 char respfile_path[PATH_MAX];
3964 CAF_T flags = 0;
3966 /* entry assertions */
3968 assert(a_pkgList != (char **)NULL);
3970 echoDebug(DBG_ADDPACKAGES_GZ_NO_LZ_ENTRY);
3971 echoDebug(DBG_ADDPACKAGES_GZ_NO_LZ_ARGS, npkgs,
3972 PSTR(a_idsName), a_repeat, PSTR(a_device));
3975 * set flags for applicability check
3978 /* in the global zone */
3980 flags |= CAF_IN_GLOBAL_ZONE;
3982 /* set -G flag */
3984 if (globalZoneOnly == B_TRUE) {
3985 flags |= CAF_SCOPE_GLOBAL;
3989 * this is the main loop where all of the packages (as listed in the
3990 * package list) are added one at a time.
3993 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3995 * if immediate reboot required from last package and this is
3996 * not 'pkgask' then suspend installation of remaining packages
3999 if ((ireboot != 0) && (askflag == 0)) {
4000 ptext(stderr, MSG_SUSPEND_ADD, pkginst);
4001 continue;
4005 * handle interrupt if the previous pkginstall was interrupted
4008 if (continue_installation() == B_FALSE) {
4009 return (B_FALSE);
4013 * check package applicability to install in this context
4016 if (check_applicability(pkgdev.dirname,
4017 pkginst, get_inst_root(), flags) == B_FALSE) {
4018 progerr(ERR_PKG_NOT_APPLICABLE, pkginst);
4019 quit(1);
4023 * if pkgask, handle response file creation:
4024 * - if the response file is a directory, then create a path to
4025 * -- a package instance within the response file directory.
4026 * - If the response file is NOT a directory, if more than one
4027 * -- package is to be installed.
4030 if ((askflag != 0) && (respdir != (char *)NULL)) {
4031 (void) snprintf(respfile_path, sizeof (respfile_path),
4032 "%s/%s", respdir, pkginst);
4033 respfile = respfile_path;
4036 echo(MSG_PROC_INST, pkginst, a_device);
4039 * If we're installing another package in the same
4040 * session, the second through nth pkginstall, must
4041 * continue from where the prior one left off. For this
4042 * reason, the continuation feature (implied by the
4043 * nature of the command) is used for the remaining
4044 * packages.
4047 if ((i == 1) && (pkgdrtarg != (char *)NULL)) {
4048 pkgcontsrc = pkgdrtarg;
4051 /* reset interrupted flag before calling pkginstall */
4053 interrupted = 0; /* last action was NOT quit */
4055 /* call pkginstall for this package */
4057 n = pkgInstall(get_inst_root(), a_idsName,
4058 pkgdev.dirname, a_altBinDir);
4060 /* set success/fail condition variables */
4062 ckreturn(n);
4064 /* decrement number of packages left to install */
4066 npkgs--;
4069 * if no packages left to install, unmount package source
4070 * device if appropriate
4073 if ((npkgs <= 0) && (pkgdev.mount || a_idsName)) {
4074 (void) chdir("/");
4075 if (!a_idsName) {
4076 (void) pkgumount(&pkgdev);
4082 * all packages in the package list have been installed.
4083 * Continue with installation if:
4084 * -- immediate reboot is NOT required
4085 * -- there are more packages to install
4086 * -- the package source is a path to a file
4087 * else return do NOT continue.
4090 if ((ireboot == 0) && (a_repeat != 0) &&
4091 (pkgdev.pathname == (char *)NULL)) {
4092 return (B_TRUE);
4095 /* return 'dont continue' */
4097 return (B_FALSE);
4101 * returns:
4102 * B_TRUE to process next data stream
4103 * B_FALSE to exit
4106 static boolean_t
4107 add_packages(char **a_pkgList,
4108 char *a_idsName, int a_repeat, char *a_altBinDir, char *a_device,
4109 boolean_t a_noZones)
4111 zoneList_t zlst;
4112 boolean_t b;
4114 /* entry assertions */
4116 assert(a_pkgList != (char **)NULL);
4118 echoDebug(DBG_ADDPACKAGES_ENTRY);
4119 echoDebug(DBG_ADDPACKAGES_ARGS, npkgs, PSTR(a_idsName),
4120 a_repeat, PSTR(a_altBinDir), PSTR(a_device));
4123 * if running in the global zone AND one or more non-global
4124 * zones exist, add packages in a 'zones aware' manner, else
4125 * add packages in the standard 'non-zones aware' manner.
4128 if ((a_noZones == B_FALSE) && (z_running_in_global_zone() == B_FALSE)) {
4129 /* in non-global zone */
4131 echoDebug(DBG_IN_LZ);
4133 b = z_lock_this_zone(ZLOCKS_PKG_ADMIN);
4134 if (b != B_TRUE) {
4135 progerr(ERR_CANNOT_LOCK_THIS_ZONE);
4136 /* set fatal error return condition */
4137 ckreturn(1);
4138 return (B_FALSE);
4141 b = add_packages_in_nonglobal_zone(a_pkgList, a_idsName,
4142 a_repeat, a_altBinDir, a_device);
4144 (void) z_unlock_this_zone(ZLOCKS_ALL);
4146 return (B_FALSE);
4149 /* running in the global zone */
4151 b = z_non_global_zones_exist();
4152 if ((a_noZones == B_FALSE) && (b == B_TRUE) &&
4153 (globalZoneOnly == B_FALSE)) {
4155 echoDebug(DBG_IN_GZ_WITH_LZ);
4157 /* error if -V specified - what to use in non-global zone? */
4159 if (vfstab_file) {
4160 progerr(ERR_V_USED_WITH_GZS);
4161 quit(1);
4164 /* get a list of all non-global zones */
4165 zlst = z_get_nonglobal_zone_list();
4166 if (zlst == (zoneList_t)NULL) {
4167 progerr(ERR_CANNOT_GET_ZONE_LIST);
4168 quit(1);
4171 /* need to lock all of the zones */
4173 quitSetZonelist(zlst);
4174 b = z_lock_zones(zlst, ZLOCKS_PKG_ADMIN);
4175 if (b == B_FALSE) {
4176 z_free_zone_list(zlst);
4177 progerr(ERR_CANNOT_LOCK_ZONES);
4178 /* set fatal error return condition */
4179 ckreturn(1);
4180 return (B_FALSE);
4183 /* add packages to all zones */
4185 b = add_packages_in_global_with_zones(a_pkgList,
4186 a_idsName, a_repeat, a_altBinDir, a_device, zlst);
4188 /* unlock all zones */
4190 (void) z_unlock_zones(zlst, ZLOCKS_ALL);
4191 quitSetZonelist((zoneList_t)NULL);
4193 /* free list of all non-global zones */
4195 z_free_zone_list(zlst);
4197 return (B_FALSE);
4200 /* in global zone no non-global zones */
4202 echoDebug(DBG_IN_GZ_NO_LZ);
4204 b = z_lock_this_zone(ZLOCKS_PKG_ADMIN);
4205 if (b != B_TRUE) {
4206 progerr(ERR_CANNOT_LOCK_THIS_ZONE);
4207 /* set fatal error return condition */
4208 ckreturn(1);
4209 return (B_FALSE);
4212 b = add_packages_in_global_no_zones(a_pkgList, a_idsName,
4213 a_repeat, a_altBinDir, a_device);
4215 (void) z_unlock_this_zone(ZLOCKS_ALL);
4217 return (B_FALSE);