8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / svr4pkg / pkgadd / main.c
blobc2f0125d551617f82ffaaa1f01a038739afe5ba7
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) 2017 Peter Tribble.
27 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
30 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
31 /* All Rights Reserved */
35 * Program: pkgadd / pkgask
37 * Function: public command and private utility functions that
38 * implement the package add and package ask operations.
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:zZ")) != 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 * CAF_SCOPE_NONGLOBAL - -Z specified
2307 * Returns: boolean_t
2308 * B_TRUE - the package can be installed
2309 * B_FALSE - the package can not be installed
2312 static boolean_t
2313 check_applicability(char *a_packageDir, char *a_pkgInst, char *a_rootPath,
2314 CAF_T a_flags)
2316 FILE *pkginfoFP;
2317 FILE *pkgmapFP;
2318 boolean_t all_zones; /* pkg is "all zones" only */
2319 boolean_t in_gz_only; /* pkg installed in global zone only */
2320 boolean_t is_hollow; /* pkg is "hollow" */
2321 boolean_t pkg_installed; /* pkg is installed */
2322 boolean_t this_zone; /* pkg is "this zone" only */
2323 boolean_t reqfile_found = B_FALSE;
2324 char instPkg[PKGSIZ+1]; /* installed pkg instance nam */
2325 char instPkgPath[PATH_MAX]; /* installed pkg toplevel dir */
2326 char pkginfoPath[PATH_MAX]; /* pkg 2 install pkginfo file */
2327 char pkgmapPath[PATH_MAX]; /* pkg 2 install pkgmap file */
2328 char pkgpath[PATH_MAX]; /* pkg 2 install toplevel dir */
2329 int len;
2330 char line[LINE_MAX];
2332 /* entry assertions */
2334 assert(a_packageDir != (char *)NULL);
2335 assert(*a_packageDir != '\0');
2336 assert(a_pkgInst != (char *)NULL);
2337 assert(*a_pkgInst != '\0');
2339 /* normalize root path */
2341 if (a_rootPath == (char *)NULL) {
2342 a_rootPath = "";
2345 /* entry debugging info */
2347 echoDebug(DBG_CHECKAPP_ENTRY);
2348 echoDebug(DBG_CHECKAPP_ARGS, a_pkgInst, a_packageDir, a_rootPath);
2351 * calculate paths to various objects
2354 /* path to package to be installed top level (main) directory */
2356 len = snprintf(pkgpath, sizeof (pkgpath), "%s/%s", a_packageDir,
2357 a_pkgInst);
2358 if (len > sizeof (pkgpath)) {
2359 progerr(ERR_CREATE_PATH_2, a_packageDir, a_pkgInst);
2360 return (B_FALSE);
2363 /* error if package top level directory does not exist */
2365 if (isdir(pkgpath) != 0) {
2366 progerr(ERR_NO_PKGDIR, pkgpath, a_pkgInst, strerror(errno));
2367 return (B_FALSE);
2370 /* path to pkginfo file within the package to be installed */
2372 len = snprintf(pkginfoPath, sizeof (pkginfoPath), "%s/pkginfo",
2373 pkgpath);
2374 if (len > sizeof (pkginfoPath)) {
2375 progerr(ERR_CREATE_PATH_2, pkgpath, "pkginfo");
2376 return (B_FALSE);
2379 /* path to highest instance of package currently installed */
2381 pkgLocateHighestInst(instPkgPath, sizeof (instPkgPath),
2382 instPkg, sizeof (instPkg), a_rootPath, a_pkgInst);
2385 * gather information from this package's pkginfo file
2388 pkginfoFP = fopen(pkginfoPath, "r");
2390 if (pkginfoFP == (FILE *)NULL) {
2391 progerr(ERR_NO_PKG_INFOFILE, a_pkgInst, pkginfoPath,
2392 strerror(errno));
2393 return (B_FALSE);
2396 /* determine "HOLLOW" setting for this package */
2398 is_hollow = pkginfoParamTruth(pkginfoFP, PKG_HOLLOW_VARIABLE,
2399 "true", B_FALSE);
2401 /* determine "ALLZONES" setting for this package */
2403 all_zones = pkginfoParamTruth(pkginfoFP, PKG_ALLZONES_VARIABLE,
2404 "true", B_FALSE);
2406 /* determine "THISZONE" setting for this package */
2408 this_zone = pkginfoParamTruth(pkginfoFP, PKG_THISZONE_VARIABLE,
2409 "true", B_FALSE);
2411 /* close pkginfo file */
2413 (void) fclose(pkginfoFP);
2416 * If request file is not found, it may be in the datastream which
2417 * is not yet unpacked. Check in the pkgmap file.
2419 if (isfile(pkgpath, REQUEST_FILE) != 0) {
2421 /* path to pkgmap file within the package to be installed */
2422 (void) snprintf(pkgmapPath, sizeof (pkgmapPath), "%s/pkgmap",
2423 pkgpath);
2425 pkgmapFP = fopen(pkgmapPath, "r");
2427 if (pkgmapFP == NULL) {
2428 progerr(ERR_NO_PKG_MAPFILE, a_pkgInst,
2429 pkgmapPath, strerror(errno));
2430 return (B_FALSE);
2433 while (fgets(line, LINE_MAX, pkgmapFP) != NULL) {
2434 if (strstr(line, " i request") != NULL) {
2435 reqfile_found = B_TRUE;
2436 break;
2439 (void) fclose(pkgmapFP);
2440 } else {
2441 reqfile_found = B_TRUE;
2445 * If this package is not marked for installation in this zone only,
2446 * check to see if this package has a request script. If this package
2447 * does have a request script, then mark the package for installation
2448 * in this zone only. Any package with a request script cannot be
2449 * installed outside of the zone the pkgadd command is being run in,
2450 * nor can such a package be installed as part of a new zone install.
2451 * A new zone install must be non-interactive, which is required
2452 * by all packages integrated into the Solaris WOS.
2455 if ((!this_zone) && (reqfile_found)) {
2456 if (a_flags & CAF_IN_GLOBAL_ZONE) {
2457 echoDebug(DBG_CHECKAPP_THISZONE_REQUEST, a_pkgInst);
2459 this_zone = B_TRUE;
2463 * If this package is already installed, see if the current installation
2464 * of the package has a request file - if it does, then act as though
2465 * the current package to be added has a request file - install the
2466 * package in the current zone only.
2469 if ((!this_zone) && (instPkgPath[0] != '\0') &&
2470 (isfile(instPkgPath, REQUEST_FILE) == 0)) {
2471 if (a_flags & CAF_IN_GLOBAL_ZONE) {
2472 echoDebug(DBG_CHECKAPP_THISZONE_INSTREQ,
2473 a_pkgInst, instPkg);
2475 this_zone = B_TRUE;
2478 /* gather information from the global zone only file */
2480 in_gz_only = B_FALSE;
2481 if (a_flags & CAF_IN_GLOBAL_ZONE) {
2482 in_gz_only = pkgIsPkgInGzOnly(a_rootPath, a_pkgInst);
2485 /* determine if this package is currently installed */
2487 pkg_installed = pkginfoIsPkgInstalled((struct pkginfo **)NULL,
2488 a_pkgInst);
2491 * verify package applicability based on information gathered,
2492 * and validate the three SUNW_PKG_ options:
2494 * -----------|--------------|-------------|-------------|-----------
2495 * - - - - - -| GLOBAL ZONE -| GLOBAL ZONE | LOCAL ZONE | LOCAL ZONE
2496 * - - - - - -| - - pkgadd - | pkgadd -G | pkgadd | pkgadd -G
2497 * ----1------|--------------|-------------|-------------|------------
2498 * ALLZONES f | add to gz | add to gz | add to ls | add to ls
2499 * HOLLOW f | current lz | not to curr | only - - - -| only - - -
2500 * THISZONE f | futr lz - - -| or futr lz | - - - - - - | - - - - - -
2501 * ----2------|--------------|-------------|-------------|------------
2502 * ALLZONES T | add to gz | operation | operation | operation
2503 * HOLLOW f | current lz | not allowed | not allowed | not allowed
2504 * THISZONE f | future lz | - - - - - - | - - - - - - | - - - - - -
2505 * ----3------|--------------|-------------|-------------|------------
2506 * ALLZONES T | add to gz | operation | operation | operation
2507 * HOLLOW T | pkg db only | not allowed | not allowed | not allowed
2508 * THISZONE f | curr/futr lz | - - - - - - | - - - - - - | - - - - - -
2509 * ----4------|--------------|-------------|-------------|------------
2510 * ALLZONES T | bad option | bad option | bad option | bad option
2511 * HOLLOW * | combo - - - -| combo - - - | combo - - - | combo - -
2512 * THISZONE T | - - - - - - -|- - - - - - -|- - - - - - -|- - - - - -
2513 * ----5------|--------------|-------------|-------------|------------
2514 * ALLZONES f | bad option | bad option | bad option | bad option
2515 * HOLLOW T | combo - - - -| combo - - - | combo - - - | combo - - -
2516 * THISZONE * | - - - - - - -| - - - - - - | - - - - - - | - - - - - -
2517 * ----6------|--------------|-------------|-------------|------------
2518 * ALLZONES f | add to gz | add to gz | add to lz | add to lz
2519 * HOLLOW f | not current | not current | only - - - | only - - -
2520 * THISZONE T | or future lz | or futr lz | - - - - - - | - - - - - -
2521 * -----------|--------------|-------------|-------------|-----------
2524 /* pkg "all zones" && "this zone" (#4) */
2526 if (all_zones && this_zone) {
2527 progerr(ERR_ALLZONES_AND_THISZONE, a_pkgInst,
2528 PKG_ALLZONES_VARIABLE, PKG_THISZONE_VARIABLE);
2529 return (B_FALSE);
2532 /* pkg "!all zones" && "hollow" (#5) */
2534 if ((!all_zones) && is_hollow) {
2535 progerr(ERR_NOW_ALLZONES_AND_HOLLOW, a_pkgInst,
2536 PKG_ALLZONES_VARIABLE, PKG_HOLLOW_VARIABLE);
2537 return (B_FALSE);
2540 /* pkg ALLZONES=true && -Z specified */
2542 if (all_zones && (a_flags & CAF_SCOPE_NONGLOBAL)) {
2543 progerr(ERR_ALLZONES_AND_Z_USED, a_pkgInst);
2544 return (B_FALSE);
2547 /* pkg ALLZONES=true & not running in global zone (#2/#3) */
2549 if (all_zones && (!(a_flags & CAF_IN_GLOBAL_ZONE))) {
2550 progerr(ERR_ALLZONES_AND_IN_LZ, a_pkgInst);
2551 return (B_FALSE);
2554 /* pkg "in gz only" & pkg "NOT installed" */
2556 if (in_gz_only && (!pkg_installed)) {
2557 /* MAKE A WARNING */
2558 echo(ERR_IN_GZ_AND_NOT_INSTALLED, a_pkgInst,
2559 pkgGetGzOnlyPath());
2562 /* pkg ALLZONES=true & pkg "in gz only" & pkg "is installed" */
2564 if (all_zones && in_gz_only && pkg_installed) {
2565 progerr(ERR_IN_GZ_AND_ALLZONES_AND_INSTALLED, a_pkgInst);
2566 return (B_FALSE);
2569 /* pkg ALLZONES=true && -G specified (#2/#3) */
2571 if (all_zones && (a_flags & CAF_SCOPE_GLOBAL)) {
2572 progerr(ERR_ALLZONES_AND_G_USED, a_pkgInst);
2573 return (B_FALSE);
2576 /* pkg "!this zone" && "in gz only" & -G not specified */
2578 if ((!this_zone) && in_gz_only && (!(a_flags & CAF_SCOPE_GLOBAL))) {
2579 progerr(ERR_IN_GZ_AND_NO_G_USED, a_pkgInst);
2580 return (B_FALSE);
2583 /* pkg "NOT in gz only" & -Z specified */
2585 if ((!in_gz_only) && (a_flags & CAF_SCOPE_NONGLOBAL)) {
2586 progerr(ERR_NOT_IN_GZ_AND_Z_USED, a_pkgInst);
2587 return (B_FALSE);
2590 /* pkg "this zone" && -Z specified */
2592 if (this_zone && (a_flags & CAF_SCOPE_NONGLOBAL)) {
2593 progerr(ERR_THISZONE_AND_Z_USED, PKG_THISZONE_VARIABLE,
2594 a_pkgInst);
2595 return (B_FALSE);
2599 * If this package is marked 'this zone only', then mark the package
2600 * as "add to this zone only". This is referenced by the various
2601 * add_package_... functions to determine if the package should be
2602 * added to the current zone, or to all zones, depending on the
2603 * zone in which the command is being run.
2606 if (this_zone) {
2607 pkgAddThisZonePackage(a_pkgInst);
2610 return (B_TRUE);
2614 * Name: create_zone_adminfile
2615 * Description: Given a zone temporary directory and optionally an existing
2616 * administration file, generate an administration file that
2617 * can be used to perform "non-interactive" operations in a
2618 * non-global zone.
2619 * Arguments: r_zoneAdminFile - pointer to handle that will contain a
2620 * string representing the path to the temporary
2621 * administration file created - this must be NULL
2622 * before the first call to this function - on
2623 * subsequent calls if the pointer is NOT null then
2624 * the existing string will NOT be overwritten.
2625 * a_zoneTempDir - pointer to string representing the path
2626 * to the zone temporary directory to create the
2627 * temporary administration file in
2628 * a_admnfile - pointer to string representing the path to
2629 * an existing "user" administration file - the
2630 * administration file created will contain the
2631 * settings contained in this file, modified as
2632 * appropriate to supress any interaction;
2633 * If this is == NULL then the administration file
2634 * created will not contain any extra settings
2635 * Returns: void
2636 * NOTE: Any string returned is placed in new storage for the
2637 * calling method. The caller must use 'free' to dispose
2638 * of the storage once the string is no longer needed.
2639 * NOTE: On any error this function will call 'quit(1)'
2642 static void
2643 create_zone_adminfile(char **r_zoneAdminFile, char *a_zoneTempDir,
2644 char *a_admnfile)
2646 boolean_t b;
2648 /* entry assertions */
2650 assert(r_zoneAdminFile != (char **)NULL);
2651 assert(a_zoneTempDir != (char *)NULL);
2652 assert(*a_zoneTempDir != '\0');
2654 /* entry debugging info */
2656 echoDebug(DBG_CREATE_ZONE_ADMINFILE, a_zoneTempDir, PSTR(a_admnfile));
2658 /* if temporary name already exists, do not overwrite */
2660 if (*r_zoneAdminFile != (char *)NULL) {
2661 return;
2664 /* create temporary name */
2666 *r_zoneAdminFile = tempnam(a_zoneTempDir, "zadmn");
2667 b = z_create_zone_admin_file(*r_zoneAdminFile, a_admnfile);
2668 if (b == B_FALSE) {
2669 progerr(ERR_CREATE_TMPADMIN, *r_zoneAdminFile,
2670 strerror(errno));
2671 quit(1);
2672 /* NOTREACHED */
2675 echoDebug(DBG_CREATED_ZONE_ADMINFILE, *r_zoneAdminFile);
2679 * Name: create_zone_tempdir
2680 * Description: Given a system temporary directory, create a "zone" specific
2681 * temporary directory and return the path to the directory
2682 * created.
2683 * Arguments: r_zoneTempDir - pointer to handle that will contain a
2684 * string representing the path to the temporary
2685 * directory created - this must be NULL before the
2686 * first call to this function - on subsequent calls
2687 * if the pointer is NOT null then the existing string
2688 * will NOT be overwritten.
2689 * a_zoneTempDir - pointer to string representing the path
2690 * to the system temporary directory to create the
2691 * temporary zone directory in
2692 * Returns: void
2693 * NOTE: Any string returned is placed in new storage for the
2694 * calling method. The caller must use 'free' to dispose
2695 * of the storage once the string is no longer needed.
2696 * NOTE: On any error this function will call 'quit(1)'
2697 * NOTE: This function calls "quitSetZoneTmpdir" on success to
2698 * register the directory created with quit() so that the
2699 * directory will be automatically deleted on exit.
2702 static void
2703 create_zone_tempdir(char **r_zoneTempDir, char *a_tmpdir)
2705 boolean_t b;
2707 /* entry assertions */
2709 assert(r_zoneTempDir != (char **)NULL);
2710 assert(a_tmpdir != (char *)NULL);
2711 assert(*a_tmpdir != '\0');
2713 /* entry debugging info */
2715 echoDebug(DBG_CREATE_ZONE_TEMPDIR, a_tmpdir);
2717 /* if temporary directory already exists, do not overwrite */
2719 if (*r_zoneTempDir != (char *)NULL) {
2720 return;
2723 /* create temporary directory */
2725 b = setup_temporary_directory(r_zoneTempDir, a_tmpdir, "ztemp");
2726 if (b == B_FALSE) {
2727 progerr(ERR_ZONETEMPDIR, a_tmpdir, strerror(errno));
2728 quit(1);
2729 /* NOTREACHED */
2732 /* register with quit() so directory is removed on exit */
2734 quitSetZoneTmpdir(*r_zoneTempDir);
2736 /* exit debugging info */
2738 echoDebug(DBG_CREATED_ZONE_TEMPDIR, *r_zoneTempDir);
2742 * Name: continue_installation
2743 * Description: Called from within a loop that is installing packages,
2744 * this function examines various global variables and decides
2745 * whether or not to ask an appropriate question, and wait for
2746 * and appropriate reply.
2747 * Arguments: <<global variables>>
2748 * Returns: B_TRUE - continue processing with next package
2749 * B_FALSE - do not continue processing with next package
2752 static boolean_t
2753 continue_installation(void)
2755 char ans[MAX_INPUT];
2756 int n;
2758 /* return TRUE if not interrupted */
2760 if (!interrupted) {
2761 return (B_TRUE);
2765 * process interrupted - determine whether or not to continue
2768 /* output appropriate interrupted message */
2770 if (askflag) {
2771 echo(npkgs == 1 ? MSG_1MORE_PROC : MSG_MORE_PROC, npkgs);
2772 } else {
2773 echo(npkgs == 1 ? MSG_1MORE_INST : MSG_MORE_INST, npkgs);
2776 /* if running with no interaction (-n) do not ask question */
2778 if (nointeract) {
2779 /* if admin required return 'dont continue' */
2780 if (needconsult) {
2781 return (B_FALSE);
2783 ckquit = 1;
2784 return (B_TRUE);
2787 /* interaction possible: ask question */
2789 ckquit = 0;
2790 n = ckyorn(ans, NULL, NULL, NULL, ASK_CONTINUE_ADD);
2791 if (n != 0) {
2792 quit(n);
2793 /* NOTREACHED */
2795 ckquit = 1;
2796 if (strchr("yY", *ans) == NULL) {
2797 return (B_FALSE);
2799 return (B_TRUE);
2803 * package can be in a number of formats:
2804 * - file containing package stream (pkgadd -d file [pkgs])
2805 * - directory containing packages (pkgadd -d /dir [pkgs])
2806 * - device containing packages (pkgadd -d diskette1 [pkgs])
2807 * non-global zones can be passed open files and strings as arguments
2808 * - for file containing package stream
2809 * -- the stream can be passed directly to the non-global zone
2810 * - for directory
2811 * -- convert packages to datastream to pass to the non-global zone
2812 * - for device
2813 * -- ?
2816 static boolean_t
2817 unpack_and_check_packages(char **a_pkgList, char *a_idsName, char *a_packageDir)
2819 int savenpkgs = npkgs;
2820 int i;
2821 CAF_T flags = 0;
2823 /* entry assertions */
2825 assert(a_pkgList != (char **)NULL);
2827 /* entry debugging info */
2829 echoDebug(DBG_UNPACKCHECK_ENTRY);
2830 echoDebug(DBG_UNPACKCHECK_ARGS, PSTR(a_idsName), PSTR(a_packageDir));
2833 * set flags for applicability check
2836 /* determine if running in the global zone */
2838 if (z_running_in_global_zone() == B_TRUE) {
2839 flags |= CAF_IN_GLOBAL_ZONE;
2842 /* set -G flag */
2844 if (globalZoneOnly == B_TRUE) {
2845 flags |= CAF_SCOPE_GLOBAL;
2849 * for each package to install:
2850 * - if packages from datastream, unpack package into package dir
2851 * - check applicability of installing package on this system/zone
2854 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
2855 if (a_idsName != (char *)NULL) {
2856 /* create stream out of package if not already one */
2857 if (unpack_package_from_stream(a_idsName, pkginst,
2858 a_packageDir) == B_FALSE) {
2859 progerr(ERR_CANNOT_UNPACK_PKGSTRM,
2860 PSTR(pkginst), PSTR(a_idsName),
2861 PSTR(a_packageDir));
2863 npkgs = savenpkgs;
2864 return (B_FALSE);
2866 } else {
2867 echoDebug(DBG_PKG_IN_DIR, pkginst, a_packageDir);
2870 /* check package applicability */
2871 if (check_applicability(a_packageDir,
2872 pkginst, get_inst_root(), flags) == B_FALSE) {
2873 progerr(ERR_PKG_NOT_INSTALLABLE, pkginst);
2874 npkgs = savenpkgs;
2875 return (B_FALSE);
2877 npkgs--;
2880 npkgs = savenpkgs;
2881 return (B_TRUE);
2885 * returns:
2886 * B_TRUE - package list generated
2887 * B_FALSE - failed to generate package list
2888 * Will call quit(n) on fatal error.
2891 static boolean_t
2892 get_package_list(char ***r_pkgList, char **a_argv, char *a_categories,
2893 char **a_categoryList, char *a_idsName, int *r_repeat)
2895 int n;
2897 /* entry assertions */
2899 assert(r_repeat != (int *)NULL);
2901 /* entry debugging info */
2903 echoDebug(DBG_GETPKGLIST_ENTRY);
2904 echoDebug(DBG_GETPKGLIST_ARGS, PSTR(a_idsName), PSTR(pkgdev.dirname),
2905 *r_repeat);
2908 * get the list of the packages to add
2911 n = pkgGetPackageList(r_pkgList, a_argv, optind, a_categories,
2912 a_categoryList, &pkgdev);
2914 switch (n) {
2915 case -1: /* no packages found */
2916 echoDebug(DBG_PKGLIST_NONFOUND, PSTR(a_idsName),
2917 pkgdev.dirname);
2918 return (B_FALSE);
2920 case 0: /* packages found */
2921 break;
2923 default: /* "quit" error */
2924 echoDebug(DBG_PKGLIST_ERROR, PSTR(a_idsName),
2925 pkgdev.dirname, n);
2926 quit(n);
2927 /* NOTREACHED */
2930 /* order package list if input data stream specified */
2932 if (a_idsName) {
2933 ds_order(*r_pkgList);
2936 return (B_TRUE);
2940 * Name: install_in_one_zone
2941 * Description: Install a single package in a single zone
2942 * Arguments: a_zoneName - pointer to string representing the name of the
2943 * zone to install the package into.
2944 * a_idsName - pointer to string representing the data stream
2945 * device (input data stream) containing the package to
2946 * be installed.
2947 * If this is == NULL the package is assumed to be
2948 * spooled in the zone temporary directory.
2949 * a_zoneAdminFile - pointer to string representing the admin
2950 * file to pass to pkginstall when installing the package.
2951 * If this is == NULL no admin file is given to pkginstall.
2952 * a_zoneTempDir - pointer to string representing the temporary
2953 * directory in which spooled packages can be found if
2954 * a_idsName is == NULL.
2955 * a_altBinDir - pointer to string representing an alternative
2956 * binary location directory to pass to pkginstall.
2957 * If this is == NULL no alternative binary location is
2958 * passed to pkginstall.
2959 * a_scratchName - pointer to string representing the name of the
2960 * scratch zone to use for installation.
2961 * a_zoneState - state of the zone; must be mounted or running.
2962 * a_tmpzn - B_TRUE when this zone is booted by the package
2963 * command or B_FALSE if it was running before.
2964 * Returns: void
2965 * NOTE: As a side effect, "ckreturn" is called on the result returned
2966 * from running 'pkginstall' in the zone; this sets several global
2967 * variables which allows the caller to determine the result of
2968 * the installation operation.
2971 static void
2972 install_in_one_zone(char *a_zoneName, char *a_idsName,
2973 char *a_zoneAdminFile, char *a_zoneTempDir,
2974 char *a_altBinDir, zone_state_t a_zoneState, boolean_t a_tmpzn)
2976 char zoneStreamName[PATH_MAX] = {'\0'};
2977 int n;
2979 /* entry assertions */
2981 assert(a_zoneName != (char *)NULL);
2982 assert(*a_zoneName != '\0');
2984 /* entry debugging info */
2986 echoDebug(DBG_INSTINONEZONE_ENTRY);
2987 echoDebug(DBG_INSTINONEZONE_ARGS, a_zoneName, PSTR(a_idsName),
2988 PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir),
2989 PSTR(a_altBinDir));
2991 /* echo operation to perform to stdout */
2993 echo(MSG_INSTALL_PKG_IN_ZONE, pkginst, a_zoneName);
2995 /* determine path to the package stream */
2997 if (a_idsName == (char *)NULL) {
2998 /* locate temp stream created earlier */
2999 (void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3000 "%s/%s.dstream", a_zoneTempDir, pkginst);
3001 } else {
3002 /* use stream passed in on command line */
3003 (void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3004 "%s", a_idsName);
3007 echoDebug(DBG_INSTALL_IN_ZONE, pkginst, a_zoneName, zoneStreamName);
3009 n = pkgZoneInstall(a_zoneName, a_zoneState, zoneStreamName,
3010 a_altBinDir, a_zoneAdminFile, a_tmpzn);
3012 /* set success/fail condition variables */
3014 ckreturn(n);
3016 /* exit debugging info */
3018 echoDebug(DBG_INSTALL_FLAG_VALUES, "after install", admnflag, doreboot,
3019 failflag, interrupted, intrflag, ireboot, needconsult,
3020 nullflag, warnflag);
3024 * Name: install_in_zones
3025 * Description: Install a single package in the zones that are running from
3026 * a list of zones
3027 * Arguments: a_zlst - list of zones to install the package into
3028 * a_idsName - pointer to string representing the data stream
3029 * device (input data stream) containing the package to
3030 * be installed.
3031 * If this is == NULL the package is assumed to be
3032 * spooled in the zone temporary directory.
3033 * a_altBinDir - pointer to string representing an alternative
3034 * binary location directory to pass to pkginstall.
3035 * If this is == NULL no alternative binary location is
3036 * passed to pkginstall.
3037 * a_zoneAdminFile - pointer to string representing the admin
3038 * file to pass to pkginstall when installing the package.
3039 * If this is == NULL no admin file is given to pkginstall.
3040 * a_zoneTempDir - pointer to string representing the temporary
3041 * directory in which spooled packages can be found if
3042 * a_idsName is == NULL.
3045 static int
3046 install_in_zones(zoneList_t a_zlst, char *a_idsName, char *a_altBinDir,
3047 char *a_zoneAdminFile, char *a_zoneTempDir)
3049 char *zoneName;
3050 int zoneIndex;
3051 int zonesSkipped = 0;
3052 zone_state_t zst;
3054 /* entry assertions */
3056 assert(a_zlst != (zoneList_t)NULL);
3058 /* entry debugging info */
3060 echoDebug(DBG_INSTALLINZONES_ENTRY);
3061 echoDebug(DBG_INSTALLINZONES_ARGS, PSTR(a_idsName),
3062 PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir));
3064 /* process each zone in the list */
3066 for (zoneIndex = 0;
3067 (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3068 zoneIndex++) {
3070 /* skip the zone if it is NOT running */
3072 zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3073 if (zst != ZONE_STATE_RUNNING && zst != ZONE_STATE_MOUNTED) {
3074 zonesSkipped++;
3075 echoDebug(DBG_SKIPPING_ZONE, zoneName);
3076 continue;
3079 /* install the package in this zone */
3081 install_in_one_zone(z_zlist_get_scratch(a_zlst, zoneIndex),
3082 a_idsName, a_zoneAdminFile, a_zoneTempDir, a_altBinDir,
3083 zst, B_FALSE);
3086 return (zonesSkipped);
3090 * Name: boot_and_install_in_zones
3091 * Description: Install a single package in the zones that are NOT running from
3092 * a list of zones - each zone is booted, the package installed,
3093 * and the zone is halted
3094 * Arguments: a_zlst - list of zones to install the package into
3095 * a_idsName - pointer to string representing the data stream
3096 * device (input data stream) containing the package to
3097 * be installed.
3098 * If this is == NULL the package is assumed to be
3099 * spooled in the zone temporary directory.
3100 * a_altBinDir - pointer to string representing an alternative
3101 * binary location directory to pass to pkginstall.
3102 * If this is == NULL no alternative binary location is
3103 * passed to pkginstall.
3104 * a_zoneAdminFile - pointer to string representing the admin
3105 * file to pass to pkginstall when installing the package.
3106 * If this is == NULL no admin file is given to pkginstall.
3107 * a_zoneTempDir - pointer to string representing the temporary
3108 * directory in which spooled packages can be found if
3109 * a_idsName is == NULL.
3112 static int
3113 boot_and_install_in_zones(zoneList_t a_zlst, char *a_idsName, char *a_altBinDir,
3114 char *a_zoneAdminFile, char *a_zoneTempDir)
3116 boolean_t b;
3117 char *zoneName;
3118 int zoneIndex;
3119 int zonesSkipped = 0;
3120 zone_state_t zst;
3122 /* entry assertions */
3124 assert(a_zlst != (zoneList_t)NULL);
3126 /* entry debugging info */
3128 echoDebug(DBG_BOOTINSTALLINZONES_ENTRY);
3129 echoDebug(DBG_BOOTINSTALLINZONES_ARGS, PSTR(a_idsName),
3130 PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir));
3132 /* process each zone in the list */
3134 for (zoneIndex = 0;
3135 (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3136 zoneIndex++) {
3138 /* skip the zone if it IS running */
3140 zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3141 if (zst == ZONE_STATE_RUNNING || zst == ZONE_STATE_MOUNTED) {
3142 echoDebug(DBG_SKIPPING_ZONE_BOOT, zoneName);
3143 continue;
3146 /* skip the zone if it is NOT bootable */
3148 if (z_zlist_is_zone_runnable(a_zlst, zoneIndex) == B_FALSE) {
3149 echo(MSG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3150 echoDebug(DBG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3151 continue;
3154 /* mount up the zone */
3156 echo(MSG_BOOTING_ZONE, zoneName);
3157 echoDebug(DBG_BOOTING_ZONE, zoneName);
3159 b = z_zlist_change_zone_state(a_zlst, zoneIndex,
3160 ZONE_STATE_MOUNTED);
3161 if (b == B_FALSE) {
3162 progerr(ERR_CANNOT_BOOT_ZONE, zoneName);
3163 /* set fatal error return condition */
3164 ckreturn(1);
3165 zonesSkipped++;
3166 continue;
3169 /* install the package in this zone */
3171 install_in_one_zone(z_zlist_get_scratch(a_zlst, zoneIndex),
3172 a_idsName, a_zoneAdminFile, a_zoneTempDir, a_altBinDir,
3173 ZONE_STATE_MOUNTED, B_TRUE);
3175 /* restore original state of zone */
3177 echo(MSG_RESTORE_ZONE_STATE, zoneName);
3178 echoDebug(DBG_RESTORE_ZONE_STATE, zoneName);
3180 b = z_zlist_restore_zone_state(a_zlst, zoneIndex);
3183 return (zonesSkipped);
3187 * Name: pkginstall_check_in_one_zone
3188 * Description: Do a pre install check of a single package in a single zone
3189 * Arguments: a_zoneName - pointer to string representing the name of the
3190 * zone to check install the package in.
3191 * a_idsName - pointer to string representing the data stream
3192 * device (input data stream) containing the package to
3193 * be check installed.
3194 * If this is == NULL the package is assumed to be
3195 * spooled in the zone temporary directory.
3196 * a_zoneAdminFile - pointer to string representing the admin
3197 * file to pass to pkginstall when installing the package.
3198 * If this is == NULL no admin file is given to pkginstall.
3199 * a_zoneTempDir - pointer to string representing the temporary
3200 * directory in which spooled packages can be found if
3201 * a_idsName is == NULL.
3202 * a_altBinDir - pointer to string representing an alternative
3203 * binary location directory to pass to pkginstall.
3204 * If this is == NULL no alternative binary location is
3205 * passed to pkginstall.
3206 * a_scratchName - pointer to string representing the name of the
3207 * scratch zone to use for installation.
3208 * a_zoneState - state of the zone; must be mounted or running.
3209 * a_tmpzn - B_TRUE when this zone is booted by the package
3210 * command or B_FALSE if it was running before.
3211 * Returns: void
3212 * NOTE: As a side effect, "ckreturn" is called on the result returned
3213 * from running 'pkginstall' in the zone; this sets several global
3214 * variables which allows the caller to determine the result of
3215 * the pre installation check operation.
3218 static void
3219 pkginstall_check_in_one_zone(char *a_zoneName,
3220 char *a_idsName, char *a_zoneAdminFile, char *a_zoneTempDir,
3221 char *a_altBinDir, char *a_scratchName, zone_state_t a_zoneState,
3222 boolean_t a_tmpzn)
3224 char preinstallcheckPath[PATH_MAX+1];
3225 char zoneStreamName[PATH_MAX] = {'\0'};
3226 int n;
3228 echo(MSG_CHECKINSTALL_PKG_IN_ZONE, pkginst, a_zoneName);
3229 echoDebug(MSG_CHECKINSTALL_PKG_IN_ZONE, pkginst, a_zoneName);
3231 (void) snprintf(preinstallcheckPath, sizeof (preinstallcheckPath),
3232 "%s/%s.%s.preinstallcheck.txt", a_zoneTempDir, pkginst,
3233 a_zoneName);
3235 if (a_idsName == (char *)NULL) {
3236 /* locate temporary stream created earlier */
3237 (void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3238 "%s/%s.dstream", a_zoneTempDir, pkginst);
3239 } else {
3240 (void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3241 "%s", a_idsName);
3244 echoDebug(DBG_CHECKINSTALL_IN_ZONE, pkginst, a_zoneName,
3245 zoneStreamName);
3247 n = pkgZoneCheckInstall(a_scratchName, a_zoneState, zoneStreamName,
3248 a_altBinDir, a_zoneAdminFile, preinstallcheckPath, a_tmpzn);
3250 /* set success/fail condition variables */
3252 ckreturn(n);
3254 echoDebug(DBG_INSTALL_FLAG_VALUES, "after preinstall check",
3255 admnflag, doreboot, failflag, interrupted, intrflag,
3256 ireboot, needconsult, nullflag, warnflag);
3260 * Name: pkginstall_check_in_zones
3261 * Description: Check installation of a single package in the zones that
3262 * are running from a list of zones
3263 * Arguments: a_zlst - list of zones to check install the package
3264 * a_idsName - pointer to string representing the data stream
3265 * device (input data stream) containing the package to
3266 * be check installed.
3267 * If this is == NULL the package is assumed to be
3268 * spooled in the zone temporary directory.
3269 * a_altBinDir - pointer to string representing an alternative
3270 * binary location directory to pass to pkginstall.
3271 * If this is == NULL no alternative binary location is
3272 * passed to pkginstall.
3273 * a_zoneAdminFile - pointer to string representing the admin
3274 * file to pass to pkginstall when checking the installing
3275 * of the package.
3276 * If this is == NULL no admin file is given to pkginstall.
3277 * a_zoneTempDir - pointer to string representing the temporary
3278 * directory in which spooled packages can be found if
3279 * a_idsName is == NULL.
3282 static int
3283 pkginstall_check_in_zones(zoneList_t a_zlst, char *a_idsName, char *a_altBinDir,
3284 char *a_zoneAdminFile, char *a_zoneTempDir)
3286 char *zoneName;
3287 int zoneIndex;
3288 int zonesSkipped = 0;
3289 zone_state_t zst;
3291 for (zoneIndex = 0;
3292 (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3293 zoneIndex++) {
3295 zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3296 if (zst != ZONE_STATE_RUNNING && zst != ZONE_STATE_MOUNTED) {
3297 zonesSkipped++;
3298 echoDebug(DBG_SKIPPING_ZONE, zoneName);
3299 continue;
3302 pkginstall_check_in_one_zone(zoneName, a_idsName,
3303 a_zoneAdminFile, a_zoneTempDir, a_altBinDir,
3304 z_zlist_get_scratch(a_zlst, zoneIndex), zst, B_FALSE);
3307 return (zonesSkipped);
3311 * Name: boot_and_pkginstall_check_in_zones
3312 * Description: Check installation of a single package in the zones that
3313 * are NOT running from a list of zones - each zone is booted,
3314 * the package installation is checked, and the zone is halted.
3315 * Arguments: a_zlst - list of zones to install the package into
3316 * a_idsName - pointer to string representing the data stream
3317 * device (input data stream) containing the package to
3318 * be check installed.
3319 * If this is == NULL the package is assumed to be
3320 * spooled in the zone temporary directory.
3321 * a_altBinDir - pointer to string representing an alternative
3322 * binary location directory to pass to pkginstall.
3323 * If this is == NULL no alternative binary location is
3324 * passed to pkginstall.
3325 * a_zoneAdminFile - pointer to string representing the admin
3326 * file to pass to pkginstall when check installing the
3327 * package.
3328 * If this is == NULL no admin file is given to pkginstall.
3329 * a_zoneTempDir - pointer to string representing the temporary
3330 * directory in which spooled packages can be found if
3331 * a_idsName is == NULL.
3334 static int
3335 boot_and_pkginstall_check_in_zones(zoneList_t a_zlst, char *a_idsName,
3336 char *a_altBinDir, char *a_zoneAdminFile, char *a_zoneTempDir)
3338 int zoneIndex;
3339 int zonesSkipped = 0;
3340 char *zoneName;
3341 boolean_t b;
3342 zone_state_t zst;
3344 /* entry assertions */
3346 assert(a_zlst != (zoneList_t)NULL);
3348 /* entry debugging info */
3350 echoDebug(DBG_BOOTCHECKINSTALLINZONES_ENTRY);
3351 echoDebug(DBG_BOOTCHECKINSTALLINZONES_ARGS, PSTR(a_idsName),
3352 PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir));
3354 /* process each zone in the list */
3356 for (zoneIndex = 0;
3357 (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3358 zoneIndex++) {
3360 /* skip the zone if it IS running */
3362 zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3363 if (zst == ZONE_STATE_RUNNING || zst == ZONE_STATE_MOUNTED) {
3364 echoDebug(DBG_SKIPPING_ZONE_BOOT, zoneName);
3365 continue;
3368 /* skip the zone if it is NOT bootable */
3370 if (z_zlist_is_zone_runnable(a_zlst, zoneIndex) == B_FALSE) {
3371 echo(MSG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3372 echoDebug(DBG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3373 continue;
3376 /* mount up the zone */
3378 echo(MSG_BOOTING_ZONE, zoneName);
3379 echoDebug(DBG_BOOTING_ZONE, zoneName);
3381 b = z_zlist_change_zone_state(a_zlst, zoneIndex,
3382 ZONE_STATE_MOUNTED);
3383 if (b == B_FALSE) {
3384 progerr(ERR_CANNOT_BOOT_ZONE, zoneName);
3385 /* set fatal error return condition */
3386 ckreturn(1);
3387 zonesSkipped++;
3388 continue;
3391 /* pre-installation check of the package in this zone */
3393 pkginstall_check_in_one_zone(zoneName, a_idsName,
3394 a_zoneAdminFile, a_zoneTempDir, a_altBinDir,
3395 z_zlist_get_scratch(a_zlst, zoneIndex),
3396 ZONE_STATE_MOUNTED, B_TRUE);
3398 /* restore original state of zone */
3400 echo(MSG_RESTORE_ZONE_STATE, zoneName);
3401 echoDebug(DBG_RESTORE_ZONE_STATE, zoneName);
3403 b = z_zlist_restore_zone_state(a_zlst, zoneIndex);
3406 return (zonesSkipped);
3410 * Function: add_packages_in_global_with_zones
3411 * Description: call this function to add a list of packages in the global zone
3412 * when one or more non-global zones exist
3413 * returns:
3414 * B_TRUE to process next data stream
3415 * B_FALSE to exit
3418 static boolean_t
3419 add_packages_in_global_with_zones(char **a_pkgList,
3420 char *a_idsName, int a_repeat, char *a_altBinDir,
3421 char *a_device, zoneList_t a_zlst)
3423 static char *zoneTempDir = (char *)NULL;
3424 static char *zoneAdminFile = (char *)NULL;
3426 boolean_t b;
3427 char *packageDir;
3428 char instdir[PATH_MAX];
3429 char respfile_path[PATH_MAX];
3430 char zoneStreamName[PATH_MAX] = {'\0'};
3431 int i;
3432 int n;
3433 int savenpkgs = npkgs;
3434 int zonesSkipped;
3435 boolean_t globalPresent;
3437 /* entry assertions */
3439 assert(a_pkgList != (char **)NULL);
3440 assert(a_zlst != (zoneList_t)NULL);
3442 echoDebug(DBG_ADDPACKAGES_GZ_W_LZ_ENTRY);
3443 echoDebug(DBG_ADDPACKAGES_GZ_W_LZ_ARGS, npkgs,
3444 PSTR(a_idsName), a_repeat, PSTR(a_device));
3446 /* create temporary directory for use by zone operations */
3448 create_zone_tempdir(&zoneTempDir, tmpdir);
3450 /* create hands off settings admin file for use in a non-global zone */
3452 create_zone_adminfile(&zoneAdminFile, zoneTempDir, admnfile);
3454 /* determine directory where packages can be found */
3456 if (a_idsName == (char *)NULL) {
3457 /* no stream - directory containing packages provided */
3458 packageDir = pkgdev.dirname;
3459 } else {
3460 packageDir = zoneTempDir;
3463 /* unpack and check all packages */
3465 b = unpack_and_check_packages(a_pkgList, a_idsName, packageDir);
3466 if (b != B_TRUE) {
3467 quit(1);
3471 * if the packages are contained in a directory, convert the
3472 * packages into individual streams because pkgZoneInstall is only able
3473 * to pass a stream to the non-global zone's pkginstall command.
3474 * After this code is executed:
3475 * if the original input was a datastream:
3476 * -> that datastream has been unpacked into "instdir"
3477 * if the original input was a directory with packages in it:
3478 * -> those packages have been placed into a single datastream
3481 if (a_idsName == (char *)NULL) {
3482 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3483 char *pkgs[2];
3485 /* package is not a stream - create one */
3487 (void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3488 "%s/%s.dstream", zoneTempDir, pkginst);
3490 echoDebug(DBG_CONVERTING_PKG, packageDir, pkginst,
3491 zoneStreamName);
3493 /* set up list of packages to be this package only */
3495 pkgs[0] = pkginst;
3496 pkgs[1] = (char *)NULL;
3498 n = pkgtrans(packageDir, zoneStreamName, pkgs,
3499 PT_SILENT|PT_ODTSTREAM);
3500 if (n != 0) {
3501 progerr(ERR_CANNOT_CONVERT_PKGSTRM,
3502 pkginst, packageDir, zoneStreamName);
3503 quit(1);
3505 npkgs--;
3507 npkgs = savenpkgs;
3511 * Phase I - run collect dependency information for all packages for all
3512 * zones - this involves running pkginstall with the "preinstallcheck"
3513 * option which causes all dependency checks to be performed without
3514 * actually doing the installation of the packages. This information is
3515 * gathered in the zone temporary directory and is used later to present
3516 * the dependency check results to the system administrator depending
3517 * on the administration settings.
3520 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3522 /* reset interrupted flag before calling pkginstall */
3524 interrupted = 0; /* last action was NOT quit */
3527 * if this package is marked "install in this zone only", then
3528 * do not check dependencies in any other zone
3531 if (pkgPackageIsThisZone(pkginst) == B_TRUE) {
3532 echoDebug(DBG_VERIFY_SKIP_THISZONE, pkginst);
3533 npkgs--;
3534 continue;
3538 * if operation failed in global zone do not propagate
3539 * to any non-global zones
3542 if (interrupted != 0) {
3543 echo(MSG_CHECKINSTALL_INTERRUPT_B4_Z, pkginst);
3544 echoDebug(MSG_CHECKINSTALL_INTERRUPT_B4_Z, pkginst);
3545 break;
3548 echoDebug(DBG_INSTALL_FLAG_VALUES, "after pkginstall",
3549 admnflag, doreboot, failflag, interrupted, intrflag,
3550 ireboot, needconsult, nullflag, warnflag);
3553 * call pkginstall to verify this package for all non-global
3554 * zones that are currently booted
3557 zonesSkipped = pkginstall_check_in_zones(a_zlst, a_idsName,
3558 a_altBinDir, admnfile, zoneTempDir);
3561 * if any zones were skipped (becuase they are not currently
3562 * booted), boot each zone one at a time and call pkginstall
3563 * to verify this package for each such non-global zone
3566 if (zonesSkipped > 0) {
3567 echoDebug(DBG_ZONES_SKIPPED, zonesSkipped);
3569 zonesSkipped =
3570 boot_and_pkginstall_check_in_zones(a_zlst,
3571 a_idsName, a_altBinDir, admnfile,
3572 zoneTempDir);
3574 if (zonesSkipped > 0) {
3575 progerr(ERR_INSTALL_ZONES_SKIPPED,
3576 zonesSkipped);
3580 npkgs--;
3584 * At this point, all of the dependency information has been gathered
3585 * and is ready to be analyzed. This function processes all of that
3586 * dependency information and presents the results to the system
3587 * administrator, depending on the current administration settings.
3590 i = preinstall_verify(a_pkgList, a_zlst, zoneTempDir);
3591 if (i != 0) {
3592 /* dependency checks failed - exit */
3593 quit(i);
3596 npkgs = savenpkgs;
3599 * reset all error return condition variables that may have been
3600 * set during package installation dependency checking so that they
3601 * do not reflect on the success/failure of the actual package
3602 * installation operations
3605 resetreturn();
3608 * At this point, all of the dependency checking is completed, and
3609 * the installation of the packages can proceed. Install each package
3610 * one at a time, starting with the global zone, and the for each
3611 * non-global zone that is booted, and then for each non-global zone
3612 * that is not currently booted.
3615 globalPresent = z_on_zone_spec(GLOBAL_ZONENAME);
3617 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3619 * if immediate reboot required from last package and this is
3620 * not 'pkgask' then suspend installation of remaining packages
3623 if ((ireboot != 0) && (askflag == 0)) {
3624 ptext(stderr, MSG_SUSPEND_ADD, pkginst);
3625 continue;
3629 * handle interrupt if the previous pkginstall was interrupted
3632 if (continue_installation() == B_FALSE) {
3633 return (B_FALSE);
3637 * if pkgask, handle response file creation:
3638 * - if the response file is a directory, then create a path to
3639 * -- a package instance within the response file directory.
3640 * - If the response file is NOT a directory, if more than one
3641 * -- package is to be installed.
3644 if ((askflag != 0) && (respdir != (char *)NULL)) {
3645 (void) snprintf(respfile_path, sizeof (respfile_path),
3646 "%s/%s", respdir, pkginst);
3647 respfile = respfile_path;
3650 echo(MSG_PROC_INST, pkginst, a_device);
3653 * If we're installing another package in the same
3654 * session, the second through nth pkginstall, must
3655 * continue from where the prior one left off. For this
3656 * reason, the continuation feature (implied by the
3657 * nature of the command) is used for the remaining
3658 * packages.
3661 if ((i == 1) && (pkgdrtarg != (char *)NULL)) {
3662 pkgcontsrc = pkgdrtarg;
3665 if (globalPresent) {
3667 * call pkginstall for this package for the global zone
3670 echo(MSG_INSTALLING_PKG_IN_GZ, pkginst);
3672 /* reset interrupted flag before calling pkginstall */
3674 interrupted = 0; /* last action was NOT quit */
3676 n = pkgInstall(get_inst_root(), NULL, packageDir,
3677 a_altBinDir);
3679 /* set success/fail condition variables */
3681 ckreturn(n);
3684 * if operation failed in global zone do not propagate
3685 * to any non-global zones
3688 if (interrupted != 0) {
3689 echo(MSG_INSTALL_INTERRUPT_B4_ZONES, pkginst);
3690 echoDebug(MSG_INSTALL_INTERRUPT_B4_ZONES,
3691 pkginst);
3692 break;
3697 * if this package is marked "install in this zone only",
3698 * then only need to install the package in the global zone;
3699 * skip installation in any non-global zones.
3702 if (pkgPackageIsThisZone(pkginst) == B_TRUE) {
3703 echoDebug(DBG_INSTALL_SKIP_THISZONE, pkginst);
3704 npkgs--;
3705 continue;
3708 echoDebug(DBG_INSTALL_FLAG_VALUES, "install in running zones",
3709 admnflag, doreboot, failflag, interrupted, intrflag,
3710 ireboot, needconsult, nullflag, warnflag);
3712 /* install package in currently booted zones */
3714 zonesSkipped = install_in_zones(a_zlst, a_idsName, a_altBinDir,
3715 zoneAdminFile, zoneTempDir);
3717 /* install package in zones that are not currently booted */
3719 if (zonesSkipped > 0) {
3720 echoDebug(DBG_ZONES_SKIPPED, zonesSkipped);
3722 zonesSkipped = boot_and_install_in_zones(a_zlst,
3723 a_idsName, a_altBinDir, zoneAdminFile,
3724 zoneTempDir);
3726 if (zonesSkipped > 0) {
3727 progerr(ERR_INSTALL_ZONES_SKIPPED,
3728 zonesSkipped);
3733 * package completely installed - remove any temporary stream
3734 * of the package that might have been created
3737 if (a_idsName == (char *)NULL) {
3738 /* locate temporary stream created earlier */
3739 (void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3740 "%s/%s.dstream", zoneTempDir, pkginst);
3741 /* remove stream - no longer needed */
3742 echoDebug(DBG_REMOVING_DSTREAM_PKGDIR, zoneStreamName,
3743 pkginst);
3744 (void) remove(zoneStreamName);
3745 } else {
3746 /* remove package - no longer needed */
3747 if (snprintf(instdir, sizeof (instdir), "%s/%s",
3748 zoneTempDir, pkginst) >= PATH_MAX) {
3749 progerr(ERR_CANNOT_CREATE_PKGPATH, tmpdir);
3750 quit(1);
3752 echoDebug(DBG_REMOVING_PKG_TMPDIR, instdir, pkginst);
3753 (void) remove(instdir);
3756 /* decrement number of packages left to install */
3758 npkgs--;
3761 * if no packages left to install, unmount package source
3762 * device if appropriate
3765 if ((npkgs <= 0) && (pkgdev.mount || a_idsName)) {
3766 (void) chdir("/");
3767 if (!a_idsName) {
3768 echoDebug(DBG_UNMOUNTING_DEV,
3769 PSTR(pkgdev.mount));
3770 (void) pkgumount(&pkgdev);
3776 * all packages in the package list have been installed.
3777 * Continue with installation if:
3778 * -- immediate reboot is NOT required
3779 * -- there are more packages to install
3780 * -- the package source is a path to a file
3781 * else return do NOT continue.
3784 if ((ireboot == 0) && (a_repeat != 0) &&
3785 (pkgdev.pathname == (char *)NULL)) {
3786 return (B_TRUE);
3789 /* return 'dont continue' */
3791 return (B_FALSE);
3795 * Function: add_packages_in_nonglobal_zone
3796 * Description: call this function to add a list of packages in a non-global
3797 * zone
3798 * returns:
3799 * B_TRUE to process next data stream
3800 * B_FALSE to exit
3803 static boolean_t
3804 add_packages_in_nonglobal_zone(char **a_pkgList,
3805 char *a_idsName, int a_repeat, char *a_altBinDir, char *a_device)
3807 static char *zoneTempDir = (char *)NULL;
3809 char *packageDir;
3810 char respfile_path[PATH_MAX];
3811 int i;
3812 int n;
3813 boolean_t b;
3814 int savenpkgs = npkgs;
3816 /* entry assertions */
3818 assert(a_pkgList != (char **)NULL);
3820 /* entry debugging info */
3822 echoDebug(DBG_ADDPACKAGES_LZ_ENTRY);
3823 echoDebug(DBG_ADDPACKAGES_LZ_ARGS, npkgs, PSTR(a_idsName),
3824 a_repeat, PSTR(a_device));
3826 /* create temporary directory for use by zone operations */
3828 create_zone_tempdir(&zoneTempDir, tmpdir);
3831 * package can be in a number of formats:
3832 * - file containing package stream (pkgadd -d file [pkgs])
3833 * - directory containing packages (pkgadd -d /dir [pkgs])
3834 * - device containing packages (pkgadd -d diskette1 [pkgs])
3835 * non-global zones can be passed open file drescriptors and
3836 * strings as arguments
3837 * - for file containing package stream
3838 * -- the stream can be passed directly to the non-global zone
3839 * - for directory
3840 * -- convert packages to datastream to pass to the non-global zone
3841 * - for device
3844 /* determine directory where packages can be found */
3846 if (a_idsName == (char *)NULL) {
3847 /* no stream - directory containing packages provided */
3848 packageDir = pkgdev.dirname;
3849 } else {
3850 packageDir = zoneTempDir;
3853 b = unpack_and_check_packages(a_pkgList, a_idsName, packageDir);
3854 if (b != B_TRUE) {
3855 quit(1);
3859 * this is the main loop where all of the packages (as listed in the
3860 * package list) are added one at a time.
3863 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3864 npkgs--;
3867 npkgs = savenpkgs;
3870 * this is the main loop where all of the packages (as listed in the
3871 * package list) are added one at a time.
3874 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3876 * if immediate reboot required from last package and this is
3877 * not 'pkgask' then suspend installation of remaining packages
3880 if ((ireboot != 0) && (askflag == 0)) {
3881 ptext(stderr, MSG_SUSPEND_ADD, pkginst);
3882 continue;
3886 * handle interrupt if the previous pkginstall was interrupted
3889 if (continue_installation() == B_FALSE) {
3890 return (B_FALSE);
3894 * if pkgask, handle response file creation:
3895 * - if the response file is a directory, then create a path to
3896 * -- a package instance within the response file directory.
3897 * - If the response file is NOT a directory, if more than one
3898 * -- package is to be installed.
3901 if ((askflag != 0) && (respdir != (char *)NULL)) {
3902 (void) snprintf(respfile_path, sizeof (respfile_path),
3903 "%s/%s", respdir, pkginst);
3904 respfile = respfile_path;
3907 echo(MSG_PROC_INST, pkginst, a_device);
3910 * If we're installing another package in the same
3911 * session, the second through nth pkginstall, must
3912 * continue from where the prior one left off. For this
3913 * reason, the continuation feature (implied by the
3914 * nature of the command) is used for the remaining
3915 * packages.
3918 if ((i == 1) && (pkgdrtarg != (char *)NULL)) {
3919 pkgcontsrc = pkgdrtarg;
3922 /* reset interrupted flag before calling pkginstall */
3924 interrupted = 0; /* last action was NOT quit */
3926 /* call pkginstall for this package */
3928 n = pkgInstall(get_inst_root(), NULL,
3929 packageDir, a_altBinDir);
3931 /* set success/fail condition variables */
3933 ckreturn(n);
3935 /* decrement number of packages left to install */
3937 npkgs--;
3940 * if no packages left to install, unmount package source
3941 * device if appropriate
3944 if ((npkgs <= 0) && (pkgdev.mount || a_idsName)) {
3945 (void) chdir("/");
3946 if (!a_idsName) {
3947 (void) pkgumount(&pkgdev);
3953 * all packages in the package list have been installed.
3954 * Continue with installation if:
3955 * -- immediate reboot is NOT required
3956 * -- there are more packages to install
3957 * -- the package source is a path to a file
3958 * else return do NOT continue.
3961 if ((ireboot == 0) && (a_repeat != 0) &&
3962 (pkgdev.pathname == (char *)NULL)) {
3963 return (B_TRUE);
3966 /* return 'dont continue' */
3968 return (B_FALSE);
3972 * Function: add_packages_in_global_no_zones
3973 * Description: call this function to add a list of packages in the global zone
3974 * when no non-global zones exist
3975 * returns:
3976 * B_TRUE to process next data stream
3977 * B_FALSE to exit
3980 static boolean_t
3981 add_packages_in_global_no_zones(char **a_pkgList,
3982 char *a_idsName, int a_repeat, char *a_altBinDir, char *a_device)
3984 int n;
3985 int i;
3986 char respfile_path[PATH_MAX];
3987 CAF_T flags = 0;
3989 /* entry assertions */
3991 assert(a_pkgList != (char **)NULL);
3993 echoDebug(DBG_ADDPACKAGES_GZ_NO_LZ_ENTRY);
3994 echoDebug(DBG_ADDPACKAGES_GZ_NO_LZ_ARGS, npkgs,
3995 PSTR(a_idsName), a_repeat, PSTR(a_device));
3998 * set flags for applicability check
4001 /* in the global zone */
4003 flags |= CAF_IN_GLOBAL_ZONE;
4005 /* set -G flag */
4007 if (globalZoneOnly == B_TRUE) {
4008 flags |= CAF_SCOPE_GLOBAL;
4012 * this is the main loop where all of the packages (as listed in the
4013 * package list) are added one at a time.
4016 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
4018 * if immediate reboot required from last package and this is
4019 * not 'pkgask' then suspend installation of remaining packages
4022 if ((ireboot != 0) && (askflag == 0)) {
4023 ptext(stderr, MSG_SUSPEND_ADD, pkginst);
4024 continue;
4028 * handle interrupt if the previous pkginstall was interrupted
4031 if (continue_installation() == B_FALSE) {
4032 return (B_FALSE);
4036 * check package applicability to install in this context
4039 if (check_applicability(pkgdev.dirname,
4040 pkginst, get_inst_root(), flags) == B_FALSE) {
4041 progerr(ERR_PKG_NOT_APPLICABLE, pkginst);
4042 quit(1);
4046 * if pkgask, handle response file creation:
4047 * - if the response file is a directory, then create a path to
4048 * -- a package instance within the response file directory.
4049 * - If the response file is NOT a directory, if more than one
4050 * -- package is to be installed.
4053 if ((askflag != 0) && (respdir != (char *)NULL)) {
4054 (void) snprintf(respfile_path, sizeof (respfile_path),
4055 "%s/%s", respdir, pkginst);
4056 respfile = respfile_path;
4059 echo(MSG_PROC_INST, pkginst, a_device);
4062 * If we're installing another package in the same
4063 * session, the second through nth pkginstall, must
4064 * continue from where the prior one left off. For this
4065 * reason, the continuation feature (implied by the
4066 * nature of the command) is used for the remaining
4067 * packages.
4070 if ((i == 1) && (pkgdrtarg != (char *)NULL)) {
4071 pkgcontsrc = pkgdrtarg;
4074 /* reset interrupted flag before calling pkginstall */
4076 interrupted = 0; /* last action was NOT quit */
4078 /* call pkginstall for this package */
4080 n = pkgInstall(get_inst_root(), a_idsName,
4081 pkgdev.dirname, a_altBinDir);
4083 /* set success/fail condition variables */
4085 ckreturn(n);
4087 /* decrement number of packages left to install */
4089 npkgs--;
4092 * if no packages left to install, unmount package source
4093 * device if appropriate
4096 if ((npkgs <= 0) && (pkgdev.mount || a_idsName)) {
4097 (void) chdir("/");
4098 if (!a_idsName) {
4099 (void) pkgumount(&pkgdev);
4105 * all packages in the package list have been installed.
4106 * Continue with installation if:
4107 * -- immediate reboot is NOT required
4108 * -- there are more packages to install
4109 * -- the package source is a path to a file
4110 * else return do NOT continue.
4113 if ((ireboot == 0) && (a_repeat != 0) &&
4114 (pkgdev.pathname == (char *)NULL)) {
4115 return (B_TRUE);
4118 /* return 'dont continue' */
4120 return (B_FALSE);
4124 * returns:
4125 * B_TRUE to process next data stream
4126 * B_FALSE to exit
4129 static boolean_t
4130 add_packages(char **a_pkgList,
4131 char *a_idsName, int a_repeat, char *a_altBinDir, char *a_device,
4132 boolean_t a_noZones)
4134 zoneList_t zlst;
4135 boolean_t b;
4137 /* entry assertions */
4139 assert(a_pkgList != (char **)NULL);
4141 echoDebug(DBG_ADDPACKAGES_ENTRY);
4142 echoDebug(DBG_ADDPACKAGES_ARGS, npkgs, PSTR(a_idsName),
4143 a_repeat, PSTR(a_altBinDir), PSTR(a_device));
4146 * if running in the global zone AND one or more non-global
4147 * zones exist, add packages in a 'zones aware' manner, else
4148 * add packages in the standard 'non-zones aware' manner.
4151 if ((a_noZones == B_FALSE) && (z_running_in_global_zone() == B_FALSE)) {
4152 /* in non-global zone */
4154 echoDebug(DBG_IN_LZ);
4156 b = z_lock_this_zone(ZLOCKS_PKG_ADMIN);
4157 if (b != B_TRUE) {
4158 progerr(ERR_CANNOT_LOCK_THIS_ZONE);
4159 /* set fatal error return condition */
4160 ckreturn(1);
4161 return (B_FALSE);
4164 b = add_packages_in_nonglobal_zone(a_pkgList, a_idsName,
4165 a_repeat, a_altBinDir, a_device);
4167 (void) z_unlock_this_zone(ZLOCKS_ALL);
4169 return (B_FALSE);
4172 /* running in the global zone */
4174 b = z_non_global_zones_exist();
4175 if ((a_noZones == B_FALSE) && (b == B_TRUE) &&
4176 (globalZoneOnly == B_FALSE)) {
4178 echoDebug(DBG_IN_GZ_WITH_LZ);
4180 /* error if -V specified - what to use in non-global zone? */
4182 if (vfstab_file) {
4183 progerr(ERR_V_USED_WITH_GZS);
4184 quit(1);
4187 /* get a list of all non-global zones */
4188 zlst = z_get_nonglobal_zone_list();
4189 if (zlst == (zoneList_t)NULL) {
4190 progerr(ERR_CANNOT_GET_ZONE_LIST);
4191 quit(1);
4194 /* need to lock all of the zones */
4196 quitSetZonelist(zlst);
4197 b = z_lock_zones(zlst, ZLOCKS_PKG_ADMIN);
4198 if (b == B_FALSE) {
4199 z_free_zone_list(zlst);
4200 progerr(ERR_CANNOT_LOCK_ZONES);
4201 /* set fatal error return condition */
4202 ckreturn(1);
4203 return (B_FALSE);
4206 /* add packages to all zones */
4208 b = add_packages_in_global_with_zones(a_pkgList,
4209 a_idsName, a_repeat, a_altBinDir, a_device, zlst);
4211 /* unlock all zones */
4213 (void) z_unlock_zones(zlst, ZLOCKS_ALL);
4214 quitSetZonelist((zoneList_t)NULL);
4216 /* free list of all non-global zones */
4218 z_free_zone_list(zlst);
4220 return (B_FALSE);
4223 /* in global zone no non-global zones */
4225 echoDebug(DBG_IN_GZ_NO_LZ);
4227 b = z_lock_this_zone(ZLOCKS_PKG_ADMIN);
4228 if (b != B_TRUE) {
4229 progerr(ERR_CANNOT_LOCK_THIS_ZONE);
4230 /* set fatal error return condition */
4231 ckreturn(1);
4232 return (B_FALSE);
4235 b = add_packages_in_global_no_zones(a_pkgList, a_idsName,
4236 a_repeat, a_altBinDir, a_device);
4238 (void) z_unlock_this_zone(ZLOCKS_ALL);
4240 return (B_FALSE);