1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28
29
30 /*
31 * Program: pkgadd / pkgask
32 *
33 * Function: public command and private utility functions that
34 * implement the package add and package ask operations.
35 *
36 */
37
38 /*
39 * System includes
40 */
41
42 #include <stdio.h>
43 #include <limits.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46 #include <string.h>
47 #include <fcntl.h>
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include <signal.h>
51 #include <errno.h>
52 #include <pkgdev.h>
53 #include <pkginfo.h>
54 #include <pkglocs.h>
55 #include <locale.h>
56 #include <libintl.h>
57 #include <pkgtrans.h>
58 #include <boot_http.h>
59 #include <assert.h>
60
61 /*
62 * consolidation pkg command library includes
63 */
64 #include <pkglib.h>
65 #include <pkgerr.h>
66 #include <pkgweb.h>
67
68 #include <instzones_api.h>
69
70 /*
71 * local pkg command library includes
72 */
73 #include <install.h>
74 #include <libinst.h>
75 #include <libadm.h>
76 #include <messages.h>
77
78
79 /*
80 * pkgadd local includes
81 */
82
83 #include "quit.h"
84
85 /*
86 * imported global variables/functions
87 */
88
89 /* check.c */
90 extern int preinstall_verify(char **a_pkgList, zoneList_t a_zlst,
91 char *a_zoneTempDir);
92
93 /*
94 * ckquit is a global that controls 'ckyorn' (defined in libadm)
95 * If ckquit is non-zero, then "quit" is allowed as an answer when
96 * ckyorn is called. If is it zero, then "quit" is not an allowed answer.
97 */
98 extern int ckquit;
99
100 /*
101 * exported global variables
102 */
103
104 /* these globals are set by ckreturn and used by quit.c */
105
106 int admnflag = 0; /* != 0 if any pkg op admin setting failure (4) */
107 int doreboot = 0; /* != 0 if reboot required after installation */
108 int failflag = 0; /* != 0 if fatal error has occurred (1) */
109 int intrflag = 0; /* != 0 if user selected quit (3) */
110 int ireboot = 0; /* != 0 if immediate reboot required */
111 int nullflag = 0; /* != 0 if admin interaction required (5) */
112 int warnflag = 0; /* != 0 if non-fatal error has occurred (2) */
113
114 /* imported by quit.c */
115 int npkgs = 0; /* the number of packages yet to be installed */
116
117 /* imported by various (many) */
118 char *respfile = NULL; /* response pathname (or NULL) */
119 char *tmpdir = NULL; /* location to place temporary files */
120
121 struct admin adm; /* holds info about installation admin */
122 struct pkgdev pkgdev; /* holds info about the installation device */
123
124 /*
125 * internal global variables
126 */
127
128 static char *admnfile = NULL; /* file to use for installation admin */
129 static char *ids_name = NULL; /* name of data stream device */
130 static char *pkgcontsrc = NULL; /* continuation file (-c option) */
131 static char *pkgdrtarg = NULL; /* dry run file (-D option) */
132 static char *pkginst = NULL; /* current pkg/src instance 2 process */
133 static char *respdir = NULL; /* respfile is a directory spec */
134 static char *rw_block_size = NULL;
135 static char *vfstab_file = NULL;
136 static int askflag = 0; /* non-zero if invoked as "pkgask" */
137 static int disableAttributes = 0; /* Disabling attribute checking */
138 static int disableChecksum = 0; /* Disable checksumming */
139 static int disableSaveSpool = 0; /* Disable partial spool dir create */
140 static int init_install = 0; /* inform scripts initial install */
141 static int no_map_client = 0; /* do not map from vfstab file */
142 static int nointeract = 0; /* non-zero - no user interaction */
143 static int pkgverbose = 0; /* non-zero if verbose mode selected */
144 static int saveSpoolInstall = 0; /* installing from save spool dir */
145 static int suppressCopyright = 0; /* suppress copyright notices */
146
147 /* set by ckreturn() */
148
149 static int interrupted = 0; /* last pkg op was quit (1,2,3,4,5) */
150 static int needconsult = 0; /* essential ask admin now (1,2,3,5) */
151
152 /* Set by -O nozones: do not process any zones */
153
154 static boolean_t noZones = B_FALSE;
155
156 /* Set by -O zonelist=<names...>: process only named zones */
157
158 static boolean_t usedZoneList = B_FALSE;
159
160 /* Set by -O debug: debug output is enabled? */
161
162 static boolean_t debugFlag = B_FALSE;
163
164 /* Set by the -G option: install packages in global zone only */
165
166 static boolean_t globalZoneOnly = B_FALSE;
167
168 /*
169 * Assume the package is ABI and POSIX compliant as regards user
170 * interactiion during procedure scripts.
171 */
172
173 static int old_pkg = 0;
174
175 /* Assume pkg should be installed according to the ABI */
176
177 static int old_symlinks = 0;
178
179 /*
180 * Default name length will be 32 chars - if this is set,
181 * disable the 32 char name limit extension
182 */
183
184 static int ABI_namelength = 0;
185
186 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
187 #define TEXT_DOMAIN "SYS_TEST"
188 #endif
189
190 /* printable string - if string is null results in ??? */
191
192 #define PSTR(STR) (((STR) == (char *)NULL) ? "???" : (STR))
193
194 #define MAX_FDS 20
195
196 /*
197 * forward declarations
198 */
199
200 static int boot_and_pkginstall_check_in_zones(zoneList_t a_zlst,
201 char *a_idsName, char *a_altBinDir,
202 char *a_zoneAdminFile, char *a_zoneTempDir);
203 static int boot_and_install_in_zones(zoneList_t a_zlst,
204 char *a_idsName, char *a_altBinDir,
205 char *a_zoneAdminFile, char *a_zoneTempDir);
206 static void pkginstall_check_in_one_zone(char *a_zoneName,
207 char *a_idsName, char *a_zoneAdminFile,
208 char *a_zoneTempDir, char *a_altBinDir,
209 char *a_scratchName, zone_state_t a_zoneState,
210 boolean_t a_tmpzn);
211 static void ckreturn(int retcode);
212 static void create_zone_adminfile(char **r_zoneAdminFile,
213 char *a_zoneTempDir, char *a_admnfile);
214 static void create_zone_tempdir(char **r_zoneTempDir,
215 char *a_tmpdir);
216 static void install_in_one_zone(char *a_zoneName, char *a_idsName,
217 char *a_zoneAdminFile, char *a_zoneTempDir,
218 char *a_altBinDir, zone_state_t a_zoneState,
219 boolean_t a_tmpzn);
220 static int pkginstall_check_in_zones(zoneList_t a_zlst,
221 char *a_idsName, char *a_altBinDir,
222 char *a_zoneAdminFile, char *a_zoneTempDir);
223 static int install_in_zones(zoneList_t a_zlst, char *a_idsName,
224 char *a_altBinDir, char *a_zoneAdminFile,
225 char *a_zoneTempDir);
226 static int pkgInstall(char *ir, char *a_idsName, char *a_pkgDir,
227 char *a_altBinDir);
228 static int pkgZoneCheckInstall(char *a_zoneName,
229 zone_state_t a_zoneState,
230 char *a_idsName, char *a_altBinDir,
231 char *a_adminFile, char *a_stdoutPath,
232 boolean_t a_tmpzn);
233 static int pkgZoneInstall(char *a_zoneName,
234 zone_state_t a_zoneState,
235 char *a_idsName, char *a_altBinDir,
236 char *a_adminFile, boolean_t a_tmpzn);
237 static void resetreturn();
238 static void usage(void);
239 static boolean_t add_packages(char **a_pkgList, char *a_uri,
240 char *a_idsName, int a_repeat,
241 char *a_altBinDir, char *a_device,
242 boolean_t a_noZones);
243 static boolean_t add_packages_in_global_no_zones(char **a_pkgList,
244 char *a_uri, char *a_idsName, int a_repeat,
245 char *a_altBinDir, char *a_device);
246 static boolean_t add_packages_in_global_with_zones(char **a_pkgList,
247 char *a_uri, char *a_idsName, int a_repeat,
248 char *a_altBinDir, char *a_device,
249 zoneList_t a_zlst);
250 static boolean_t add_packages_in_nonglobal_zone(char **a_pkgList,
251 char *a_uri, char *a_idsName, int a_repeat,
252 char *a_altBinDir, char *a_device);
253 static boolean_t check_applicability(char *a_packageDir,
254 char *a_pkgInst, char *a_rootPath,
255 CAF_T a_flags);
256 static boolean_t get_package_list(char ***r_pkgList, char **a_argv,
257 char *a_categories, char **a_categoryList,
258 int a_ignoreSignatures, PKG_ERR *a_err,
259 ushort_t a_httpProxyPort, char *a_httpProxyName,
260 keystore_handle_t a_keystore,
261 char *a_keystoreFile, char *a_idsName,
262 int *r_repeat);
263 static boolean_t continue_installation(void);
264 static boolean_t unpack_and_check_packages(char **a_pkgList,
265 char *a_idsName, char *a_packageDir);
266 /*
267 * *****************************************************************************
268 * global external (public) functions
269 * *****************************************************************************
270 */
271
272 /*
273 * Name: main
274 * Description: main entry point for pkgadd/pkgask
275 * Returns: int
276 * 0 Successful completion
277 * 1 Fatal error.
278 * 2 Warning.
279 * 3 Interruption.
280 * 4 Administration.
281 * 5 Administration. Interaction is required. Do not use pkgadd -n.
282 * In addition, one of the following values may be added to the previous value
283 * as appropriate:
284 * 10 Reboot after installation of all packages.
285 * 20 Reboot after installation of this package.
286 * For example, "14" would indicate both "administration" and "reboot after
287 * installation of all packages".
288 */
289
290 int
main(int argc,char ** argv)291 main(int argc, char **argv)
292 {
293 PKG_ERR *err = NULL;
294 WebScheme scheme = none;
295 char **category = NULL;
296 char *abiPtr;
297 char *altBinDir = (char *)NULL;
298 char *catg_arg = NULL;
299 char *device = NULL; /* dev pkg stored on */
300 char *dwnld_dir = NULL;
301 char *keystore_file = NULL;
302 char *p;
303 char *q;
304 char *prog;
305 char *prog_full_name = NULL;
306 char *proxy = NULL;
307 char *spoolDir = NULL; /* specified with -s */
308 char *uri = NULL;
309 char Rpath[PATH_MAX+1] = {'\0'};
310 int c;
311 int ignore_sig = 0;
312 int n;
313 int repeat;
314 int retries = NET_RETRIES_DEFAULT;
315 int timeout = NET_TIMEOUT_DEFAULT;
316 keystore_handle_t keystore = NULL;
317 struct sigaction nact;
318 struct sigaction oact;
319 ushort_t proxy_port = 0;
320
321 /* initialize locale environment */
322
323 (void) setlocale(LC_ALL, "");
324 (void) textdomain(TEXT_DOMAIN);
325
326 /* initialize program name */
327
328 prog_full_name = argv[0];
329 prog = set_prog_name(argv[0]);
330
331 /* tell spmi zones interface how to access package output functions */
332
333 z_set_output_functions(echo, echoDebug, progerr);
334
335 askflag = (strcmp(prog, "pkgask") == 0);
336
337 /* set sane umask */
338
339 (void) umask(0022);
340
341 /* tell quit which ckreturn function to call */
342
343 quitSetCkreturnFunc(&ckreturn);
344
345 /* initially no source "device" */
346
347 device = NULL;
348
349 /* reset npkgs (used as pkg remaining count in quit.c) */
350
351 npkgs = 0;
352
353 /* set default password prompt for encrypted packages */
354
355 set_passphrase_prompt(MSG_PASSPROMPT);
356
357 /* initialize security operations structures and libraries */
358
359 sec_init();
360
361 if (z_running_in_global_zone() && !enable_local_fs()) {
362 progerr(ERR_CANNOT_ENABLE_LOCAL_FS);
363 }
364
365 pkgserversetmode(DEFAULTMODE);
366
367 /*
368 * ********************************************************************
369 * parse command line options
370 * ********************************************************************
371 */
372
373 while ((c = getopt(argc, argv,
374 "?Aa:b:B:Cc:D:d:GhIik:MnO:P:R:r:Ss:tV:vx:Y:zZ")) != EOF) {
375 switch (c) {
376
377 /*
378 * Not a public interface: This disables attribute checking.
379 * It speeds up installation a little bit.
380 */
381 case 'A':
382 disableAttributes++;
383 break;
384
385 /*
386 * Public interface: Define an installation administration
387 * file, admin, to be used in place of the default
388 * administration file. The token none overrides the use
389 * of any admin file, and thus forces interaction with the
390 * user. Unless a full path name is given, pkgadd first
391 * looks in the current working directory for the
392 * administration file. If the specified administration
393 * file is not in the current working directory, pkgadd
394 * looks in the /var/sadm/install/admin directory for the
395 * administration file.
396 */
397 case 'a':
398 admnfile = flex_device(optarg, 0);
399 break;
400
401 /*
402 * Not a public interface: control block size given to
403 * pkginstall - block size used in read()/write() loop;
404 * default is st_blksize from stat() of source file.
405 */
406 case 'B':
407 if (optarg[0] == '-') {
408 usage();
409 quit(1);
410 }
411 rw_block_size = optarg;
412 break;
413
414 /*
415 * Not a public interface: location where package executables
416 * can be found - default is /usr/sadm/install/bin.
417 */
418 case 'b':
419 if (optarg[0] == '-') {
420 usage();
421 quit(1);
422 }
423 if (!path_valid(optarg)) {
424 progerr(ERR_PATH, optarg);
425 quit(1);
426 }
427 if (isdir(optarg) != 0) {
428 p = strerror(errno);
429 progerr(ERR_CANNOT_USE_DIR, optarg, p);
430 quit(1);
431 }
432 altBinDir = optarg;
433 break;
434
435 /*
436 * Not a public interface: This disables checksum tests on
437 * the source files. It speeds up installation a little bit.
438 */
439 case 'C':
440 disableChecksum++;
441 break;
442
443 /*
444 * Not a public interface: This allows designation of a
445 * continuation file. It is the same format as a dryrun file
446 * but it is used to take up where the dryrun left off.
447 */
448 case 'c':
449 pkgcontsrc = flex_device(optarg, 0);
450 break;
451
452 /*
453 * Not a public interface: This allows designation of a
454 * dryrun file. This pkgadd will create dryrun files
455 * in the directory provided.
456 */
457 case 'D':
458 if (optarg[0] == '-') {
459 usage();
460 quit(1);
461 }
462 pkgdrtarg = flex_device(optarg, 0);
463 break;
464
465 /*
466 * Public interface: Install or copy a package from
467 * device. device can be a full path name to a directory
468 * or the identifiers for tape, floppy disk, or removable
469 * disk - for example, /var/tmp or /floppy/floppy_name.
470 * It can also be a device alias - for example,
471 * /floppy/floppy0, or a datastream created by pkgtrans.
472 */
473 case 'd':
474 if (optarg[0] == '-') {
475 usage();
476 quit(1);
477 }
478 if (!path_valid(optarg)) {
479 progerr(ERR_PATH, optarg);
480 quit(1);
481 /* NOTREACHED */
482 }
483
484 if (strncmp(optarg, HTTP, 7) == 0) {
485 scheme = web_http;
486 } else if (strncmp(optarg, HTTPS, 8) == 0) {
487 scheme = web_https;
488 }
489
490 if (scheme == web_https || scheme == web_http) {
491 uri = optarg;
492 if ((device = malloc(PATH_MAX)) == NULL) {
493 progerr(ERR_MEM);
494 exit(1);
495 }
496 (void) memset(device, '\0', PATH_MAX);
497 } else {
498 device = flex_device(optarg, 1);
499 }
500 break;
501
502 /*
503 * Public interface: install package in global zone only.
504 */
505 case 'G':
506 globalZoneOnly = B_TRUE;
507 break;
508
509 /*
510 * Not a public interface: Enable hollow package support. When
511 * specified, for any package that has SUNW_PKG_HOLLOW=true:
512 * Do not calculate and verify package size against target.
513 * Do not run any package procedure or class action scripts.
514 * Do not create any target directories.
515 * Do not perform any script locking.
516 * Do not install any components of any package.
517 * Do not output any status or database update messages.
518 */
519 case 'h':
520 set_depend_pkginfo_DB(B_TRUE);
521 break;
522
523 /*
524 * Not a public interface: Informs scripts that this is
525 * an initial install by setting the environment parameter
526 * PKG_INIT_INSTALL=TRUE for all scripts. They may use it as
527 * they see fit, safe in the knowledge that the target
528 * filesystem is tabula rasa.
529 */
530 case 'I':
531 init_install++;
532 break;
533
534 /*
535 * Not a public interface: ignore signatures.
536 */
537 case 'i':
538 ignore_sig++;
539 break;
540
541 /*
542 * Public interface: Use keystore as the location from which to
543 * get trusted certificate authority certificates when verifying
544 * digital signatures found in packages. If no keystore is
545 * specified, then the default keystore locations are searched
546 * for valid trusted certificates.
547 */
548 case 'k':
549 if (!path_valid(optarg)) {
550 progerr(ERR_PATH, optarg);
551 quit(1);
552 /* NOTREACHED */
553 }
554 keystore_file = optarg;
555 break;
556
557 /*
558 * Public interface: Instruct pkgadd not to use the
559 * $root_path/etc/vfstab file for determining the client's
560 * mount points. This option assumes the mount points are
561 * correct on the server and it behaves consistently with
562 * Solaris 2.5 and earlier releases.
563 */
564 case 'M':
565 no_map_client = 1;
566 break;
567
568 /*
569 * Not a public interface: the -O option allows the behavior
570 * of the package tools to be modified. Recognized options:
571 * -> debug
572 * ---> enable debugging output
573 * -> addzonename
574 * ---> add zone name to appropriate messages
575 * -> nozones
576 * ---> act as though in global zone with no non-global zones
577 * -> enable-hollow-package-support
578 * ---> Enable hollow package support. When specified, for any
579 * ---> package that has SUNW_PKG_HOLLOW=true:
580 * ---> Do not calculate and verify package size against target
581 * ---> Do not run any package procedure or class action scripts
582 * ---> Do not create any target directories
583 * ---> Do not perform any script locking
584 * ---> Do not install any components of any package
585 * ---> Do not output any status or database update messages
586 * -> zonelist="<names...>"
587 * ---> add package to space/colon separated list of zones only
588 */
589
590 case 'O':
591 for (p = strtok(optarg, ","); p != (char *)NULL;
592 p = strtok(NULL, ",")) {
593
594 if (strcmp(p, "debug") == 0) {
595 /* set debug flag/enable debug output */
596 debugFlag = B_TRUE;
597 (void) echoDebugSetFlag(debugFlag);
598
599 /* debug info on arguments to pkgadd */
600 for (n = 0; n < argc && argv[n]; n++) {
601 echoDebug(DBG_ARG, n, argv[n]);
602 }
603
604 continue;
605 }
606
607 if (strcmp(p,
608 "enable-hollow-package-support") == 0) {
609 set_depend_pkginfo_DB(B_TRUE);
610 continue;
611 }
612
613 if (strcmp(p, "addzonename") == 0) {
614 quitSetZoneName(z_get_zonename());
615 continue;
616 }
617
618 if (strcmp(p, "nozones") == 0) {
619 noZones = B_TRUE;
620 continue;
621 }
622
623 if (strncmp(p, "zonelist=", 9) == 0) {
624 /*
625 * If colons used as separators,
626 * convert to spaces.
627 */
628 q = p + 9;
629 while (*q != '\0') {
630 if (*q == ':') {
631 *q = ' ';
632 }
633 q++;
634 }
635
636 if (z_set_zone_spec(p + 9) == -1)
637 quit(1);
638 usedZoneList = B_TRUE;
639 continue;
640 }
641
642 progerr(ERR_INVALID_O_OPTION, p);
643 continue;
644 }
645 break;
646
647 /*
648 * Public interface: installation occurs in
649 * non-interactive mode. Suppress output of the list of
650 * installed files. The default mode is interactive.
651 */
652 case 'n':
653 nointeract++;
654 (void) echoSetFlag(B_FALSE);
655 break;
656
657 /*
658 * Public interface: Password to use to decrypt keystore
659 * specified with -k, if required. See PASS PHRASE
660 * ARGUMENTS for more information about the format of this
661 * option's argument.
662 */
663 case 'P':
664 if (optarg[0] == '-') {
665 usage();
666 quit(1);
667 }
668 set_passphrase_passarg(optarg);
669 if (ci_strneq(optarg, "pass:", 5)) {
670 /*
671 * passwords on the command line are highly
672 * insecure. complain.
673 */
674 logerr(PASSWD_CMDLINE, "pass:<pass>");
675 }
676 break;
677
678 /*
679 * Public interface: Define the full path name of a
680 * directory to use as the root_path. All files,
681 * including package system information files, are
682 * relocated to a directory tree starting in the specified
683 * root_path. The root_path may be specified when
684 * installing to a client from a server (for example,
685 * /export/root/client1).
686 */
687 case 'R':
688 if (optarg[0] == '-') {
689 usage();
690 quit(1);
691 }
692 /* determine the real path specified */
693
694 n = resolvepath(optarg, Rpath, sizeof (Rpath)-1);
695
696 /* use supplied path if not resolvable */
697
698 if (n == -1) {
699 (void) strlcpy(Rpath, optarg, sizeof (Rpath));
700 } else {
701 /* null terminate string */
702 Rpath[n] = '\0';
703 }
704
705 /* set the alternative root path */
706
707 if (!set_inst_root(Rpath)) {
708 progerr(ERR_ROOT_CMD);
709 exit(1);
710 }
711 break;
712
713 /*
714 * Public interface: Identify a file or directory which
715 * contains output from a previous pkgask(1M)
716 * session. This file supplies the interaction responses
717 * that would be requested by the package in interactive
718 * mode. response must be a full pathname.
719 */
720 case 'r':
721 if (optarg[0] == '-') {
722 usage();
723 quit(1);
724 }
725 respfile = flex_device(optarg, 2);
726 if (isdir(respfile) == 0)
727 respdir = respfile;
728 break;
729
730 /*
731 * Not a public interface: suppress copyright notice being
732 * output during installation.
733 */
734 case 'S':
735 suppressCopyright++;
736 break;
737
738 /*
739 * Public interface: Write the package into the directory
740 * spool instead of installing it. The default directory
741 * for spooled packages is /var/sadm/pkg.
742 */
743 case 's':
744 spoolDir = flex_device(optarg, 1);
745 break;
746
747 /*
748 * Not a public interface: disable save spool area creation;
749 * suppress the creation and population of the package save
750 * spool area (var/sadm/pkg/PKG/save/pspool/PKG).
751 */
752 case 't':
753 disableSaveSpool++;
754 break;
755
756 /*
757 * Public interface: Specify an alternative fs_file to map
758 * the client's file systems. For example, used in
759 * situations where the $root_path/etc/vfstab file is
760 * non-existent or unreliable. Informs the pkginstall
761 * portion to mount up a client filesystem based upon the
762 * supplied vfstab-like file of stable format.
763 */
764 case 'V':
765 vfstab_file = flex_device(optarg, 2);
766 no_map_client = 0;
767 break;
768
769 /*
770 * Public interface: Trace all of the scripts that get
771 * executed by pkgadd, located in the pkginst/install
772 * directory. This option is used for debugging the
773 * procedural and non-procedural scripts
774 */
775 case 'v':
776 pkgverbose++;
777 break;
778
779 /*
780 * Public interface: Specify a HTTP[S] proxy to use when
781 * downloading packages The format of proxy is host:port,
782 * where host is the hostname of the HTTP[S] proxy, and
783 * port is the port number associated with the proxy. This
784 * switch overrides all other methods of specifying a
785 * proxy. See ENVIRONMENT VARIABLES for more information
786 * on alternate methods of specifying a default proxy.
787 */
788 case 'x':
789 if (!path_valid(optarg)) {
790 progerr(ERR_PATH, optarg);
791 quit(1);
792 /* NOTREACHED */
793 }
794 proxy = optarg;
795 break;
796
797 /*
798 * Public interface: Install packages based on the value
799 * of the CATEGORY parameter stored in the package's
800 * pkginfo(4) file. All packages on the source medium
801 * whose CATEGORY matches one of the specified categories
802 * will be selected for installation or spooling. Install
803 * packages that contain the same CATEGORY as the one
804 * provided on the command line.
805 */
806 case 'Y':
807 if (optarg[0] == '-') {
808 usage();
809 quit(1);
810 }
811 catg_arg = strdup(optarg);
812
813 if ((category = get_categories(catg_arg)) == NULL) {
814 progerr(ERR_CAT_INV, catg_arg);
815 exit(1);
816 } else if (is_not_valid_length(category)) {
817 progerr(ERR_CAT_LNGTH);
818 exit(1);
819 }
820 break;
821
822 /*
823 * Not a public interface: perform fresh install from
824 * package save spool area. When set, the package contents
825 * are installed from the package spool save area instead
826 * of from the package root area, so that the original
827 * source packages are not required to install the
828 * package. If the -h option is also specified and the
829 * package is hollow, then this option is ignored. When -z
830 * is specified:
831 * - Editable files are installed from the package instance
832 * save area.
833 * - Volatile files are installed from the package instance
834 * save area.
835 * - Executable and data files are installed from the final
836 * installed location as specified in the pkgmap file.
837 * - Installation scripts are run from the package spool
838 * save area.
839 */
840 case 'z':
841 saveSpoolInstall++;
842 break;
843
844 /*
845 * unrecognized option
846 */
847
848 default:
849 usage();
850 return (1);
851 }
852 }
853
854 /*
855 * ********************************************************************
856 * validate command line options
857 * ********************************************************************
858 */
859
860 /* set "debug echo" flag according to setting of "-O debug" option */
861
862 (void) echoDebugSetFlag(debugFlag);
863
864 /* output entry debugging information */
865
866 if (z_running_in_global_zone()) {
867 echoDebug(DBG_ENTRY_IN_GZ, prog_full_name);
868 } else {
869 echoDebug(DBG_ENTRY_IN_LZ, prog_full_name, getzoneid(),
870 z_get_zonename());
871 }
872
873 /*
874 * Later, it may be decided to pursue this ability to continue to an
875 * actual installation based only on the dryrun data. At this time,
876 * it is too risky.
877 */
878
879 if (pkgcontsrc && !pkgdrtarg) {
880 progerr(ERR_NO_LIVE_MODE);
881 usage();
882 return (1);
883 }
884
885 /* ignore -G option if not used in the global zone */
886
887 if (!z_running_in_global_zone()) {
888 globalZoneOnly = B_FALSE;
889 }
890
891 /* if zonelist used, must be in global zone */
892
893 if (usedZoneList && !z_running_in_global_zone()) {
894 progerr(ERR_Z_USED_IN_NONGLOBAL_ZONE);
895 return (1);
896 }
897
898 /* -G and zonelist cannot be used together */
899
900 if (globalZoneOnly && usedZoneList) {
901 progerr(ERR_GZ_USED_TOGETHER);
902 usage();
903 return (1);
904 }
905
906 /* -s cannot be used with either -G or zonelist */
907
908 if (spoolDir != NULL) {
909 if (globalZoneOnly) {
910 progerr(ERR_SPOOLDIR_USED_WITH_G);
911 usage();
912 return (1);
913 }
914 if (usedZoneList) {
915 progerr(ERR_SPOOLDIR_USED_WITH_Z);
916 usage();
917 return (1);
918 }
919 if (strcmp(spoolDir, "/var/sadm/pkg") == 0) {
920 progerr(ERR_SPOOLDIR_CANNOT_BE_SYS, "/var/sadm/pkg");
921 usage();
922 return (1);
923 }
924 }
925
926 /* pkgask does not support the same options as pkgadd */
927
928 if (askflag && proxy) {
929 progerr(ERR_PKGASK_AND_PROXY);
930 usage();
931 return (1);
932 }
933
934 if (askflag && uri) {
935 progerr(ERR_PKGASK_AND_URI);
936 usage();
937 return (1);
938 }
939
940 if (askflag && keystore_file) {
941 progerr(ERR_PKGASK_AND_KEYSTORE_FILE);
942 usage();
943 return (1);
944 }
945
946 if (askflag && ignore_sig) {
947 progerr(ERR_PKGASK_AND_IGNORE_SIG);
948 usage();
949 return (1);
950 }
951
952 if (askflag && spoolDir) {
953 progerr(ERR_PKGASK_AND_SPOOLDIR);
954 usage();
955 return (1);
956 }
957
958 if (askflag && nointeract) {
959 progerr(ERR_PKGASK_AND_NOINTERACT);
960 usage();
961 return (1);
962 }
963
964 /* cannot use response file and web address together */
965
966 if (respfile && uri) {
967 progerr(ERR_RESPFILE_AND_URI);
968 usage();
969 return (1);
970 }
971
972 /* cannot use response file/not-interactive and spool-to directory */
973
974 if (spoolDir && nointeract) {
975 progerr(ERR_SPOOLDIR_AND_NOINTERACT);
976 usage();
977 return (1);
978 }
979
980 if (spoolDir && respfile) {
981 progerr(ERR_SPOOLDIR_AND_RESPFILE);
982 usage();
983 return (1);
984 }
985
986 if (usedZoneList) {
987 /* Verify supplied zone list valid for the target */
988 if (z_verify_zone_spec() == -1)
989 return (1);
990
991 /* -z zonelist=global is logically the same as -G */
992 if (z_global_only() && z_running_in_global_zone())
993 globalZoneOnly = B_TRUE;
994 }
995
996 /*
997 * hook SIGINT and SIGHUP interrupts into quit.c's trap handler
998 */
999
1000 /* hold SIGINT/SIGHUP interrupts */
1001
1002 (void) sighold(SIGHUP);
1003 (void) sighold(SIGINT);
1004
1005 /* connect quit.c:trap() to SIGINT */
1006
1007 nact.sa_handler = quitGetTrapHandler();
1008 nact.sa_flags = SA_RESTART;
1009 (void) sigemptyset(&nact.sa_mask);
1010
1011 (void) sigaction(SIGINT, &nact, &oact);
1012
1013 /* connect quit.c:trap() to SIGHUP */
1014
1015 nact.sa_handler = quitGetTrapHandler();
1016 nact.sa_flags = SA_RESTART;
1017 (void) sigemptyset(&nact.sa_mask);
1018
1019 (void) sigaction(SIGHUP, &nact, &oact);
1020
1021 /* release hold on signals */
1022
1023 (void) sigrelse(SIGHUP);
1024 (void) sigrelse(SIGINT);
1025
1026 /*
1027 * This function is in the libadm library; it sets:
1028 * -> get_PKGLOC() = <install_root>/var/sadm/pkg
1029 * -> get_PKGADM() = <install_root>/var/sadm/install
1030 * -> pkgdir = <install_root>/var/sadm/pkg
1031 * -> pkg_install_root = <install_root>
1032 * This controls operations of libadm functions such as:
1033 * -> pkginfofind, pkginfopen, fpkgparam, pkgparam, get_PKGLOC,
1034 * -> get_PKGADM, get_install_root
1035 */
1036
1037 set_PKGpaths(get_inst_root());
1038 echoDebug(DBG_PKGADD_PKGPATHS,
1039 get_PKGLOC() ? get_PKGLOC() : "",
1040 get_PKGADM() ? get_PKGADM() : "");
1041
1042 /*
1043 * This function is in the libinst library; it reads the specified
1044 * admin(4) file and, using fpkgparam(), sets the global "adm" structure
1045 * values to match what is in the specified admin file.
1046 */
1047
1048 echoDebug(DBG_PKGADD_ADMINFILE, admnfile ? admnfile : "");
1049 setadminFile(admnfile);
1050
1051 /*
1052 * if running in the global zone, and non-global zones exist, then
1053 * enable hollow package support so that any packages that are marked
1054 * SUNW_PKG_HOLLOW=true will be correctly installed in non-global zones
1055 * when added directly in the global zone by the global zone admin.
1056 */
1057
1058 if (is_depend_pkginfo_DB()) {
1059 echoDebug(DBG_PKGADD_HOLLOW_ENABLED);
1060 } else if ((z_running_in_global_zone() == B_TRUE) &&
1061 (z_non_global_zones_exist() == B_TRUE)) {
1062 echoDebug(DBG_PKGADD_ENABLING_HOLLOW);
1063 set_depend_pkginfo_DB(B_TRUE);
1064 }
1065
1066 /* if no device and no url, get and validate default device */
1067
1068 if ((device == NULL) && (uri == NULL)) {
1069 device = devattr("spool", "pathname");
1070 if (device == NULL) {
1071 progerr(ERR_NODEVICE);
1072 quit(1);
1073 /* NOTREACHED */
1074 }
1075 }
1076
1077 /* must be root if not directing results to spool directory */
1078
1079 if ((getuid() != 0) && (spoolDir == NULL)) {
1080 progerr(ERR_NOT_ROOT, prog);
1081 exit(1);
1082 }
1083
1084 /*
1085 * process response file argument
1086 */
1087
1088 if (respfile) {
1089 echoDebug(DBG_PKGADD_RESPFILE,
1090 respfile, respdir ? respdir : "");
1091
1092 if (respfile[0] != '/') {
1093 progerr(ERR_RSP_FILE_NOTFULLPATH, respfile);
1094 quit(1);
1095 /* NOTREACHED */
1096 }
1097 if (respdir == NULL) {
1098 if (askflag) {
1099 if (access(respfile, F_OK) == 0) {
1100 progerr(ERR_NORESP, respfile);
1101 quit(1);
1102 /* NOTREACHED */
1103 }
1104 } else if (access(respfile, F_OK) != 0) {
1105 progerr(ERR_ACCRESP, respfile);
1106 quit(1);
1107 /* NOTREACHED */
1108 }
1109 }
1110 } else if (askflag) {
1111 progerr(ERR_RSP_FILE_NOT_GIVEN);
1112 usage();
1113 quit(1);
1114 /* NOTREACHED */
1115 }
1116
1117 /* establish temporary directory to use */
1118
1119 if ((tmpdir = getenv("TMPDIR")) == NULL) {
1120 /* use default - no override specified */
1121 tmpdir = P_tmpdir;
1122 }
1123
1124 echoDebug(DBG_PKGADD_TMPDIR, tmpdir);
1125
1126 /*
1127 * setup and prepare secure package operations
1128 */
1129
1130 /* initialize error object used by security functions */
1131
1132 err = pkgerr_new();
1133
1134 /* validate keystore file */
1135
1136 if (!check_keystore_admin(&keystore_file)) {
1137 progerr(ERR_ADM_KEYSTORE);
1138 quit(1);
1139 /* NOTREACHED */
1140 }
1141
1142 /* if uri provided, establish session */
1143
1144 if (uri != NULL) {
1145 boolean_t b;
1146 int len;
1147 char *bname = (char *)NULL;
1148
1149 set_web_install();
1150
1151 if (!get_proxy_port(err, &proxy, &proxy_port)) {
1152 pkgerr(err);
1153 quit(1);
1154 /* NOTREACHED */
1155 }
1156
1157 if (proxy == NULL) {
1158 if (!get_proxy_port_admin(&proxy, &proxy_port)) {
1159 progerr(ERR_ADM_PROXY);
1160 quit(1);
1161 /* NOTREACHED */
1162 }
1163 }
1164
1165 if ((retries = web_ck_retries()) == 0) {
1166 pkgerr(err);
1167 quit(1);
1168 /* NOTREACHED */
1169 }
1170
1171 if ((timeout = web_ck_timeout()) == 0) {
1172 pkgerr(err);
1173 quit(1);
1174 /* NOTREACHED */
1175 }
1176
1177 /* create temporary directory */
1178
1179 b = setup_temporary_directory(&dwnld_dir, tmpdir, "dwnld");
1180 if (b != B_TRUE) {
1181 progerr(ERR_DWNLDTEMPDIR, tmpdir, strerror(errno));
1182 quit(1);
1183 /* NOTREACHED */
1184 }
1185 canonize_slashes(dwnld_dir);
1186
1187 /* register with quit() so directory is removed on exit */
1188
1189 quitSetDwnldTmpdir(dwnld_dir); /* DO NOT FREE() */
1190
1191 /* open keystore if this is a secure download */
1192 if (scheme == web_https) {
1193 if (open_keystore(err, keystore_file,
1194 get_prog_name(), pkg_passphrase_cb,
1195 KEYSTORE_DFLT_FLAGS, &keystore) != 0) {
1196 pkgerr(err);
1197 web_cleanup();
1198 quit(1);
1199 /* NOTREACHED */
1200 }
1201 }
1202
1203 if (!web_session_control(err, uri, dwnld_dir, keystore, proxy,
1204 proxy_port, retries, timeout, nointeract, &bname)) {
1205 pkgerr(err);
1206 web_cleanup();
1207 quit(1);
1208 /* NOTREACHED */
1209 }
1210
1211 /*
1212 * reset device to point to newly-downloaded file; note
1213 * when (scheme == web_https || scheme == web_http) that
1214 * device gets preloaded with a pointer to PATH_MAX bytes
1215 * allocated via malloc().
1216 */
1217
1218 len = snprintf(device, PATH_MAX, "%s/%s", dwnld_dir, bname);
1219 if ((len < 0) || (len >= PATH_MAX)) {
1220 progerr(ERR_DIR_CONST, tmpdir);
1221 quit(1);
1222 /* NOTREACHED */
1223 }
1224 }
1225
1226 /*
1227 * See if user wants this to be handled as an old style pkg.
1228 * NOTE : the ``exception_pkg()'' stuff is to be used only
1229 * through on495. This function comes out for on1095. See
1230 * PSARC 1993-546. -- JST
1231 */
1232
1233 if (getenv("NONABI_SCRIPTS") != NULL) {
1234 old_pkg = 1;
1235 }
1236
1237 /*
1238 * See if the user wants to process symlinks consistent with
1239 * the old behavior.
1240 */
1241
1242 if (getenv("PKG_NONABI_SYMLINKS") != NULL) {
1243 old_symlinks = 1;
1244 }
1245
1246 /*
1247 * See if the user wants the package name length restricted.
1248 */
1249
1250 abiPtr = getenv("PKG_ABI_NAMELENGTH");
1251 if (abiPtr && strncasecmp(abiPtr, "TRUE", 4) == 0) {
1252 ABI_namelength = 1;
1253 }
1254
1255 /*
1256 * validate the package source device - return pkgdev info that
1257 * describes the package source device.
1258 */
1259
1260 if (devtype(device, &pkgdev)) {
1261 progerr(ERR_BAD_DEVICE, device);
1262 quit(1);
1263 /* NOTREACHED */
1264 }
1265
1266 /*
1267 * If writing the packages into a spool directory instead of
1268 * installing the packages, open the package datastream and
1269 * invoke pkgtrans to perform the conversion and exit.
1270 */
1271
1272 if (spoolDir != (char *)NULL) {
1273 boolean_t b;
1274 int n;
1275
1276 echoDebug(DBG_INSTALLING_TO_SPOOL, spoolDir);
1277
1278 b = open_package_datastream(argc, argv, spoolDir, device,
1279 &repeat, &ids_name, tmpdir,
1280 &pkgdev, optind);
1281
1282 quitSetIdsName(ids_name);
1283
1284 if (b != B_TRUE) {
1285 progerr(ERR_CANNOT_OPEN_PKG_STREAM, PSTR(device));
1286 quit(1);
1287 }
1288
1289 n = pkgtrans(device, spoolDir, &argv[optind],
1290 0, NULL, NULL);
1291 quit(n);
1292 /* NOTREACHED */
1293 }
1294
1295 /*
1296 * error if there are packages on the command line and a category
1297 * was specified
1298 */
1299
1300 if ((optind < argc) && (catg_arg != NULL)) {
1301 progerr(ERR_PKGS_AND_CAT_PKGADD);
1302 usage();
1303 quit(1);
1304 /* NOTREACHED */
1305 }
1306
1307 /*
1308 * ********************************************************************
1309 * main package processing "loop"
1310 * ********************************************************************
1311 */
1312
1313 ids_name = NULL;
1314 quitSetIdsName(ids_name);
1315
1316 for (;;) {
1317 boolean_t b;
1318 char **pkglist; /* points to array of pkgs */
1319
1320 /*
1321 * open next package data stream
1322 */
1323
1324 b = open_package_datastream(argc, argv, spoolDir, device,
1325 &repeat, &ids_name, tmpdir,
1326 &pkgdev, optind);
1327
1328 quitSetIdsName(ids_name);
1329
1330 if (b == B_FALSE) {
1331 echoDebug(ERR_CANNOT_OPEN_PKG_STREAM, PSTR(device));
1332 continue;
1333 }
1334
1335 /*
1336 * package source data stream open - get the package list
1337 */
1338
1339 b = get_package_list(&pkglist, argv, catg_arg, category,
1340 ignore_sig, err, proxy_port, proxy, keystore,
1341 keystore_file, ids_name, &repeat);
1342
1343 if (b == B_FALSE) {
1344 char path[PATH_MAX];
1345
1346 echoDebug(DBG_CANNOT_GET_PKGLIST);
1347
1348 progerr(ERR_NOPKGS, pkgdev.dirname);
1349 quit(1);
1350 /* NOTREACHED */
1351 }
1352
1353 /*
1354 * count the number of packages to install
1355 * NOTE: npkgs is a global variable that is referenced by quit.c
1356 * when error messages are generated - it is referenced directly
1357 * by the other functions called below...
1358 */
1359
1360 for (npkgs = 0; pkglist[npkgs] != (char *)NULL; /* void */) {
1361 echoDebug(DBG_PKG_SELECTED, npkgs, pkglist[npkgs]);
1362 npkgs++;
1363 }
1364
1365 /* output number of packages to be added */
1366
1367 echoDebug(DBG_NUM_PKGS_TO_ADD, npkgs);
1368
1369 /*
1370 * if pkgask and response container is a file (not a directory),
1371 * and there is more than one package to install, then it is an
1372 * error - too many packages to install when response container
1373 * is a file.
1374 */
1375
1376 if ((askflag != 0) && (respdir == (char *)NULL) &&
1377 (npkgs > 1)) {
1378 progerr(ERR_TOO_MANY_PKGS);
1379 quit(1);
1380 /* NOTREACHED */
1381 }
1382
1383 /*
1384 * package list generated - add packages
1385 */
1386
1387 b = add_packages(pkglist, uri, ids_name, repeat,
1388 altBinDir, device, noZones);
1389
1390 /*
1391 * close open input data stream (source package) if left open.
1392 */
1393
1394 if (ids_name) {
1395 echoDebug(DBG_CLOSING_STREAM, ids_name,
1396 PSTR(pkgdev.dirname));
1397 (void) ds_close(1);
1398 rrmdir(pkgdev.dirname);
1399 ids_name = NULL;
1400 quitSetIdsName(ids_name);
1401 }
1402
1403 /*
1404 * continue with next sequence of packages if continue set
1405 */
1406
1407 if (b == B_TRUE) {
1408 continue;
1409 }
1410
1411 /*
1412 * not continuing - quit with 0 exit code
1413 */
1414
1415 quit(0);
1416 /* NOTREACHED */
1417 }
1418
1419 /* NOTREACHED */
1420 }
1421
1422 /*
1423 * *****************************************************************************
1424 * static internal (private) functions
1425 * *****************************************************************************
1426 */
1427
1428 /*
1429 * Name: pkgZoneCheckInstall
1430 * Description: Invoke pkginstall in a specified zone to perform a preinstall
1431 * check of the a single package in the specified zone
1432 * Arguments: a_zoneName - pointer to string representing the name of the
1433 * zone to check install the package in.
1434 * a_zoneState - current state of the zone; must be mounted or
1435 * running.
1436 * a_idsName - pointer to string representing the data stream
1437 * device (input data stream) containing the package to
1438 * be check installed.
1439 * a_altBinDir - pointer to string representing an alternative
1440 * binary location directory to pass to pkginstall.
1441 * If this is == NULL no alternative binary location is
1442 * passed to pkginstall.
1443 * a_adminFile - pointer to string representing the admin
1444 * file to pass to pkginstall when installing the package.
1445 * If this is == NULL no admin file is given to pkginstall.
1446 * a_stdoutPath - pointer to string representing the local path
1447 * into which all output written by pkginstall to stdout
1448 * is stored.
1449 * If this is == NULL stdout is redirected to /dev/null
1450 * a_tmpzn - B_TRUE when this zone is booted by the package
1451 * command or B_FALSE if it was running before.
1452 * Returns: int (see ckreturn() function for details)
1453 * 0 - success
1454 * 1 - package operation failed (fatal error)
1455 * 2 - non-fatal error (warning)
1456 * 3 - user selected quit (operation interrupted)
1457 * 4 - admin settings prevented operation
1458 * 5 - interaction required and -n (non-interactive) specified
1459 * "10" will be added to indicate "immediate reboot required"
1460 * "20" will be added to indicate "reboot after install required"
1461 */
1462
1463 static int
pkgZoneCheckInstall(char * a_zoneName,zone_state_t a_zoneState,char * a_idsName,char * a_altBinDir,char * a_adminFile,char * a_stdoutPath,boolean_t a_tmpzn)1464 pkgZoneCheckInstall(char *a_zoneName, zone_state_t a_zoneState,
1465 char *a_idsName, char *a_altBinDir, char *a_adminFile,
1466 char *a_stdoutPath, boolean_t a_tmpzn)
1467 {
1468 char *arg[MAXARGS];
1469 char *p;
1470 char adminfd_path[PATH_MAX];
1471 char path[PATH_MAX];
1472 char pkgstreamfd_path[PATH_MAX];
1473 int fds[MAX_FDS];
1474 int maxfds;
1475 int n;
1476 int nargs;
1477
1478 /* entry assertions */
1479
1480 assert(a_zoneName != (char *)NULL);
1481 assert(*a_zoneName != '\0');
1482
1483 /* entry debugging info */
1484
1485 echoDebug(DBG_PKGZONECHECKINSTALL_ENTRY);
1486 echoDebug(DBG_PKGZONECHECKINSTALL_ARGS, a_zoneName, PSTR(pkginst),
1487 PSTR(pkgdev.dirname), PSTR(pkgdev.mount), PSTR(pkgdev.bdevice),
1488 a_zoneState == ZONE_STATE_MOUNTED ? "/a" : "/",
1489 PSTR(a_idsName), PSTR(a_adminFile), PSTR(a_stdoutPath));
1490
1491 /* generate full path to 'phatinstall' to run in zone */
1492
1493 (void) snprintf(path, sizeof (path), "%s/pkginstall",
1494 "/usr/sadm/install/bin");
1495
1496 /* start at first file descriptor */
1497
1498 maxfds = 0;
1499
1500 /*
1501 * generate argument list for call to pkginstall
1502 */
1503
1504 /* start at argument 0 */
1505
1506 nargs = 0;
1507
1508 /* first argument is always: full path to executable */
1509
1510 arg[nargs++] = path;
1511
1512 /*
1513 * second argument is always: pass -O debug to pkginstall: debug mode
1514 */
1515 if (debugFlag == B_TRUE) {
1516 arg[nargs++] = "-O";
1517 arg[nargs++] = "debug";
1518 }
1519
1520 /* pkgadd -G: pass -G to pkginstall */
1521
1522 if (globalZoneOnly == B_TRUE) {
1523 arg[nargs++] = "-G";
1524 }
1525
1526 /* pkgadd -b dir: pass -b to pkginstall */
1527
1528 if (a_altBinDir != (char *)NULL) {
1529 arg[nargs++] = "-b";
1530 arg[nargs++] = a_altBinDir;
1531 }
1532
1533 /* pkgadd -C: pass -C to pkginstall: disable checksum */
1534
1535 if (disableChecksum) {
1536 arg[nargs++] = "-C";
1537 }
1538
1539 /* pkgadd -A: pass -A to pkginstall: disable attribute checking */
1540
1541 if (disableAttributes) {
1542 arg[nargs++] = "-A";
1543 }
1544
1545 /*
1546 * NONABI_SCRIPTS defined: pass -o to pkginstall; refers to a
1547 * pkg requiring operator interaction during a procedure script
1548 * (common before on1093)
1549 */
1550
1551 if (old_pkg) {
1552 arg[nargs++] = "-o";
1553 }
1554
1555 /*
1556 * PKG_NONABI_SYMLINKS defined: pass -y to pkginstall; process
1557 * symlinks consistent with old behavior
1558 */
1559
1560 if (old_symlinks) {
1561 arg[nargs++] = "-y";
1562 }
1563
1564 /*
1565 * PKG_ABI_NAMELENGTH defined: pass -e to pkginstall; causes
1566 * package name length to be restricted
1567 */
1568
1569 if (ABI_namelength) {
1570 arg[nargs++] = "-e";
1571 }
1572
1573 /* pkgadd -S: pass -S to pkginstall: suppress copyright notices */
1574
1575 arg[nargs++] = "-S";
1576
1577 /* pkgadd -M: pass -M to pkginstall: dont mount client file systems */
1578
1579 arg[nargs++] = "-M";
1580
1581 /* pkgadd -v: pass -v to pkginstall: never trace scripts */
1582
1583 /* if running pkgask, pass -i to pkginstall: running pkgask */
1584
1585 if (askflag) {
1586 return (0);
1587 }
1588
1589 /* pass "-O enable-hollow-package-support" */
1590
1591 if (is_depend_pkginfo_DB()) {
1592 arg[nargs++] = "-O";
1593 arg[nargs++] = "enable-hollow-package-support";
1594 }
1595
1596 /* check is always in non-interactive mode */
1597
1598 arg[nargs++] = "-n";
1599
1600 /* pkgadd -a admin: pass -a admin to pkginstall in zone: admin file */
1601
1602 if (a_adminFile) {
1603 int fd;
1604 fd = openLocal(a_adminFile, O_RDONLY, tmpdir);
1605 if (fd < 0) {
1606 progerr(ERR_CANNOT_COPY_LOCAL, a_adminFile,
1607 errno, strerror(errno));
1608 return (1);
1609 }
1610 (void) snprintf(adminfd_path, sizeof (adminfd_path),
1611 "/proc/self/fd/%d", fd);
1612 fds[maxfds++] = fd;
1613 arg[nargs++] = "-a";
1614 arg[nargs++] = adminfd_path;
1615 }
1616
1617 /* pkgadd -R root: pass -R /a to pkginstall when zone is mounted */
1618
1619 if (a_zoneState == ZONE_STATE_MOUNTED) {
1620 arg[nargs++] = "-R";
1621 arg[nargs++] = "/a";
1622 }
1623
1624 /* pass -N to pkginstall: program name to report */
1625
1626 arg[nargs++] = "-N";
1627 arg[nargs++] = get_prog_name();
1628
1629 /* pass "-O preinstallcheck" */
1630
1631 arg[nargs++] = "-O";
1632 arg[nargs++] = "preinstallcheck";
1633
1634 /* add "-O addzonename" */
1635
1636 arg[nargs++] = "-O";
1637 arg[nargs++] = "addzonename";
1638
1639 /*
1640 * add parent zone info/type
1641 */
1642
1643 p = z_get_zonename();
1644 if ((p != NULL) && (*p != '\0')) {
1645 char zn[MAXPATHLEN];
1646 (void) snprintf(zn, sizeof (zn),
1647 "parent-zone-name=%s", p);
1648 arg[nargs++] = "-O";
1649 arg[nargs++] = strdup(zn);
1650 }
1651
1652 /* current zone type */
1653
1654 arg[nargs++] = "-O";
1655 if (z_running_in_global_zone() == B_TRUE) {
1656 char zn[MAXPATHLEN];
1657 (void) snprintf(zn, sizeof (zn),
1658 "parent-zone-type=%s",
1659 TAG_VALUE_GLOBAL_ZONE);
1660 arg[nargs++] = strdup(zn);
1661 } else {
1662 char zn[MAXPATHLEN];
1663 (void) snprintf(zn, sizeof (zn),
1664 "parent-zone-type=%s",
1665 TAG_VALUE_NONGLOBAL_ZONE);
1666 arg[nargs++] = strdup(zn);
1667 }
1668
1669 /* Add the pkgserv options */
1670 arg[nargs++] = "-O";
1671 arg[nargs++] = pkgmodeargument(a_tmpzn ? RUN_ONCE : pkgservergetmode());
1672
1673 /* add in the package stream file */
1674
1675 if (a_idsName != NULL) {
1676 int fd;
1677 fd = openLocal(a_idsName, O_RDONLY, tmpdir);
1678 if (fd < 0) {
1679 progerr(ERR_STREAM_UNAVAILABLE, a_idsName,
1680 pkginst, strerror(errno));
1681 quit(1);
1682 }
1683 (void) snprintf(pkgstreamfd_path, sizeof (pkgstreamfd_path),
1684 "/proc/self/fd/%d", fd);
1685 fds[maxfds++] = fd;
1686 arg[nargs++] = pkgstreamfd_path;
1687 } else {
1688 progerr(ERR_PKGZONEINSTALL_NO_STREAM);
1689 quit(1);
1690 }
1691
1692 /* add package instance name */
1693
1694 arg[nargs++] = pkginst;
1695
1696 /* terminate the argument list */
1697
1698 arg[nargs++] = NULL;
1699
1700 /*
1701 * run the appropriate pkginstall command in the specified zone
1702 */
1703
1704 if (debugFlag == B_TRUE) {
1705 echoDebug(DBG_ZONE_EXEC_ENTER, a_zoneName, arg[0]);
1706 for (n = 0; arg[n]; n++) {
1707 echoDebug(DBG_ARG, n, arg[n]);
1708 }
1709 }
1710
1711 /* terminate file descriptor list */
1712
1713 fds[maxfds] = -1;
1714
1715 /* exec command in zone */
1716
1717 n = z_zone_exec(a_zoneName, path, arg, a_stdoutPath, (char *)NULL, fds);
1718
1719 echoDebug(DBG_ZONE_EXEC_EXIT, a_zoneName, arg[0], n,
1720 PSTR(a_stdoutPath));
1721
1722 /*
1723 * close any files that were opened for use by the
1724 * /proc/self/fd interface so they could be passed to programs
1725 * via the z_zone_exec() interface
1726 */
1727
1728 for (; maxfds > 0; maxfds--) {
1729 (void) close(fds[maxfds-1]);
1730 }
1731
1732 /* return results of pkginstall in zone execution */
1733
1734 return (n);
1735 }
1736
1737 /*
1738 * Name: pkgZoneInstall
1739 * Description: Invoke pkginstall in a specified zone to perform an install
1740 * of a single package in the specified zone
1741 * Arguments: a_zoneName - pointer to string representing the name of the
1742 * zone to install the package in.
1743 * a_zoneState - current state of the zone; must be mounted or
1744 * running.
1745 * a_idsName - pointer to string representing the data stream
1746 * device (input data stream) containing the package to
1747 * be installed.
1748 * a_altBinDir - pointer to string representing an alternative
1749 * binary location directory to pass to pkginstall.
1750 * If this is == NULL no alternative binary location is
1751 * passed to pkginstall.
1752 * a_adminFile - pointer to string representing the admin
1753 * file to pass to pkginstall when installing the package.
1754 * If this is == NULL no admin file is given to pkginstall.
1755 * a_stdoutPath - pointer to string representing the local path
1756 * into which all output written by pkginstall to stdout
1757 * is stored.
1758 * If this is == NULL stdout is redirected to /dev/null
1759 * a_tmpzn - B_TRUE when this zone is booted by the package
1760 * command or B_FALSE if it was running before.
1761 * Returns: int (see ckreturn() function for details)
1762 * 0 - success
1763 * 1 - package operation failed (fatal error)
1764 * 2 - non-fatal error (warning)
1765 * 3 - user selected quit (operation interrupted)
1766 * 4 - admin settings prevented operation
1767 * 5 - interaction required and -n (non-interactive) specified
1768 * "10" will be added to indicate "immediate reboot required"
1769 * "20" will be added to indicate "reboot after install required"
1770 */
1771
1772 static int
pkgZoneInstall(char * a_zoneName,zone_state_t a_zoneState,char * a_idsName,char * a_altBinDir,char * a_adminFile,boolean_t a_tmpzn)1773 pkgZoneInstall(char *a_zoneName, zone_state_t a_zoneState, char *a_idsName,
1774 char *a_altBinDir, char *a_adminFile, boolean_t a_tmpzn)
1775 {
1776 char *arg[MAXARGS];
1777 char *p;
1778 char adminfd_path[PATH_MAX];
1779 char path[PATH_MAX];
1780 char pkgstreamfd_path[PATH_MAX];
1781 char respfilefd_path[PATH_MAX];
1782 int fds[MAX_FDS];
1783 int maxfds;
1784 int n;
1785 int nargs;
1786
1787 /* entry assertions */
1788
1789 assert(a_zoneName != (char *)NULL);
1790 assert(*a_zoneName != '\0');
1791
1792 /* entry debugging info */
1793
1794 echoDebug(DBG_PKGZONEINSTALL_ENTRY);
1795 echoDebug(DBG_PKGZONEINSTALL_ARGS, a_zoneName, PSTR(pkginst),
1796 PSTR(pkgdev.dirname), PSTR(pkgdev.mount), PSTR(pkgdev.bdevice),
1797 a_zoneState == ZONE_STATE_MOUNTED ? "/a" : "", PSTR(a_idsName),
1798 a_adminFile);
1799
1800 /* generate path to pkginstall */
1801
1802 (void) snprintf(path, sizeof (path), "%s/pkginstall", PKGBIN);
1803
1804 /* start at first file descriptor */
1805
1806 maxfds = 0;
1807
1808 /*
1809 * generate argument list for call to pkginstall
1810 */
1811
1812 /* start at argument 0 */
1813
1814 nargs = 0;
1815
1816 /* first argument is path to executable */
1817
1818 arg[nargs++] = path;
1819
1820 /*
1821 * second argument is always: pass -O debug to pkginstall: debug mode
1822 */
1823 if (debugFlag == B_TRUE) {
1824 arg[nargs++] = "-O";
1825 arg[nargs++] = "debug";
1826 }
1827
1828 /* pkgadd -G: pass -G to pkginstall */
1829
1830 if (globalZoneOnly == B_TRUE) {
1831 arg[nargs++] = "-G";
1832 }
1833
1834 /* pkgadd -b dir: pass -b to pkginstall in zone */
1835
1836 if (a_altBinDir != (char *)NULL) {
1837 arg[nargs++] = "-b";
1838 arg[nargs++] = a_altBinDir;
1839 }
1840
1841 /* pkgadd -B blocksize: pass -B to pkginstall in zone */
1842
1843 if (rw_block_size != NULL) {
1844 arg[nargs++] = "-B";
1845 arg[nargs++] = rw_block_size;
1846 }
1847
1848 /* pkgadd -C: pass -C to pkgadd in zone: disable checksum */
1849
1850 if (disableChecksum) {
1851 arg[nargs++] = "-C";
1852 }
1853
1854 /* pkgadd -A: pass -A to pkgadd in zone: disable attribute checking */
1855
1856 if (disableAttributes) {
1857 arg[nargs++] = "-A";
1858 }
1859
1860 /* pkgadd -S: pass -S to pkgadd in zone: suppress copyright notices */
1861
1862 arg[nargs++] = "-S";
1863
1864 /* pkgadd -I: pass -I to pkgadd in zone: initial install */
1865
1866 if (init_install) {
1867 arg[nargs++] = "-I";
1868 }
1869
1870 /* pkgadd -M: pass -M to pkgadd in zone: dont mount client file sys */
1871
1872 arg[nargs++] = "-M";
1873
1874 /* pkgadd -v: pass -v to pkgadd in zone: trace scripts */
1875
1876 if (pkgverbose) {
1877 arg[nargs++] = "-v";
1878 }
1879
1880 /* pkgadd -z: pass -z to pkgadd in zone fresh inst from pkg save area */
1881
1882 if (saveSpoolInstall) {
1883 arg[nargs++] = "-z";
1884 }
1885
1886 /* pass "-O enable-hollow-package-support" */
1887
1888 if (is_depend_pkginfo_DB()) {
1889 arg[nargs++] = "-O";
1890 arg[nargs++] = "enable-hollow-package-support";
1891 }
1892
1893 /* pkgadd -t pass -t to pkgadd in zone disable save spool area create */
1894
1895 if (disableSaveSpool) {
1896 arg[nargs++] = "-t";
1897 }
1898
1899 /* if running pkgask, pass -i to pkgadd in zone: running pkgask */
1900
1901 if (askflag) {
1902 echo(MSG_BYPASSING_ZONE, a_zoneName);
1903 return (0);
1904 }
1905
1906 /*
1907 * pkgadd -n (not pkgask): pass -n to pkginstall: noninteractive mode
1908 */
1909 if (nointeract && !askflag) {
1910 arg[nargs++] = "-n";
1911 }
1912
1913 /* pkgadd -a admin: pass -a admin to pkginstall in zone: admin file */
1914
1915 if (a_adminFile) {
1916 int fd;
1917 fd = openLocal(a_adminFile, O_RDONLY, tmpdir);
1918 if (fd < 0) {
1919 progerr(ERR_CANNOT_COPY_LOCAL, a_adminFile,
1920 errno, strerror(errno));
1921 return (1);
1922 }
1923 (void) snprintf(adminfd_path, sizeof (adminfd_path),
1924 "/proc/self/fd/%d", fd);
1925 fds[maxfds++] = fd;
1926 arg[nargs++] = "-a";
1927 arg[nargs++] = adminfd_path;
1928 }
1929
1930 /* pkgadd -R root: pass -R /a to pkginstall when zone is mounted */
1931 if (a_zoneState == ZONE_STATE_MOUNTED) {
1932 arg[nargs++] = "-R";
1933 arg[nargs++] = "/a";
1934 }
1935
1936 /*
1937 * pkgadd -D arg: pass -D dryrun to pkginstall in zone: dryrun
1938 * mode/file
1939 */
1940 if (pkgdrtarg) {
1941 arg[nargs++] = "-D";
1942 arg[nargs++] = pkgdrtarg;
1943 }
1944
1945 /*
1946 * pkgadd -c cont: pass -c cont to pkginstall in zone: continuation
1947 * file
1948 */
1949 if (pkgcontsrc) {
1950 arg[nargs++] = "-c";
1951 arg[nargs++] = pkgcontsrc;
1952 }
1953
1954 /* pkgadd -r resp: pass -r resp to pkginstall in zone: response file */
1955
1956 if (respfile) {
1957 int fd;
1958 fd = openLocal(respfile, O_RDONLY, tmpdir);
1959 if (fd < 0) {
1960 progerr(ERR_CANNOT_COPY_LOCAL, a_adminFile,
1961 errno, strerror(errno));
1962 return (1);
1963 }
1964 (void) snprintf(respfilefd_path,
1965 sizeof (respfilefd_path),
1966 "/proc/self/fd/%d", fd);
1967 fds[maxfds++] = fd;
1968 arg[nargs++] = "-r";
1969 arg[nargs++] = respfilefd_path;
1970 }
1971
1972 /* add "-O addzonename" */
1973
1974 arg[nargs++] = "-O";
1975 arg[nargs++] = "addzonename";
1976
1977 /*
1978 * add parent zone info/type
1979 */
1980
1981 p = z_get_zonename();
1982 if ((p != NULL) && (*p != '\0')) {
1983 char zn[MAXPATHLEN];
1984 (void) snprintf(zn, sizeof (zn),
1985 "parent-zone-name=%s", p);
1986 arg[nargs++] = "-O";
1987 arg[nargs++] = strdup(zn);
1988 }
1989
1990 /* current zone type */
1991
1992 arg[nargs++] = "-O";
1993 if (z_running_in_global_zone() == B_TRUE) {
1994 char zn[MAXPATHLEN];
1995 (void) snprintf(zn, sizeof (zn),
1996 "parent-zone-type=%s",
1997 TAG_VALUE_GLOBAL_ZONE);
1998 arg[nargs++] = strdup(zn);
1999 } else {
2000 char zn[MAXPATHLEN];
2001 (void) snprintf(zn, sizeof (zn),
2002 "parent-zone-type=%s",
2003 TAG_VALUE_NONGLOBAL_ZONE);
2004 arg[nargs++] = strdup(zn);
2005 }
2006
2007 /* Add the pkgserv options */
2008 arg[nargs++] = "-O";
2009 arg[nargs++] = pkgmodeargument(a_tmpzn ? RUN_ONCE : pkgservergetmode());
2010
2011 /* add in the package stream file */
2012
2013 if (a_idsName != NULL) {
2014 int fd;
2015 fd = openLocal(a_idsName, O_RDONLY, tmpdir);
2016 if (fd < 0) {
2017 progerr(ERR_STREAM_UNAVAILABLE, a_idsName,
2018 pkginst, strerror(errno));
2019 quit(1);
2020 }
2021 (void) snprintf(pkgstreamfd_path, sizeof (pkgstreamfd_path),
2022 "/proc/self/fd/%d", fd);
2023 fds[maxfds++] = fd;
2024 arg[nargs++] = pkgstreamfd_path;
2025 } else {
2026 progerr(ERR_PKGZONEINSTALL_NO_STREAM);
2027 quit(1);
2028 }
2029
2030 /* add package instance name */
2031
2032 arg[nargs++] = pkginst;
2033
2034 /* terminate the argument list */
2035
2036 arg[nargs++] = NULL;
2037
2038 /*
2039 * run the appropriate pkginstall command in the specified zone
2040 */
2041
2042 if (debugFlag == B_TRUE) {
2043 echoDebug(DBG_ZONE_EXEC_ENTER, a_zoneName, arg[0]);
2044 for (n = 0; arg[n]; n++) {
2045 echoDebug(DBG_ARG, n, arg[n]);
2046 }
2047 }
2048
2049 /* terminate file descriptor list */
2050
2051 fds[maxfds] = -1;
2052
2053 /* exec command in zone */
2054
2055 n = z_zone_exec(a_zoneName, path, arg, (char *)NULL, (char *)NULL, fds);
2056
2057 echoDebug(DBG_ZONE_EXEC_EXIT, a_zoneName, arg[0], n, "");
2058
2059 /*
2060 * close any files that were opened for use by the
2061 * /proc/self/fd interface so they could be passed to programs
2062 * via the z_zone_exec() interface
2063 */
2064
2065 for (; maxfds > 0; maxfds--) {
2066 (void) close(fds[maxfds-1]);
2067 }
2068
2069 /* return results of pkginstall in zone execution */
2070
2071 return (n);
2072 }
2073
2074 /*
2075 * Name: pkgInstall
2076 * Description: Invoke pkginstall in the current zone to perform an install
2077 * of a single package to the current zone or standalone system
2078 * Arguments: a_altRoot - pointer to string representing the alternative
2079 * root to use for the install
2080 * a_idsName - pointer to string representing the data stream
2081 * device (input data stream) containing the package to
2082 * be installed.
2083 * a_pkgDir - pointer to string representing the path to the
2084 * directory containing the package
2085 * a_altBinDir - pointer to string representing location of the
2086 * pkginstall executable to run. If not NULL, then pass
2087 * the path specified to the -b option to pkginstall.
2088 * Returns: int (see ckreturn() function for details)
2089 * 0 - success
2090 * 1 - package operation failed (fatal error)
2091 * 2 - non-fatal error (warning)
2092 * 3 - user selected quit (operation interrupted)
2093 * 4 - admin settings prevented operation
2094 * 5 - interaction required and -n (non-interactive) specified
2095 * "10" will be added to indicate "immediate reboot required"
2096 * "20" will be added to indicate "reboot after install required"
2097 * NOTE: Both a_idsName and a_pkgDir are used to determine where the
2098 * package to be installed is located. If a_idsName is != NULL
2099 * then it must be the path to a device containing a package
2100 * stream that contains the package to be installed. If a_idsName
2101 * is == NULL then a_pkgDir must contain a full path to a directory
2102 * that contains the package to be installed.
2103 */
2104
2105 static int
pkgInstall(char * a_altRoot,char * a_idsName,char * a_pkgDir,char * a_altBinDir)2106 pkgInstall(char *a_altRoot, char *a_idsName, char *a_pkgDir, char *a_altBinDir)
2107 {
2108 char *arg[MAXARGS];
2109 char *p;
2110 char path[PATH_MAX];
2111 char buffer[256];
2112 int n, nargs;
2113
2114 /* entry debugging info */
2115
2116 echoDebug(DBG_PKGINSTALL_ENTRY);
2117 echoDebug(DBG_PKGINSTALL_ARGS, PSTR(pkginst), PSTR(pkgdev.dirname),
2118 PSTR(pkgdev.mount), PSTR(pkgdev.bdevice), PSTR(a_altRoot),
2119 PSTR(a_idsName), PSTR(a_pkgDir));
2120
2121 /* generate full path to 'pkginstall' to run in zone */
2122
2123 (void) snprintf(path, sizeof (path), "%s/pkginstall",
2124 a_altBinDir == (char *)NULL ? PKGBIN : a_altBinDir);
2125 /*
2126 * generate argument list for call to pkginstall
2127 */
2128
2129 /* start at argument 0 */
2130
2131 nargs = 0;
2132
2133 /* first argument is path to executable */
2134
2135 arg[nargs++] = path;
2136
2137 /*
2138 * second argument is always: pass -O debug to pkginstall: debug mode
2139 */
2140 if (debugFlag == B_TRUE) {
2141 arg[nargs++] = "-O";
2142 arg[nargs++] = "debug";
2143 }
2144
2145 arg[nargs++] = "-O";
2146 arg[nargs++] = pkgmodeargument(pkgservergetmode());
2147
2148 /*
2149 * pkgadd -G: pass -G to pkginstall if:
2150 * - the -G option is specified on the pkgadd command line
2151 * - this package is marked 'this zone only':
2152 * -- package has SUNW_PKG_THISZONE=true, or
2153 * -- package has a request script
2154 * Setting -G for pkginstall causes pkginstall to install the package
2155 * in the target zone. If running in the global zone, will install the
2156 * package and mark the package as installed "in the global zone only".
2157 * If running in a non-global zone, will just install the package.
2158 */
2159
2160 if (globalZoneOnly == B_TRUE) {
2161 arg[nargs++] = "-G";
2162 } else if (pkgPackageIsThisZone(pkginst) == B_TRUE) {
2163 arg[nargs++] = "-G";
2164 }
2165
2166 /* pkgadd -b dir: pass -b to pkginstall */
2167
2168 if (a_altBinDir != (char *)NULL) {
2169 arg[nargs++] = "-b";
2170 arg[nargs++] = a_altBinDir;
2171 }
2172
2173 /* pkgadd -B blocksize: pass -B to pkginstall */
2174
2175 if (rw_block_size != NULL) {
2176 arg[nargs++] = "-B";
2177 arg[nargs++] = rw_block_size;
2178 }
2179
2180 /* pkgadd -C: pass -C to pkginstall: disable checksum */
2181
2182 if (disableChecksum) {
2183 arg[nargs++] = "-C";
2184 }
2185
2186 /* pkgadd -A: pass -A to pkginstall: disable attribute checking */
2187
2188 if (disableAttributes) {
2189 arg[nargs++] = "-A";
2190 }
2191
2192 /*
2193 * NONABI_SCRIPTS defined: pass -o to pkginstall; refers to a
2194 * pkg requiring operator interaction during a procedure script
2195 * (common before on1093)
2196 */
2197
2198 if (old_pkg) {
2199 arg[nargs++] = "-o";
2200 }
2201
2202 /*
2203 * PKG_NONABI_SYMLINKS defined: pass -y to pkginstall; process
2204 * symlinks consistent with old behavior
2205 */
2206
2207 if (old_symlinks) {
2208 arg[nargs++] = "-y";
2209 }
2210
2211 /*
2212 * PKG_ABI_NAMELENGTH defined: pass -e to pkginstall; causes
2213 * package name length to be restricted
2214 */
2215
2216 if (ABI_namelength) {
2217 arg[nargs++] = "-e";
2218 }
2219
2220 /* pkgadd -S: pass -S to pkginstall: suppress copyright notices */
2221
2222 if (suppressCopyright) {
2223 arg[nargs++] = "-S";
2224 }
2225
2226 /* pkgadd -I: pass -I to pkginstall: initial install being performed */
2227
2228 if (init_install) {
2229 arg[nargs++] = "-I";
2230 }
2231
2232 /* pkgadd -M: pass -M to pkginstall: dont mount client file systems */
2233
2234 if (no_map_client) {
2235 arg[nargs++] = "-M";
2236 }
2237
2238 /* pkgadd -v: pass -v to pkginstall: trace scripts */
2239
2240 if (pkgverbose) {
2241 arg[nargs++] = "-v";
2242 }
2243
2244 /* pkgadd -z: pass -z to pkginstall: fresh install from pkg save area */
2245
2246 if (saveSpoolInstall) {
2247 arg[nargs++] = "-z";
2248 }
2249
2250 /*
2251 * if running in a non-global zone and the 'hollow' attribute is
2252 * passed in, then pass -h to pkginstall so that it knows how to
2253 * handle hollow packages for this local zone.
2254 */
2255
2256 if (!z_running_in_global_zone() && is_depend_pkginfo_DB()) {
2257 arg[nargs++] = "-h";
2258 }
2259
2260 /* pkgadd -t: pass -t to pkginstall: disable save spool area creation */
2261
2262 if (disableSaveSpool) {
2263 arg[nargs++] = "-t";
2264 }
2265
2266 /* if running pkgask, pass -i to pkginstall: running pkgask */
2267
2268 if (askflag) {
2269 arg[nargs++] = "-i";
2270 }
2271
2272 /* pkgadd -n (not pkgask): pass -n to pkginstall: noninteractive mode */
2273
2274 if (nointeract && !askflag) {
2275 arg[nargs++] = "-n";
2276 }
2277
2278 /* pkgadd -a admin: pass -a admin to pkginstall: admin file */
2279
2280 if (admnfile) {
2281 arg[nargs++] = "-a";
2282 arg[nargs++] = admnfile;
2283 }
2284
2285 /* pkgadd -D dryrun: pass -D dryrun to pkginstall: dryrun mode/file */
2286
2287 if (pkgdrtarg) {
2288 arg[nargs++] = "-D";
2289 arg[nargs++] = pkgdrtarg;
2290 }
2291
2292 /* pkgadd -c cont: pass -c cont to pkginstall: continuation file */
2293
2294 if (pkgcontsrc) {
2295 arg[nargs++] = "-c";
2296 arg[nargs++] = pkgcontsrc;
2297 }
2298
2299 /* pkgadd -V vfstab: pass -V vfstab to pkginstall: alternate vfstab */
2300
2301 if (vfstab_file) {
2302 arg[nargs++] = "-V";
2303 arg[nargs++] = vfstab_file;
2304 }
2305
2306 /* pkgadd -r resp: pass -r resp to pkginstall: response file */
2307
2308 if (respfile) {
2309 arg[nargs++] = "-r";
2310 arg[nargs++] = respfile;
2311 }
2312
2313 /* pkgadd -R root: pass -R root to pkginstall: alternative root */
2314
2315 if (a_altRoot && *a_altRoot) {
2316 arg[nargs++] = "-R";
2317 arg[nargs++] = a_altRoot;
2318 }
2319
2320 /*
2321 * If input data stream is available,
2322 * - add: -d ids_name -p number_of_parts
2323 * else,
2324 * - add: -d device -m mount [-f type]
2325 */
2326
2327 if (a_idsName != NULL) {
2328 arg[nargs++] = "-d";
2329 arg[nargs++] = a_idsName;
2330 arg[nargs++] = "-p";
2331 ds_close(1);
2332 ds_putinfo(buffer, sizeof (buffer));
2333 arg[nargs++] = buffer;
2334 } else if (pkgdev.mount != NULL) {
2335 arg[nargs++] = "-d";
2336 arg[nargs++] = pkgdev.bdevice;
2337 arg[nargs++] = "-m";
2338 arg[nargs++] = pkgdev.mount;
2339 if (pkgdev.fstyp != NULL) {
2340 arg[nargs++] = "-f";
2341 arg[nargs++] = pkgdev.fstyp;
2342 }
2343 }
2344
2345 /*
2346 * add parent zone info/type
2347 */
2348
2349 p = z_get_zonename();
2350 if ((p != NULL) && (*p != '\0')) {
2351 char zn[MAXPATHLEN];
2352 (void) snprintf(zn, sizeof (zn),
2353 "parent-zone-name=%s", p);
2354 arg[nargs++] = "-O";
2355 arg[nargs++] = strdup(zn);
2356 }
2357
2358 /* current zone type */
2359
2360 arg[nargs++] = "-O";
2361 if (z_running_in_global_zone() == B_TRUE) {
2362 char zn[MAXPATHLEN];
2363 (void) snprintf(zn, sizeof (zn),
2364 "parent-zone-type=%s",
2365 TAG_VALUE_GLOBAL_ZONE);
2366 arg[nargs++] = strdup(zn);
2367 } else {
2368 char zn[MAXPATHLEN];
2369 (void) snprintf(zn, sizeof (zn),
2370 "parent-zone-type=%s",
2371 TAG_VALUE_NONGLOBAL_ZONE);
2372 arg[nargs++] = strdup(zn);
2373 }
2374
2375 /* pass -N to pkginstall: program name to report */
2376
2377 arg[nargs++] = "-N";
2378 arg[nargs++] = get_prog_name();
2379
2380 /* add package directory name */
2381
2382 arg[nargs++] = a_pkgDir;
2383
2384 /* add package instance name */
2385
2386 arg[nargs++] = pkginst;
2387
2388 /* terminate the argument list */
2389
2390 arg[nargs++] = NULL;
2391
2392 /*
2393 * run the appropriate pkginstall command in the specified zone
2394 */
2395
2396 if (debugFlag == B_TRUE) {
2397 echoDebug(DBG_ZONE_EXEC_ENTER, "global", arg[0]);
2398 for (n = 0; arg[n]; n++) {
2399 echoDebug(DBG_ARG, n, arg[n]);
2400 }
2401 }
2402
2403 /* execute pkginstall command */
2404
2405 n = pkgexecv(NULL, NULL, NULL, NULL, arg);
2406
2407 /* return results of pkginstall execution */
2408
2409 return (n);
2410 }
2411
2412 /*
2413 * function to clear out any exisiting error return conditions that may have
2414 * been set by previous calls to ckreturn()
2415 */
2416 static void
resetreturn()2417 resetreturn()
2418 {
2419 admnflag = 0; /* != 0 if any pkg op admin setting failure (4) */
2420 doreboot = 0; /* != 0 if reboot required after installation (>= 10) */
2421 failflag = 0; /* != 0 if fatal error has occurred (1) */
2422 intrflag = 0; /* != 0 if user selected quit (3) */
2423 ireboot = 0; /* != 0 if immediate reboot required (>= 20) */
2424 nullflag = 0; /* != 0 if admin interaction required (5) */
2425 warnflag = 0; /* != 0 if non-fatal error has occurred (2) */
2426 interrupted = 0; /* last pkg op was quit (1,2,3,4,5) */
2427 needconsult = 0; /* essential ask admin now (1,2,3,5) */
2428 }
2429
2430 /*
2431 * function which checks the indicated return value
2432 * and indicates disposition of installation
2433 */
2434 static void
ckreturn(int retcode)2435 ckreturn(int retcode)
2436 {
2437 /*
2438 * entry debugging info
2439 */
2440
2441 echoDebug(DBG_PKGADD_CKRETURN, retcode, PSTR(pkginst));
2442
2443 /* reset needconsult so it only reflects this call to ckreturn */
2444 needconsult = 0;
2445
2446 switch (retcode) {
2447 case 0: /* successful */
2448 case 10:
2449 case 20:
2450 break; /* empty case */
2451
2452 case 1: /* package operation failed (fatal error) */
2453 case 11:
2454 case 21:
2455 failflag++;
2456 interrupted++;
2457 needconsult++;
2458 break;
2459
2460 case 2: /* non-fatal error (warning) */
2461 case 12:
2462 case 22:
2463 warnflag++;
2464 interrupted++;
2465 needconsult++;
2466 break;
2467
2468 case 3: /* user selected quit; operation interrupted */
2469 case 13:
2470 case 23:
2471 intrflag++;
2472 interrupted++;
2473 needconsult++;
2474 break;
2475
2476 case 4: /* admin settings prevented operation */
2477 case 14:
2478 case 24:
2479 admnflag++;
2480 interrupted++;
2481 break;
2482
2483 case 5: /* administration: interaction req (no -n) */
2484 case 15:
2485 case 25:
2486 nullflag++;
2487 interrupted++;
2488 needconsult++;
2489 break;
2490
2491 default:
2492 failflag++;
2493 interrupted++;
2494 needconsult++;
2495 return;
2496 }
2497
2498 if (retcode >= 20) {
2499 ireboot++;
2500 } else if (retcode >= 10) {
2501 doreboot++;
2502 }
2503 }
2504
2505 static void
usage(void)2506 usage(void)
2507 {
2508 char *prog = get_prog_name();
2509
2510 if (askflag) {
2511 (void) fprintf(stderr, ERR_USAGE_PKGASK, prog);
2512 } else if (z_running_in_global_zone() == B_FALSE) {
2513 (void) fprintf(stderr, ERR_USAGE_PKGADD_NONGLOBALZONE,
2514 prog, prog);
2515 } else {
2516 (void) fprintf(stderr, ERR_USAGE_PKGADD_GLOBALZONE,
2517 prog, prog);
2518 }
2519 }
2520
2521 /*
2522 * Name: check_applicability
2523 * Description: determine if a package is installable in this zone; that is,
2524 * does the scope of install conflict with existing installation
2525 * or can the package be installed
2526 * Arguments: a_packageDir - [RO, *RO] - (char *)
2527 * Pointer to string representing the directory where the
2528 * package is located
2529 * a_pkgInst - [RO, *RO] - (char *)
2530 * Pointer to string representing the name of the package
2531 * to check
2532 * a_rootPath - [RO, *RO] - (char *)
2533 * Pointer to string representing path to the root of the
2534 * file system where the package is to be installed - this
2535 * is usually the same as the "-R" argument to pkgadd
2536 * a_flags - [RO, *RO] - (CAF_T)
2537 * Flags set by the caller to indicate the conditions
2538 * under which the package is to be installed:
2539 * CAF_IN_GLOBAL_ZONE - in global zone
2540 * CAF_SCOPE_GLOBAL - -G specified
2541 * CAF_SCOPE_NONGLOBAL - -Z specified
2542 * Returns: boolean_t
2543 * B_TRUE - the package can be installed
2544 * B_FALSE - the package can not be installed
2545 */
2546
2547 static boolean_t
check_applicability(char * a_packageDir,char * a_pkgInst,char * a_rootPath,CAF_T a_flags)2548 check_applicability(char *a_packageDir, char *a_pkgInst, char *a_rootPath,
2549 CAF_T a_flags)
2550 {
2551 FILE *pkginfoFP;
2552 FILE *pkgmapFP;
2553 boolean_t all_zones; /* pkg is "all zones" only */
2554 boolean_t in_gz_only; /* pkg installed in global zone only */
2555 boolean_t is_hollow; /* pkg is "hollow" */
2556 boolean_t pkg_installed; /* pkg is installed */
2557 boolean_t this_zone; /* pkg is "this zone" only */
2558 boolean_t reqfile_found = B_FALSE;
2559 char instPkg[PKGSIZ+1]; /* installed pkg instance nam */
2560 char instPkgPath[PATH_MAX]; /* installed pkg toplevel dir */
2561 char pkginfoPath[PATH_MAX]; /* pkg 2 install pkginfo file */
2562 char pkgmapPath[PATH_MAX]; /* pkg 2 install pkgmap file */
2563 char pkgpath[PATH_MAX]; /* pkg 2 install toplevel dir */
2564 int len;
2565 char line[LINE_MAX];
2566
2567 /* entry assertions */
2568
2569 assert(a_packageDir != (char *)NULL);
2570 assert(*a_packageDir != '\0');
2571 assert(a_pkgInst != (char *)NULL);
2572 assert(*a_pkgInst != '\0');
2573
2574 /* normalize root path */
2575
2576 if (a_rootPath == (char *)NULL) {
2577 a_rootPath = "";
2578 }
2579
2580 /* entry debugging info */
2581
2582 echoDebug(DBG_CHECKAPP_ENTRY);
2583 echoDebug(DBG_CHECKAPP_ARGS, a_pkgInst, a_packageDir, a_rootPath);
2584
2585 /*
2586 * calculate paths to various objects
2587 */
2588
2589 /* path to package to be installed top level (main) directory */
2590
2591 len = snprintf(pkgpath, sizeof (pkgpath), "%s/%s", a_packageDir,
2592 a_pkgInst);
2593 if (len > sizeof (pkgpath)) {
2594 progerr(ERR_CREATE_PATH_2, a_packageDir, a_pkgInst);
2595 return (B_FALSE);
2596 }
2597
2598 /* error if package top level directory does not exist */
2599
2600 if (isdir(pkgpath) != 0) {
2601 progerr(ERR_NO_PKGDIR, pkgpath, a_pkgInst, strerror(errno));
2602 return (B_FALSE);
2603 }
2604
2605 /* path to pkginfo file within the package to be installed */
2606
2607 len = snprintf(pkginfoPath, sizeof (pkginfoPath), "%s/pkginfo",
2608 pkgpath);
2609 if (len > sizeof (pkginfoPath)) {
2610 progerr(ERR_CREATE_PATH_2, pkgpath, "pkginfo");
2611 return (B_FALSE);
2612 }
2613
2614 /* path to highest instance of package currently installed */
2615
2616 pkgLocateHighestInst(instPkgPath, sizeof (instPkgPath),
2617 instPkg, sizeof (instPkg), a_rootPath, a_pkgInst);
2618
2619 /*
2620 * gather information from this package's pkginfo file
2621 */
2622
2623 pkginfoFP = fopen(pkginfoPath, "r");
2624
2625 if (pkginfoFP == (FILE *)NULL) {
2626 progerr(ERR_NO_PKG_INFOFILE, a_pkgInst, pkginfoPath,
2627 strerror(errno));
2628 return (B_FALSE);
2629 }
2630
2631 /* determine "HOLLOW" setting for this package */
2632
2633 is_hollow = pkginfoParamTruth(pkginfoFP, PKG_HOLLOW_VARIABLE,
2634 "true", B_FALSE);
2635
2636 /* determine "ALLZONES" setting for this package */
2637
2638 all_zones = pkginfoParamTruth(pkginfoFP, PKG_ALLZONES_VARIABLE,
2639 "true", B_FALSE);
2640
2641 /* determine "THISZONE" setting for this package */
2642
2643 this_zone = pkginfoParamTruth(pkginfoFP, PKG_THISZONE_VARIABLE,
2644 "true", B_FALSE);
2645
2646 /* close pkginfo file */
2647
2648 (void) fclose(pkginfoFP);
2649
2650 /*
2651 * If request file is not found, it may be in the datastream which
2652 * is not yet unpacked. Check in the pkgmap file.
2653 */
2654 if (isfile(pkgpath, REQUEST_FILE) != 0) {
2655
2656 /* path to pkgmap file within the package to be installed */
2657 (void) snprintf(pkgmapPath, sizeof (pkgmapPath), "%s/pkgmap",
2658 pkgpath);
2659
2660 pkgmapFP = fopen(pkgmapPath, "r");
2661
2662 if (pkgmapFP == NULL) {
2663 progerr(ERR_NO_PKG_MAPFILE, a_pkgInst,
2664 pkgmapPath, strerror(errno));
2665 return (B_FALSE);
2666 }
2667
2668 while (fgets(line, LINE_MAX, pkgmapFP) != NULL) {
2669 if (strstr(line, " i request") != NULL) {
2670 reqfile_found = B_TRUE;
2671 break;
2672 }
2673 }
2674 (void) fclose(pkgmapFP);
2675 } else {
2676 reqfile_found = B_TRUE;
2677 }
2678
2679 /*
2680 * If this package is not marked for installation in this zone only,
2681 * check to see if this package has a request script. If this package
2682 * does have a request script, then mark the package for installation
2683 * in this zone only. Any package with a request script cannot be
2684 * installed outside of the zone the pkgadd command is being run in,
2685 * nor can such a package be installed as part of a new zone install.
2686 * A new zone install must be non-interactive, which is required
2687 * by all packages integrated into the Solaris WOS.
2688 */
2689
2690 if ((!this_zone) && (reqfile_found)) {
2691 if (a_flags & CAF_IN_GLOBAL_ZONE) {
2692 echoDebug(DBG_CHECKAPP_THISZONE_REQUEST, a_pkgInst);
2693 }
2694 this_zone = B_TRUE;
2695 }
2696
2697 /*
2698 * If this package is already installed, see if the current installation
2699 * of the package has a request file - if it does, then act as though
2700 * the current package to be added has a request file - install the
2701 * package in the current zone only.
2702 */
2703
2704 if ((!this_zone) && (instPkgPath[0] != '\0') &&
2705 (isfile(instPkgPath, REQUEST_FILE) == 0)) {
2706 if (a_flags & CAF_IN_GLOBAL_ZONE) {
2707 echoDebug(DBG_CHECKAPP_THISZONE_INSTREQ,
2708 a_pkgInst, instPkg);
2709 }
2710 this_zone = B_TRUE;
2711 }
2712
2713 /* gather information from the global zone only file */
2714
2715 in_gz_only = B_FALSE;
2716 if (a_flags & CAF_IN_GLOBAL_ZONE) {
2717 in_gz_only = pkgIsPkgInGzOnly(a_rootPath, a_pkgInst);
2718 }
2719
2720 /* determine if this package is currently installed */
2721
2722 pkg_installed = pkginfoIsPkgInstalled((struct pkginfo **)NULL,
2723 a_pkgInst);
2724
2725 /*
2726 * verify package applicability based on information gathered,
2727 * and validate the three SUNW_PKG_ options:
2728 *
2729 * -----------|--------------|-------------|-------------|-----------
2730 * - - - - - -| GLOBAL ZONE -| GLOBAL ZONE | LOCAL ZONE | LOCAL ZONE
2731 * - - - - - -| - - pkgadd - | pkgadd -G | pkgadd | pkgadd -G
2732 * ----1------|--------------|-------------|-------------|------------
2733 * ALLZONES f | add to gz | add to gz | add to ls | add to ls
2734 * HOLLOW f | current lz | not to curr | only - - - -| only - - -
2735 * THISZONE f | futr lz - - -| or futr lz | - - - - - - | - - - - - -
2736 * ----2------|--------------|-------------|-------------|------------
2737 * ALLZONES T | add to gz | operation | operation | operation
2738 * HOLLOW f | current lz | not allowed | not allowed | not allowed
2739 * THISZONE f | future lz | - - - - - - | - - - - - - | - - - - - -
2740 * ----3------|--------------|-------------|-------------|------------
2741 * ALLZONES T | add to gz | operation | operation | operation
2742 * HOLLOW T | pkg db only | not allowed | not allowed | not allowed
2743 * THISZONE f | curr/futr lz | - - - - - - | - - - - - - | - - - - - -
2744 * ----4------|--------------|-------------|-------------|------------
2745 * ALLZONES T | bad option | bad option | bad option | bad option
2746 * HOLLOW * | combo - - - -| combo - - - | combo - - - | combo - -
2747 * THISZONE T | - - - - - - -|- - - - - - -|- - - - - - -|- - - - - -
2748 * ----5------|--------------|-------------|-------------|------------
2749 * ALLZONES f | bad option | bad option | bad option | bad option
2750 * HOLLOW T | combo - - - -| combo - - - | combo - - - | combo - - -
2751 * THISZONE * | - - - - - - -| - - - - - - | - - - - - - | - - - - - -
2752 * ----6------|--------------|-------------|-------------|------------
2753 * ALLZONES f | add to gz | add to gz | add to lz | add to lz
2754 * HOLLOW f | not current | not current | only - - - | only - - -
2755 * THISZONE T | or future lz | or futr lz | - - - - - - | - - - - - -
2756 * -----------|--------------|-------------|-------------|-----------
2757 */
2758
2759 /* pkg "all zones" && "this zone" (#4) */
2760
2761 if (all_zones && this_zone) {
2762 progerr(ERR_ALLZONES_AND_THISZONE, a_pkgInst,
2763 PKG_ALLZONES_VARIABLE, PKG_THISZONE_VARIABLE);
2764 return (B_FALSE);
2765 }
2766
2767 /* pkg "!all zones" && "hollow" (#5) */
2768
2769 if ((!all_zones) && is_hollow) {
2770 progerr(ERR_NOW_ALLZONES_AND_HOLLOW, a_pkgInst,
2771 PKG_ALLZONES_VARIABLE, PKG_HOLLOW_VARIABLE);
2772 return (B_FALSE);
2773 }
2774
2775 /* pkg ALLZONES=true && -Z specified */
2776
2777 if (all_zones && (a_flags & CAF_SCOPE_NONGLOBAL)) {
2778 progerr(ERR_ALLZONES_AND_Z_USED, a_pkgInst);
2779 return (B_FALSE);
2780 }
2781
2782 /* pkg ALLZONES=true & not running in global zone (#2/#3) */
2783
2784 if (all_zones && (!(a_flags & CAF_IN_GLOBAL_ZONE))) {
2785 progerr(ERR_ALLZONES_AND_IN_LZ, a_pkgInst);
2786 return (B_FALSE);
2787 }
2788
2789 /* pkg "in gz only" & pkg "NOT installed" */
2790
2791 if (in_gz_only && (!pkg_installed)) {
2792 /* MAKE A WARNING */
2793 echo(ERR_IN_GZ_AND_NOT_INSTALLED, a_pkgInst,
2794 pkgGetGzOnlyPath());
2795 }
2796
2797 /* pkg ALLZONES=true & pkg "in gz only" & pkg "is installed" */
2798
2799 if (all_zones && in_gz_only && pkg_installed) {
2800 progerr(ERR_IN_GZ_AND_ALLZONES_AND_INSTALLED, a_pkgInst);
2801 return (B_FALSE);
2802 }
2803
2804 /* pkg ALLZONES=true && -G specified (#2/#3) */
2805
2806 if (all_zones && (a_flags & CAF_SCOPE_GLOBAL)) {
2807 progerr(ERR_ALLZONES_AND_G_USED, a_pkgInst);
2808 return (B_FALSE);
2809 }
2810
2811 /* pkg "!this zone" && "in gz only" & -G not specified */
2812
2813 if ((!this_zone) && in_gz_only && (!(a_flags & CAF_SCOPE_GLOBAL))) {
2814 progerr(ERR_IN_GZ_AND_NO_G_USED, a_pkgInst);
2815 return (B_FALSE);
2816 }
2817
2818 /* pkg "NOT in gz only" & -Z specified */
2819
2820 if ((!in_gz_only) && (a_flags & CAF_SCOPE_NONGLOBAL)) {
2821 progerr(ERR_NOT_IN_GZ_AND_Z_USED, a_pkgInst);
2822 return (B_FALSE);
2823 }
2824
2825 /* pkg "this zone" && -Z specified */
2826
2827 if (this_zone && (a_flags & CAF_SCOPE_NONGLOBAL)) {
2828 progerr(ERR_THISZONE_AND_Z_USED, PKG_THISZONE_VARIABLE,
2829 a_pkgInst);
2830 return (B_FALSE);
2831 }
2832
2833 /*
2834 * If this package is marked 'this zone only', then mark the package
2835 * as "add to this zone only". This is referenced by the various
2836 * add_package_... functions to determine if the package should be
2837 * added to the current zone, or to all zones, depending on the
2838 * zone in which the command is being run.
2839 */
2840
2841 if (this_zone) {
2842 pkgAddThisZonePackage(a_pkgInst);
2843 }
2844
2845 return (B_TRUE);
2846 }
2847
2848 /*
2849 * Name: create_zone_adminfile
2850 * Description: Given a zone temporary directory and optionally an existing
2851 * administration file, generate an administration file that
2852 * can be used to perform "non-interactive" operations in a
2853 * non-global zone.
2854 * Arguments: r_zoneAdminFile - pointer to handle that will contain a
2855 * string representing the path to the temporary
2856 * administration file created - this must be NULL
2857 * before the first call to this function - on
2858 * subsequent calls if the pointer is NOT null then
2859 * the existing string will NOT be overwritten.
2860 * a_zoneTempDir - pointer to string representing the path
2861 * to the zone temporary directory to create the
2862 * temporary administration file in
2863 * a_admnfile - pointer to string representing the path to
2864 * an existing "user" administration file - the
2865 * administration file created will contain the
2866 * settings contained in this file, modified as
2867 * appropriate to supress any interaction;
2868 * If this is == NULL then the administration file
2869 * created will not contain any extra settings
2870 * Returns: void
2871 * NOTE: Any string returned is placed in new storage for the
2872 * calling method. The caller must use 'free' to dispose
2873 * of the storage once the string is no longer needed.
2874 * NOTE: On any error this function will call 'quit(1)'
2875 */
2876
2877 static void
create_zone_adminfile(char ** r_zoneAdminFile,char * a_zoneTempDir,char * a_admnfile)2878 create_zone_adminfile(char **r_zoneAdminFile, char *a_zoneTempDir,
2879 char *a_admnfile)
2880 {
2881 boolean_t b;
2882
2883 /* entry assertions */
2884
2885 assert(r_zoneAdminFile != (char **)NULL);
2886 assert(a_zoneTempDir != (char *)NULL);
2887 assert(*a_zoneTempDir != '\0');
2888
2889 /* entry debugging info */
2890
2891 echoDebug(DBG_CREATE_ZONE_ADMINFILE, a_zoneTempDir, PSTR(a_admnfile));
2892
2893 /* if temporary name already exists, do not overwrite */
2894
2895 if (*r_zoneAdminFile != (char *)NULL) {
2896 return;
2897 }
2898
2899 /* create temporary name */
2900
2901 *r_zoneAdminFile = tempnam(a_zoneTempDir, "zadmn");
2902 b = z_create_zone_admin_file(*r_zoneAdminFile, a_admnfile);
2903 if (b == B_FALSE) {
2904 progerr(ERR_CREATE_TMPADMIN, *r_zoneAdminFile,
2905 strerror(errno));
2906 quit(1);
2907 /* NOTREACHED */
2908 }
2909
2910 echoDebug(DBG_CREATED_ZONE_ADMINFILE, *r_zoneAdminFile);
2911 }
2912
2913 /*
2914 * Name: create_zone_tempdir
2915 * Description: Given a system temporary directory, create a "zone" specific
2916 * temporary directory and return the path to the directory
2917 * created.
2918 * Arguments: r_zoneTempDir - pointer to handle that will contain a
2919 * string representing the path to the temporary
2920 * directory created - this must be NULL before the
2921 * first call to this function - on subsequent calls
2922 * if the pointer is NOT null then the existing string
2923 * will NOT be overwritten.
2924 * a_zoneTempDir - pointer to string representing the path
2925 * to the system temporary directory to create the
2926 * temporary zone directory in
2927 * Returns: void
2928 * NOTE: Any string returned is placed in new storage for the
2929 * calling method. The caller must use 'free' to dispose
2930 * of the storage once the string is no longer needed.
2931 * NOTE: On any error this function will call 'quit(1)'
2932 * NOTE: This function calls "quitSetZoneTmpdir" on success to
2933 * register the directory created with quit() so that the
2934 * directory will be automatically deleted on exit.
2935 */
2936
2937 static void
create_zone_tempdir(char ** r_zoneTempDir,char * a_tmpdir)2938 create_zone_tempdir(char **r_zoneTempDir, char *a_tmpdir)
2939 {
2940 boolean_t b;
2941
2942 /* entry assertions */
2943
2944 assert(r_zoneTempDir != (char **)NULL);
2945 assert(a_tmpdir != (char *)NULL);
2946 assert(*a_tmpdir != '\0');
2947
2948 /* entry debugging info */
2949
2950 echoDebug(DBG_CREATE_ZONE_TEMPDIR, a_tmpdir);
2951
2952 /* if temporary directory already exists, do not overwrite */
2953
2954 if (*r_zoneTempDir != (char *)NULL) {
2955 return;
2956 }
2957
2958 /* create temporary directory */
2959
2960 b = setup_temporary_directory(r_zoneTempDir, a_tmpdir, "ztemp");
2961 if (b == B_FALSE) {
2962 progerr(ERR_ZONETEMPDIR, a_tmpdir, strerror(errno));
2963 quit(1);
2964 /* NOTREACHED */
2965 }
2966
2967 /* register with quit() so directory is removed on exit */
2968
2969 quitSetZoneTmpdir(*r_zoneTempDir);
2970
2971 /* exit debugging info */
2972
2973 echoDebug(DBG_CREATED_ZONE_TEMPDIR, *r_zoneTempDir);
2974 }
2975
2976 /*
2977 * Name: continue_installation
2978 * Description: Called from within a loop that is installing packages,
2979 * this function examines various global variables and decides
2980 * whether or not to ask an appropriate question, and wait for
2981 * and appropriate reply.
2982 * Arguments: <<global variables>>
2983 * Returns: B_TRUE - continue processing with next package
2984 * B_FALSE - do not continue processing with next package
2985 */
2986
2987 static boolean_t
continue_installation(void)2988 continue_installation(void)
2989 {
2990 char ans[MAX_INPUT];
2991 int n;
2992
2993 /* return TRUE if not interrupted */
2994
2995 if (!interrupted) {
2996 return (B_TRUE);
2997 }
2998
2999 /*
3000 * process interrupted - determine whether or not to continue
3001 */
3002
3003 /* output appropriate interrupted message */
3004
3005 if (askflag) {
3006 echo(npkgs == 1 ? MSG_1MORE_PROC : MSG_MORE_PROC, npkgs);
3007 } else {
3008 echo(npkgs == 1 ? MSG_1MORE_INST : MSG_MORE_INST, npkgs);
3009 }
3010
3011 /* if running with no interaction (-n) do not ask question */
3012
3013 if (nointeract) {
3014 /* if admin required return 'dont continue' */
3015 if (needconsult) {
3016 return (B_FALSE);
3017 }
3018 ckquit = 1;
3019 return (B_TRUE);
3020 }
3021
3022 /* interaction possible: ask question */
3023
3024 ckquit = 0;
3025 n = ckyorn(ans, NULL, NULL, NULL, ASK_CONTINUE_ADD);
3026 if (n != 0) {
3027 quit(n);
3028 /* NOTREACHED */
3029 }
3030 ckquit = 1;
3031 if (strchr("yY", *ans) == NULL) {
3032 return (B_FALSE);
3033 }
3034 return (B_TRUE);
3035 }
3036
3037 /*
3038 * package can be in a number of formats:
3039 * - file containing package stream (pkgadd -d file [pkgs])
3040 * - directory containing packages (pkgadd -d /dir [pkgs])
3041 * - device containing packages (pkgadd -d diskette1 [pkgs])
3042 * non-global zones can be passed open files and strings as arguments
3043 * - for file containing package stream
3044 * -- the stream can be passed directly to the non-global zone
3045 * - for directory
3046 * -- convert packages to datastream to pass to the non-global zone
3047 * - for device
3048 * -- ?
3049 */
3050
3051 static boolean_t
unpack_and_check_packages(char ** a_pkgList,char * a_idsName,char * a_packageDir)3052 unpack_and_check_packages(char **a_pkgList, char *a_idsName, char *a_packageDir)
3053 {
3054 int savenpkgs = npkgs;
3055 int i;
3056 CAF_T flags = 0;
3057
3058 /* entry assertions */
3059
3060 assert(a_pkgList != (char **)NULL);
3061
3062 /* entry debugging info */
3063
3064 echoDebug(DBG_UNPACKCHECK_ENTRY);
3065 echoDebug(DBG_UNPACKCHECK_ARGS, PSTR(a_idsName), PSTR(a_packageDir));
3066
3067 /*
3068 * set flags for applicability check
3069 */
3070
3071 /* determine if running in the global zone */
3072
3073 if (z_running_in_global_zone() == B_TRUE) {
3074 flags |= CAF_IN_GLOBAL_ZONE;
3075 }
3076
3077 /* set -G flag */
3078
3079 if (globalZoneOnly == B_TRUE) {
3080 flags |= CAF_SCOPE_GLOBAL;
3081 }
3082
3083 /*
3084 * for each package to install:
3085 * - if packages from datastream, unpack package into package dir
3086 * - check applicability of installing package on this system/zone
3087 */
3088
3089 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3090 if (a_idsName != (char *)NULL) {
3091 /* create stream out of package if not already one */
3092 if (unpack_package_from_stream(a_idsName, pkginst,
3093 a_packageDir) == B_FALSE) {
3094 progerr(ERR_CANNOT_UNPACK_PKGSTRM,
3095 PSTR(pkginst), PSTR(a_idsName),
3096 PSTR(a_packageDir));
3097
3098 npkgs = savenpkgs;
3099 return (B_FALSE);
3100 }
3101 } else {
3102 echoDebug(DBG_PKG_IN_DIR, pkginst, a_packageDir);
3103 }
3104
3105 /* check package applicability */
3106 if (check_applicability(a_packageDir,
3107 pkginst, get_inst_root(), flags) == B_FALSE) {
3108 progerr(ERR_PKG_NOT_INSTALLABLE, pkginst);
3109 npkgs = savenpkgs;
3110 return (B_FALSE);
3111 }
3112 npkgs--;
3113 }
3114
3115 npkgs = savenpkgs;
3116 return (B_TRUE);
3117 }
3118
3119 /*
3120 * returns:
3121 * B_TRUE - package list generated
3122 * B_FALSE - failed to generate package list
3123 * Will call quit(n) on fatal error.
3124 */
3125
3126 static boolean_t
get_package_list(char *** r_pkgList,char ** a_argv,char * a_categories,char ** a_categoryList,int a_ignoreSignatures,PKG_ERR * a_err,ushort_t a_httpProxyPort,char * a_httpProxyName,keystore_handle_t a_keystore,char * a_keystoreFile,char * a_idsName,int * r_repeat)3127 get_package_list(char ***r_pkgList, char **a_argv, char *a_categories,
3128 char **a_categoryList, int a_ignoreSignatures, PKG_ERR *a_err,
3129 ushort_t a_httpProxyPort, char *a_httpProxyName,
3130 keystore_handle_t a_keystore, char *a_keystoreFile,
3131 char *a_idsName, int *r_repeat)
3132 {
3133 int n;
3134 url_hport_t *proxytmp = NULL;
3135
3136 /* entry assertions */
3137
3138 assert(r_repeat != (int *)NULL);
3139
3140 /* entry debugging info */
3141
3142 echoDebug(DBG_GETPKGLIST_ENTRY);
3143 echoDebug(DBG_GETPKGLIST_ARGS, PSTR(a_idsName), PSTR(pkgdev.dirname),
3144 *r_repeat);
3145
3146 /*
3147 * get the list of the packages to add
3148 */
3149
3150 n = pkgGetPackageList(r_pkgList, a_argv, optind, a_categories,
3151 a_categoryList, &pkgdev);
3152
3153 switch (n) {
3154 case -1: /* no packages found */
3155 echoDebug(DBG_PKGLIST_NONFOUND, PSTR(a_idsName),
3156 pkgdev.dirname);
3157 return (B_FALSE);
3158
3159 case 0: /* packages found */
3160 break;
3161
3162 default: /* "quit" error */
3163 echoDebug(DBG_PKGLIST_ERROR, PSTR(a_idsName),
3164 pkgdev.dirname, n);
3165 quit(n);
3166 /* NOTREACHED */
3167 }
3168
3169 /*
3170 * If we are not ignoring signatures, check the package's
3171 * signature if one exists. pkgask doesn't care about
3172 * signatures though.
3173 */
3174 if (!askflag && !a_ignoreSignatures && a_idsName &&
3175 (web_ck_authentication() == AUTH_QUIT)) {
3176
3177 PKCS7 *sig = NULL;
3178 STACK_OF(X509) *cas = NULL;
3179
3180 /* Retrieve signature */
3181 if (!get_signature(a_err, a_idsName, &pkgdev, &sig)) {
3182 pkgerr(a_err);
3183 web_cleanup();
3184 quit(1);
3185 /* NOTREACHED */
3186 }
3187
3188 if (sig != NULL) {
3189 /* Found signature. Verify. */
3190 if (a_httpProxyName != NULL) {
3191 /* Proxy will be needed for OCSP */
3192 proxytmp = malloc(sizeof (url_hport_t));
3193 if (url_parse_hostport(a_httpProxyName,
3194 proxytmp, a_httpProxyPort)
3195 != URL_PARSE_SUCCESS) {
3196 progerr(ERR_PROXY,
3197 a_httpProxyName);
3198 PKCS7_free(sig);
3199 quit(99);
3200 /* NOTREACHED */
3201 }
3202 }
3203
3204 /* Start with fresh error stack */
3205 pkgerr_clear(a_err);
3206
3207 if (a_keystore == NULL) {
3208 /* keystore not opened - open it */
3209 if (open_keystore(a_err, a_keystoreFile,
3210 get_prog_name(), pkg_passphrase_cb,
3211 KEYSTORE_DFLT_FLAGS,
3212 &a_keystore) != 0) {
3213 pkgerr(a_err);
3214 web_cleanup();
3215 PKCS7_free(sig);
3216 quit(1);
3217 /* NOTREACHED */
3218 }
3219 }
3220
3221 /* get trusted CA certs */
3222 if (find_ca_certs(a_err, a_keystore, &cas) != 0) {
3223 pkgerr(a_err);
3224 PKCS7_free(sig);
3225 web_cleanup();
3226 quit(1);
3227 /* NOTREACHED */
3228 }
3229
3230 /* Verify signature */
3231 if (!ds_validate_signature(a_err, &pkgdev,
3232 &a_argv[optind], a_idsName, sig,
3233 cas, proxytmp, nointeract)) {
3234 pkgerr(a_err);
3235 quit(99);
3236 /* NOTREACHED */
3237 }
3238
3239 /* cleanup */
3240 PKCS7_free(sig);
3241 web_cleanup();
3242 pkgerr_free(a_err);
3243 }
3244 }
3245
3246 /* order package list if input data stream specified */
3247
3248 if (a_idsName) {
3249 ds_order(*r_pkgList);
3250 }
3251
3252 return (B_TRUE);
3253 }
3254
3255 /*
3256 * Name: install_in_one_zone
3257 * Description: Install a single package in a single zone
3258 * Arguments: a_zoneName - pointer to string representing the name of the
3259 * zone to install the package into.
3260 * a_idsName - pointer to string representing the data stream
3261 * device (input data stream) containing the package to
3262 * be installed.
3263 * If this is == NULL the package is assumed to be
3264 * spooled in the zone temporary directory.
3265 * a_zoneAdminFile - pointer to string representing the admin
3266 * file to pass to pkginstall when installing the package.
3267 * If this is == NULL no admin file is given to pkginstall.
3268 * a_zoneTempDir - pointer to string representing the temporary
3269 * directory in which spooled packages can be found if
3270 * a_idsName is == NULL.
3271 * a_altBinDir - pointer to string representing an alternative
3272 * binary location directory to pass to pkginstall.
3273 * If this is == NULL no alternative binary location is
3274 * passed to pkginstall.
3275 * a_scratchName - pointer to string representing the name of the
3276 * scratch zone to use for installation.
3277 * a_zoneState - state of the zone; must be mounted or running.
3278 * a_tmpzn - B_TRUE when this zone is booted by the package
3279 * command or B_FALSE if it was running before.
3280 * Returns: void
3281 * NOTE: As a side effect, "ckreturn" is called on the result returned
3282 * from running 'pkginstall' in the zone; this sets several global
3283 * variables which allows the caller to determine the result of
3284 * the installation operation.
3285 */
3286
3287 static void
install_in_one_zone(char * a_zoneName,char * a_idsName,char * a_zoneAdminFile,char * a_zoneTempDir,char * a_altBinDir,zone_state_t a_zoneState,boolean_t a_tmpzn)3288 install_in_one_zone(char *a_zoneName, char *a_idsName,
3289 char *a_zoneAdminFile, char *a_zoneTempDir,
3290 char *a_altBinDir, zone_state_t a_zoneState, boolean_t a_tmpzn)
3291 {
3292 char zoneStreamName[PATH_MAX] = {'\0'};
3293 int n;
3294
3295 /* entry assertions */
3296
3297 assert(a_zoneName != (char *)NULL);
3298 assert(*a_zoneName != '\0');
3299
3300 /* entry debugging info */
3301
3302 echoDebug(DBG_INSTINONEZONE_ENTRY);
3303 echoDebug(DBG_INSTINONEZONE_ARGS, a_zoneName, PSTR(a_idsName),
3304 PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir),
3305 PSTR(a_altBinDir));
3306
3307 /* echo operation to perform to stdout */
3308
3309 echo(MSG_INSTALL_PKG_IN_ZONE, pkginst, a_zoneName);
3310
3311 /* determine path to the package stream */
3312
3313 if (a_idsName == (char *)NULL) {
3314 /* locate temp stream created earlier */
3315 (void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3316 "%s/%s.dstream", a_zoneTempDir, pkginst);
3317 } else {
3318 /* use stream passed in on command line */
3319 (void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3320 "%s", a_idsName);
3321 }
3322
3323 echoDebug(DBG_INSTALL_IN_ZONE, pkginst, a_zoneName, zoneStreamName);
3324
3325 n = pkgZoneInstall(a_zoneName, a_zoneState, zoneStreamName,
3326 a_altBinDir, a_zoneAdminFile, a_tmpzn);
3327
3328 /* set success/fail condition variables */
3329
3330 ckreturn(n);
3331
3332 /* exit debugging info */
3333
3334 echoDebug(DBG_INSTALL_FLAG_VALUES, "after install", admnflag, doreboot,
3335 failflag, interrupted, intrflag, ireboot, needconsult,
3336 nullflag, warnflag);
3337 }
3338
3339 /*
3340 * Name: install_in_zones
3341 * Description: Install a single package in the zones that are running from
3342 * a list of zones
3343 * Arguments: a_zlst - list of zones to install the package into
3344 * a_idsName - pointer to string representing the data stream
3345 * device (input data stream) containing the package to
3346 * be installed.
3347 * If this is == NULL the package is assumed to be
3348 * spooled in the zone temporary directory.
3349 * a_altBinDir - pointer to string representing an alternative
3350 * binary location directory to pass to pkginstall.
3351 * If this is == NULL no alternative binary location is
3352 * passed to pkginstall.
3353 * a_zoneAdminFile - pointer to string representing the admin
3354 * file to pass to pkginstall when installing the package.
3355 * If this is == NULL no admin file is given to pkginstall.
3356 * a_zoneTempDir - pointer to string representing the temporary
3357 * directory in which spooled packages can be found if
3358 * a_idsName is == NULL.
3359 */
3360
3361 static int
install_in_zones(zoneList_t a_zlst,char * a_idsName,char * a_altBinDir,char * a_zoneAdminFile,char * a_zoneTempDir)3362 install_in_zones(zoneList_t a_zlst, char *a_idsName, char *a_altBinDir,
3363 char *a_zoneAdminFile, char *a_zoneTempDir)
3364 {
3365 char *zoneName;
3366 int zoneIndex;
3367 int zonesSkipped = 0;
3368 zone_state_t zst;
3369
3370 /* entry assertions */
3371
3372 assert(a_zlst != (zoneList_t)NULL);
3373
3374 /* entry debugging info */
3375
3376 echoDebug(DBG_INSTALLINZONES_ENTRY);
3377 echoDebug(DBG_INSTALLINZONES_ARGS, PSTR(a_idsName),
3378 PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir));
3379
3380 /* process each zone in the list */
3381
3382 for (zoneIndex = 0;
3383 (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3384 zoneIndex++) {
3385
3386 /* skip the zone if it is NOT running */
3387
3388 zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3389 if (zst != ZONE_STATE_RUNNING && zst != ZONE_STATE_MOUNTED) {
3390 zonesSkipped++;
3391 echoDebug(DBG_SKIPPING_ZONE, zoneName);
3392 continue;
3393 }
3394
3395 /* install the package in this zone */
3396
3397 install_in_one_zone(z_zlist_get_scratch(a_zlst, zoneIndex),
3398 a_idsName, a_zoneAdminFile, a_zoneTempDir, a_altBinDir,
3399 zst, B_FALSE);
3400 }
3401
3402 return (zonesSkipped);
3403 }
3404
3405 /*
3406 * Name: boot_and_install_in_zones
3407 * Description: Install a single package in the zones that are NOT running from
3408 * a list of zones - each zone is booted, the package installed,
3409 * and the zone is halted
3410 * Arguments: a_zlst - list of zones to install the package into
3411 * a_idsName - pointer to string representing the data stream
3412 * device (input data stream) containing the package to
3413 * be installed.
3414 * If this is == NULL the package is assumed to be
3415 * spooled in the zone temporary directory.
3416 * a_altBinDir - pointer to string representing an alternative
3417 * binary location directory to pass to pkginstall.
3418 * If this is == NULL no alternative binary location is
3419 * passed to pkginstall.
3420 * a_zoneAdminFile - pointer to string representing the admin
3421 * file to pass to pkginstall when installing the package.
3422 * If this is == NULL no admin file is given to pkginstall.
3423 * a_zoneTempDir - pointer to string representing the temporary
3424 * directory in which spooled packages can be found if
3425 * a_idsName is == NULL.
3426 */
3427
3428 static int
boot_and_install_in_zones(zoneList_t a_zlst,char * a_idsName,char * a_altBinDir,char * a_zoneAdminFile,char * a_zoneTempDir)3429 boot_and_install_in_zones(zoneList_t a_zlst, char *a_idsName, char *a_altBinDir,
3430 char *a_zoneAdminFile, char *a_zoneTempDir)
3431 {
3432 boolean_t b;
3433 char *zoneName;
3434 int zoneIndex;
3435 int zonesSkipped = 0;
3436 zone_state_t zst;
3437
3438 /* entry assertions */
3439
3440 assert(a_zlst != (zoneList_t)NULL);
3441
3442 /* entry debugging info */
3443
3444 echoDebug(DBG_BOOTINSTALLINZONES_ENTRY);
3445 echoDebug(DBG_BOOTINSTALLINZONES_ARGS, PSTR(a_idsName),
3446 PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir));
3447
3448 /* process each zone in the list */
3449
3450 for (zoneIndex = 0;
3451 (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3452 zoneIndex++) {
3453
3454 /* skip the zone if it IS running */
3455
3456 zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3457 if (zst == ZONE_STATE_RUNNING || zst == ZONE_STATE_MOUNTED) {
3458 echoDebug(DBG_SKIPPING_ZONE_BOOT, zoneName);
3459 continue;
3460 }
3461
3462 /* skip the zone if it is NOT bootable */
3463
3464 if (z_zlist_is_zone_runnable(a_zlst, zoneIndex) == B_FALSE) {
3465 echo(MSG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3466 echoDebug(DBG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3467 continue;
3468 }
3469
3470 /* mount up the zone */
3471
3472 echo(MSG_BOOTING_ZONE, zoneName);
3473 echoDebug(DBG_BOOTING_ZONE, zoneName);
3474
3475 b = z_zlist_change_zone_state(a_zlst, zoneIndex,
3476 ZONE_STATE_MOUNTED);
3477 if (b == B_FALSE) {
3478 progerr(ERR_CANNOT_BOOT_ZONE, zoneName);
3479 /* set fatal error return condition */
3480 ckreturn(1);
3481 zonesSkipped++;
3482 continue;
3483 }
3484
3485 /* install the package in this zone */
3486
3487 install_in_one_zone(z_zlist_get_scratch(a_zlst, zoneIndex),
3488 a_idsName, a_zoneAdminFile, a_zoneTempDir, a_altBinDir,
3489 ZONE_STATE_MOUNTED, B_TRUE);
3490
3491 /* restore original state of zone */
3492
3493 echo(MSG_RESTORE_ZONE_STATE, zoneName);
3494 echoDebug(DBG_RESTORE_ZONE_STATE, zoneName);
3495
3496 b = z_zlist_restore_zone_state(a_zlst, zoneIndex);
3497 }
3498
3499 return (zonesSkipped);
3500 }
3501
3502 /*
3503 * Name: pkginstall_check_in_one_zone
3504 * Description: Do a pre install check of a single package in a single zone
3505 * Arguments: a_zoneName - pointer to string representing the name of the
3506 * zone to check install the package in.
3507 * a_idsName - pointer to string representing the data stream
3508 * device (input data stream) containing the package to
3509 * be check installed.
3510 * If this is == NULL the package is assumed to be
3511 * spooled in the zone temporary directory.
3512 * a_zoneAdminFile - pointer to string representing the admin
3513 * file to pass to pkginstall when installing the package.
3514 * If this is == NULL no admin file is given to pkginstall.
3515 * a_zoneTempDir - pointer to string representing the temporary
3516 * directory in which spooled packages can be found if
3517 * a_idsName is == NULL.
3518 * a_altBinDir - pointer to string representing an alternative
3519 * binary location directory to pass to pkginstall.
3520 * If this is == NULL no alternative binary location is
3521 * passed to pkginstall.
3522 * a_scratchName - pointer to string representing the name of the
3523 * scratch zone to use for installation.
3524 * a_zoneState - state of the zone; must be mounted or running.
3525 * a_tmpzn - B_TRUE when this zone is booted by the package
3526 * command or B_FALSE if it was running before.
3527 * Returns: void
3528 * NOTE: As a side effect, "ckreturn" is called on the result returned
3529 * from running 'pkginstall' in the zone; this sets several global
3530 * variables which allows the caller to determine the result of
3531 * the pre installation check operation.
3532 */
3533
3534 static void
pkginstall_check_in_one_zone(char * a_zoneName,char * a_idsName,char * a_zoneAdminFile,char * a_zoneTempDir,char * a_altBinDir,char * a_scratchName,zone_state_t a_zoneState,boolean_t a_tmpzn)3535 pkginstall_check_in_one_zone(char *a_zoneName,
3536 char *a_idsName, char *a_zoneAdminFile, char *a_zoneTempDir,
3537 char *a_altBinDir, char *a_scratchName, zone_state_t a_zoneState,
3538 boolean_t a_tmpzn)
3539 {
3540 char preinstallcheckPath[PATH_MAX+1];
3541 char zoneStreamName[PATH_MAX] = {'\0'};
3542 int n;
3543
3544 echo(MSG_CHECKINSTALL_PKG_IN_ZONE, pkginst, a_zoneName);
3545 echoDebug(MSG_CHECKINSTALL_PKG_IN_ZONE, pkginst, a_zoneName);
3546
3547 (void) snprintf(preinstallcheckPath, sizeof (preinstallcheckPath),
3548 "%s/%s.%s.preinstallcheck.txt", a_zoneTempDir, pkginst,
3549 a_zoneName);
3550
3551 if (a_idsName == (char *)NULL) {
3552 /* locate temporary stream created earlier */
3553 (void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3554 "%s/%s.dstream", a_zoneTempDir, pkginst);
3555 } else {
3556 (void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3557 "%s", a_idsName);
3558 }
3559
3560 echoDebug(DBG_CHECKINSTALL_IN_ZONE, pkginst, a_zoneName,
3561 zoneStreamName);
3562
3563 n = pkgZoneCheckInstall(a_scratchName, a_zoneState, zoneStreamName,
3564 a_altBinDir, a_zoneAdminFile, preinstallcheckPath, a_tmpzn);
3565
3566 /* set success/fail condition variables */
3567
3568 ckreturn(n);
3569
3570 echoDebug(DBG_INSTALL_FLAG_VALUES, "after preinstall check",
3571 admnflag, doreboot, failflag, interrupted, intrflag,
3572 ireboot, needconsult, nullflag, warnflag);
3573 }
3574
3575 /*
3576 * Name: pkginstall_check_in_zones
3577 * Description: Check installation of a single package in the zones that
3578 * are running from a list of zones
3579 * Arguments: a_zlst - list of zones to check install the package
3580 * a_idsName - pointer to string representing the data stream
3581 * device (input data stream) containing the package to
3582 * be check installed.
3583 * If this is == NULL the package is assumed to be
3584 * spooled in the zone temporary directory.
3585 * a_altBinDir - pointer to string representing an alternative
3586 * binary location directory to pass to pkginstall.
3587 * If this is == NULL no alternative binary location is
3588 * passed to pkginstall.
3589 * a_zoneAdminFile - pointer to string representing the admin
3590 * file to pass to pkginstall when checking the installing
3591 * of the package.
3592 * If this is == NULL no admin file is given to pkginstall.
3593 * a_zoneTempDir - pointer to string representing the temporary
3594 * directory in which spooled packages can be found if
3595 * a_idsName is == NULL.
3596 */
3597
3598 static int
pkginstall_check_in_zones(zoneList_t a_zlst,char * a_idsName,char * a_altBinDir,char * a_zoneAdminFile,char * a_zoneTempDir)3599 pkginstall_check_in_zones(zoneList_t a_zlst, char *a_idsName, char *a_altBinDir,
3600 char *a_zoneAdminFile, char *a_zoneTempDir)
3601 {
3602 char *zoneName;
3603 int zoneIndex;
3604 int zonesSkipped = 0;
3605 zone_state_t zst;
3606
3607 for (zoneIndex = 0;
3608 (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3609 zoneIndex++) {
3610
3611 zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3612 if (zst != ZONE_STATE_RUNNING && zst != ZONE_STATE_MOUNTED) {
3613 zonesSkipped++;
3614 echoDebug(DBG_SKIPPING_ZONE, zoneName);
3615 continue;
3616 }
3617
3618 pkginstall_check_in_one_zone(zoneName, a_idsName,
3619 a_zoneAdminFile, a_zoneTempDir, a_altBinDir,
3620 z_zlist_get_scratch(a_zlst, zoneIndex), zst, B_FALSE);
3621 }
3622
3623 return (zonesSkipped);
3624 }
3625
3626 /*
3627 * Name: boot_and_pkginstall_check_in_zones
3628 * Description: Check installation of a single package in the zones that
3629 * are NOT running from a list of zones - each zone is booted,
3630 * the package installation is checked, and the zone is halted.
3631 * Arguments: a_zlst - list of zones to install the package into
3632 * a_idsName - pointer to string representing the data stream
3633 * device (input data stream) containing the package to
3634 * be check installed.
3635 * If this is == NULL the package is assumed to be
3636 * spooled in the zone temporary directory.
3637 * a_altBinDir - pointer to string representing an alternative
3638 * binary location directory to pass to pkginstall.
3639 * If this is == NULL no alternative binary location is
3640 * passed to pkginstall.
3641 * a_zoneAdminFile - pointer to string representing the admin
3642 * file to pass to pkginstall when check installing the
3643 * package.
3644 * If this is == NULL no admin file is given to pkginstall.
3645 * a_zoneTempDir - pointer to string representing the temporary
3646 * directory in which spooled packages can be found if
3647 * a_idsName is == NULL.
3648 */
3649
3650 static int
boot_and_pkginstall_check_in_zones(zoneList_t a_zlst,char * a_idsName,char * a_altBinDir,char * a_zoneAdminFile,char * a_zoneTempDir)3651 boot_and_pkginstall_check_in_zones(zoneList_t a_zlst, char *a_idsName,
3652 char *a_altBinDir, char *a_zoneAdminFile, char *a_zoneTempDir)
3653 {
3654 int zoneIndex;
3655 int zonesSkipped = 0;
3656 char *zoneName;
3657 boolean_t b;
3658 zone_state_t zst;
3659
3660 /* entry assertions */
3661
3662 assert(a_zlst != (zoneList_t)NULL);
3663
3664 /* entry debugging info */
3665
3666 echoDebug(DBG_BOOTCHECKINSTALLINZONES_ENTRY);
3667 echoDebug(DBG_BOOTCHECKINSTALLINZONES_ARGS, PSTR(a_idsName),
3668 PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir));
3669
3670 /* process each zone in the list */
3671
3672 for (zoneIndex = 0;
3673 (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3674 zoneIndex++) {
3675
3676 /* skip the zone if it IS running */
3677
3678 zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3679 if (zst == ZONE_STATE_RUNNING || zst == ZONE_STATE_MOUNTED) {
3680 echoDebug(DBG_SKIPPING_ZONE_BOOT, zoneName);
3681 continue;
3682 }
3683
3684 /* skip the zone if it is NOT bootable */
3685
3686 if (z_zlist_is_zone_runnable(a_zlst, zoneIndex) == B_FALSE) {
3687 echo(MSG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3688 echoDebug(DBG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3689 continue;
3690 }
3691
3692 /* mount up the zone */
3693
3694 echo(MSG_BOOTING_ZONE, zoneName);
3695 echoDebug(DBG_BOOTING_ZONE, zoneName);
3696
3697 b = z_zlist_change_zone_state(a_zlst, zoneIndex,
3698 ZONE_STATE_MOUNTED);
3699 if (b == B_FALSE) {
3700 progerr(ERR_CANNOT_BOOT_ZONE, zoneName);
3701 /* set fatal error return condition */
3702 ckreturn(1);
3703 zonesSkipped++;
3704 continue;
3705 }
3706
3707 /* pre-installation check of the package in this zone */
3708
3709 pkginstall_check_in_one_zone(zoneName, a_idsName,
3710 a_zoneAdminFile, a_zoneTempDir, a_altBinDir,
3711 z_zlist_get_scratch(a_zlst, zoneIndex),
3712 ZONE_STATE_MOUNTED, B_TRUE);
3713
3714 /* restore original state of zone */
3715
3716 echo(MSG_RESTORE_ZONE_STATE, zoneName);
3717 echoDebug(DBG_RESTORE_ZONE_STATE, zoneName);
3718
3719 b = z_zlist_restore_zone_state(a_zlst, zoneIndex);
3720 }
3721
3722 return (zonesSkipped);
3723 }
3724
3725 /*
3726 * Function: add_packages_in_global_with_zones
3727 * Description: call this function to add a list of packages in the global zone
3728 * when one or more non-global zones exist
3729 * returns:
3730 * B_TRUE to process next data stream
3731 * B_FALSE to exit
3732 */
3733
3734 static boolean_t
add_packages_in_global_with_zones(char ** a_pkgList,char * a_uri,char * a_idsName,int a_repeat,char * a_altBinDir,char * a_device,zoneList_t a_zlst)3735 add_packages_in_global_with_zones(char **a_pkgList, char *a_uri,
3736 char *a_idsName, int a_repeat, char *a_altBinDir,
3737 char *a_device, zoneList_t a_zlst)
3738 {
3739 static char *zoneTempDir = (char *)NULL;
3740 static char *zoneAdminFile = (char *)NULL;
3741
3742 boolean_t b;
3743 char *packageDir;
3744 char instdir[PATH_MAX];
3745 char respfile_path[PATH_MAX];
3746 char zoneStreamName[PATH_MAX] = {'\0'};
3747 int i;
3748 int n;
3749 int savenpkgs = npkgs;
3750 int zonesSkipped;
3751 boolean_t globalPresent;
3752
3753 /* entry assertions */
3754
3755 assert(a_pkgList != (char **)NULL);
3756 assert(a_zlst != (zoneList_t)NULL);
3757
3758 echoDebug(DBG_ADDPACKAGES_GZ_W_LZ_ENTRY);
3759 echoDebug(DBG_ADDPACKAGES_GZ_W_LZ_ARGS, npkgs, PSTR(a_uri),
3760 PSTR(a_idsName), a_repeat, PSTR(a_device));
3761
3762 /* create temporary directory for use by zone operations */
3763
3764 create_zone_tempdir(&zoneTempDir, tmpdir);
3765
3766 /* create hands off settings admin file for use in a non-global zone */
3767
3768 create_zone_adminfile(&zoneAdminFile, zoneTempDir, admnfile);
3769
3770 /* determine directory where packages can be found */
3771
3772 if (a_idsName == (char *)NULL) {
3773 /* no stream - directory containing packages provided */
3774 packageDir = pkgdev.dirname;
3775 } else {
3776 packageDir = zoneTempDir;
3777 }
3778
3779 /* unpack and check all packages */
3780
3781 b = unpack_and_check_packages(a_pkgList, a_idsName, packageDir);
3782 if (b != B_TRUE) {
3783 quit(1);
3784 }
3785
3786 /*
3787 * if the packages are contained in a directory, convert the
3788 * packages into individual streams because pkgZoneInstall is only able
3789 * to pass a stream to the non-global zone's pkginstall command.
3790 * After this code is executed:
3791 * if the original input was a datastream:
3792 * -> that datastream has been unpacked into "instdir"
3793 * if the original input was a directory with packages in it:
3794 * -> those packages have been placed into a single datastream
3795 */
3796
3797 if (a_idsName == (char *)NULL) {
3798 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3799 char *pkgs[2];
3800
3801 /* package is not a stream - create one */
3802
3803 (void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3804 "%s/%s.dstream", zoneTempDir, pkginst);
3805
3806 echoDebug(DBG_CONVERTING_PKG, packageDir, pkginst,
3807 zoneStreamName);
3808
3809 /* set up list of packages to be this package only */
3810
3811 pkgs[0] = pkginst;
3812 pkgs[1] = (char *)NULL;
3813
3814 n = pkgtrans(packageDir, zoneStreamName, pkgs,
3815 PT_SILENT|PT_ODTSTREAM, NULL, NULL);
3816 if (n != 0) {
3817 progerr(ERR_CANNOT_CONVERT_PKGSTRM,
3818 pkginst, packageDir, zoneStreamName);
3819 quit(1);
3820 }
3821 npkgs--;
3822 }
3823 npkgs = savenpkgs;
3824 }
3825
3826 /*
3827 * Phase I - run collect dependency information for all packages for all
3828 * zones - this involves running pkginstall with the "preinstallcheck"
3829 * option which causes all dependency checks to be performed without
3830 * actually doing the installation of the packages. This information is
3831 * gathered in the zone temporary directory and is used later to present
3832 * the dependency check results to the system administrator depending
3833 * on the administration settings.
3834 */
3835
3836 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3837
3838 /* reset interrupted flag before calling pkginstall */
3839
3840 interrupted = 0; /* last action was NOT quit */
3841
3842 /*
3843 * if this package is marked "install in this zone only", then
3844 * do not check dependencies in any other zone
3845 */
3846
3847 if (pkgPackageIsThisZone(pkginst) == B_TRUE) {
3848 echoDebug(DBG_VERIFY_SKIP_THISZONE, pkginst);
3849 npkgs--;
3850 continue;
3851 }
3852
3853 /*
3854 * if operation failed in global zone do not propagate
3855 * to any non-global zones
3856 */
3857
3858 if (interrupted != 0) {
3859 echo(MSG_CHECKINSTALL_INTERRUPT_B4_Z, pkginst);
3860 echoDebug(MSG_CHECKINSTALL_INTERRUPT_B4_Z, pkginst);
3861 break;
3862 }
3863
3864 echoDebug(DBG_INSTALL_FLAG_VALUES, "after pkginstall",
3865 admnflag, doreboot, failflag, interrupted, intrflag,
3866 ireboot, needconsult, nullflag, warnflag);
3867
3868 /*
3869 * call pkginstall to verify this package for all non-global
3870 * zones that are currently booted
3871 */
3872
3873 zonesSkipped = pkginstall_check_in_zones(a_zlst, a_idsName,
3874 a_altBinDir, admnfile, zoneTempDir);
3875
3876 /*
3877 * if any zones were skipped (becuase they are not currently
3878 * booted), boot each zone one at a time and call pkginstall
3879 * to verify this package for each such non-global zone
3880 */
3881
3882 if (zonesSkipped > 0) {
3883 echoDebug(DBG_ZONES_SKIPPED, zonesSkipped);
3884
3885 zonesSkipped =
3886 boot_and_pkginstall_check_in_zones(a_zlst,
3887 a_idsName, a_altBinDir, admnfile,
3888 zoneTempDir);
3889
3890 if (zonesSkipped > 0) {
3891 progerr(ERR_INSTALL_ZONES_SKIPPED,
3892 zonesSkipped);
3893 }
3894 }
3895
3896 npkgs--;
3897 }
3898
3899 /*
3900 * At this point, all of the dependency information has been gathered
3901 * and is ready to be analyzed. This function processes all of that
3902 * dependency information and presents the results to the system
3903 * administrator, depending on the current administration settings.
3904 */
3905
3906 i = preinstall_verify(a_pkgList, a_zlst, zoneTempDir);
3907 if (i != 0) {
3908 /* dependency checks failed - exit */
3909 quit(i);
3910 }
3911
3912 npkgs = savenpkgs;
3913
3914 /*
3915 * reset all error return condition variables that may have been
3916 * set during package installation dependency checking so that they
3917 * do not reflect on the success/failure of the actual package
3918 * installation operations
3919 */
3920
3921 resetreturn();
3922
3923 /*
3924 * At this point, all of the dependency checking is completed, and
3925 * the installation of the packages can proceed. Install each package
3926 * one at a time, starting with the global zone, and the for each
3927 * non-global zone that is booted, and then for each non-global zone
3928 * that is not currently booted.
3929 */
3930
3931 globalPresent = z_on_zone_spec(GLOBAL_ZONENAME);
3932
3933 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3934 /*
3935 * if immediate reboot required from last package and this is
3936 * not 'pkgask' then suspend installation of remaining packages
3937 */
3938
3939 if ((ireboot != 0) && (askflag == 0)) {
3940 ptext(stderr, MSG_SUSPEND_ADD, pkginst);
3941 continue;
3942 }
3943
3944 /*
3945 * handle interrupt if the previous pkginstall was interrupted
3946 */
3947
3948 if (continue_installation() == B_FALSE) {
3949 return (B_FALSE);
3950 }
3951
3952 /*
3953 * if pkgask, handle response file creation:
3954 * - if the response file is a directory, then create a path to
3955 * -- a package instance within the response file directory.
3956 * - If the response file is NOT a directory, if more than one
3957 * -- package is to be installed.
3958 */
3959
3960 if ((askflag != 0) && (respdir != (char *)NULL)) {
3961 (void) snprintf(respfile_path, sizeof (respfile_path),
3962 "%s/%s", respdir, pkginst);
3963 respfile = respfile_path;
3964 }
3965
3966 echo(MSG_PROC_INST, pkginst,
3967 (a_uri && a_idsName) ? a_uri : a_device);
3968
3969 /*
3970 * If we're installing another package in the same
3971 * session, the second through nth pkginstall, must
3972 * continue from where the prior one left off. For this
3973 * reason, the continuation feature (implied by the
3974 * nature of the command) is used for the remaining
3975 * packages.
3976 */
3977
3978 if ((i == 1) && (pkgdrtarg != (char *)NULL)) {
3979 pkgcontsrc = pkgdrtarg;
3980 }
3981
3982 if (globalPresent) {
3983 /*
3984 * call pkginstall for this package for the global zone
3985 */
3986
3987 echo(MSG_INSTALLING_PKG_IN_GZ, pkginst);
3988
3989 /* reset interrupted flag before calling pkginstall */
3990
3991 interrupted = 0; /* last action was NOT quit */
3992
3993 n = pkgInstall(get_inst_root(), NULL, packageDir,
3994 a_altBinDir);
3995
3996 /* set success/fail condition variables */
3997
3998 ckreturn(n);
3999
4000 /*
4001 * if operation failed in global zone do not propagate
4002 * to any non-global zones
4003 */
4004
4005 if (interrupted != 0) {
4006 echo(MSG_INSTALL_INTERRUPT_B4_ZONES, pkginst);
4007 echoDebug(MSG_INSTALL_INTERRUPT_B4_ZONES,
4008 pkginst);
4009 break;
4010 }
4011 }
4012
4013 /*
4014 * if this package is marked "install in this zone only",
4015 * then only need to install the package in the global zone;
4016 * skip installation in any non-global zones.
4017 */
4018
4019 if (pkgPackageIsThisZone(pkginst) == B_TRUE) {
4020 echoDebug(DBG_INSTALL_SKIP_THISZONE, pkginst);
4021 npkgs--;
4022 continue;
4023 }
4024
4025 echoDebug(DBG_INSTALL_FLAG_VALUES, "install in running zones",
4026 admnflag, doreboot, failflag, interrupted, intrflag,
4027 ireboot, needconsult, nullflag, warnflag);
4028
4029 /* install package in currently booted zones */
4030
4031 zonesSkipped = install_in_zones(a_zlst, a_idsName, a_altBinDir,
4032 zoneAdminFile, zoneTempDir);
4033
4034 /* install package in zones that are not currently booted */
4035
4036 if (zonesSkipped > 0) {
4037 echoDebug(DBG_ZONES_SKIPPED, zonesSkipped);
4038
4039 zonesSkipped = boot_and_install_in_zones(a_zlst,
4040 a_idsName, a_altBinDir, zoneAdminFile,
4041 zoneTempDir);
4042
4043 if (zonesSkipped > 0) {
4044 progerr(ERR_INSTALL_ZONES_SKIPPED,
4045 zonesSkipped);
4046 }
4047 }
4048
4049 /*
4050 * package completely installed - remove any temporary stream
4051 * of the package that might have been created
4052 */
4053
4054 if (a_idsName == (char *)NULL) {
4055 /* locate temporary stream created earlier */
4056 (void) snprintf(zoneStreamName, sizeof (zoneStreamName),
4057 "%s/%s.dstream", zoneTempDir, pkginst);
4058 /* remove stream - no longer needed */
4059 echoDebug(DBG_REMOVING_DSTREAM_PKGDIR, zoneStreamName,
4060 pkginst);
4061 (void) remove(zoneStreamName);
4062 } else {
4063 /* remove package - no longer needed */
4064 if (snprintf(instdir, sizeof (instdir), "%s/%s",
4065 zoneTempDir, pkginst) >= PATH_MAX) {
4066 progerr(ERR_CANNOT_CREATE_PKGPATH, tmpdir);
4067 quit(1);
4068 }
4069 echoDebug(DBG_REMOVING_PKG_TMPDIR, instdir, pkginst);
4070 (void) remove(instdir);
4071 }
4072
4073 /* decrement number of packages left to install */
4074
4075 npkgs--;
4076
4077 /*
4078 * if no packages left to install, unmount package source
4079 * device if appropriate
4080 */
4081
4082 if ((npkgs <= 0) && (pkgdev.mount || a_idsName)) {
4083 (void) chdir("/");
4084 if (!a_idsName) {
4085 echoDebug(DBG_UNMOUNTING_DEV,
4086 PSTR(pkgdev.mount));
4087 (void) pkgumount(&pkgdev);
4088 }
4089 }
4090 }
4091
4092 /*
4093 * all packages in the package list have been installed.
4094 * Continue with installation if:
4095 * -- immediate reboot is NOT required
4096 * -- there are more packages to install
4097 * -- the package source is a path to a file
4098 * else return do NOT continue.
4099 */
4100
4101 if ((ireboot == 0) && (a_repeat != 0) &&
4102 (pkgdev.pathname == (char *)NULL)) {
4103 return (B_TRUE);
4104 }
4105
4106 /* return 'dont continue' */
4107
4108 return (B_FALSE);
4109 }
4110
4111 /*
4112 * Function: add_packages_in_nonglobal_zone
4113 * Description: call this function to add a list of packages in a non-global
4114 * zone
4115 * returns:
4116 * B_TRUE to process next data stream
4117 * B_FALSE to exit
4118 */
4119
4120 static boolean_t
add_packages_in_nonglobal_zone(char ** a_pkgList,char * a_uri,char * a_idsName,int a_repeat,char * a_altBinDir,char * a_device)4121 add_packages_in_nonglobal_zone(char **a_pkgList, char *a_uri,
4122 char *a_idsName, int a_repeat, char *a_altBinDir, char *a_device)
4123 {
4124 static char *zoneTempDir = (char *)NULL;
4125
4126 char *packageDir;
4127 char respfile_path[PATH_MAX];
4128 int i;
4129 int n;
4130 boolean_t b;
4131 int savenpkgs = npkgs;
4132
4133 /* entry assertions */
4134
4135 assert(a_pkgList != (char **)NULL);
4136
4137 /* entry debugging info */
4138
4139 echoDebug(DBG_ADDPACKAGES_LZ_ENTRY);
4140 echoDebug(DBG_ADDPACKAGES_LZ_ARGS, npkgs, PSTR(a_uri), PSTR(a_idsName),
4141 a_repeat, PSTR(a_device));
4142
4143 /* create temporary directory for use by zone operations */
4144
4145 create_zone_tempdir(&zoneTempDir, tmpdir);
4146
4147 /*
4148 * package can be in a number of formats:
4149 * - file containing package stream (pkgadd -d file [pkgs])
4150 * - directory containing packages (pkgadd -d /dir [pkgs])
4151 * - device containing packages (pkgadd -d diskette1 [pkgs])
4152 * non-global zones can be passed open file drescriptors and
4153 * strings as arguments
4154 * - for file containing package stream
4155 * -- the stream can be passed directly to the non-global zone
4156 * - for directory
4157 * -- convert packages to datastream to pass to the non-global zone
4158 * - for device
4159 */
4160
4161 /* determine directory where packages can be found */
4162
4163 if (a_idsName == (char *)NULL) {
4164 /* no stream - directory containing packages provided */
4165 packageDir = pkgdev.dirname;
4166 } else {
4167 packageDir = zoneTempDir;
4168 }
4169
4170 b = unpack_and_check_packages(a_pkgList, a_idsName, packageDir);
4171 if (b != B_TRUE) {
4172 quit(1);
4173 }
4174
4175 /*
4176 * this is the main loop where all of the packages (as listed in the
4177 * package list) are added one at a time.
4178 */
4179
4180 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
4181 npkgs--;
4182 }
4183
4184 npkgs = savenpkgs;
4185
4186 /*
4187 * this is the main loop where all of the packages (as listed in the
4188 * package list) are added one at a time.
4189 */
4190
4191 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
4192 /*
4193 * if immediate reboot required from last package and this is
4194 * not 'pkgask' then suspend installation of remaining packages
4195 */
4196
4197 if ((ireboot != 0) && (askflag == 0)) {
4198 ptext(stderr, MSG_SUSPEND_ADD, pkginst);
4199 continue;
4200 }
4201
4202 /*
4203 * handle interrupt if the previous pkginstall was interrupted
4204 */
4205
4206 if (continue_installation() == B_FALSE) {
4207 return (B_FALSE);
4208 }
4209
4210 /*
4211 * if pkgask, handle response file creation:
4212 * - if the response file is a directory, then create a path to
4213 * -- a package instance within the response file directory.
4214 * - If the response file is NOT a directory, if more than one
4215 * -- package is to be installed.
4216 */
4217
4218 if ((askflag != 0) && (respdir != (char *)NULL)) {
4219 (void) snprintf(respfile_path, sizeof (respfile_path),
4220 "%s/%s", respdir, pkginst);
4221 respfile = respfile_path;
4222 }
4223
4224 echo(MSG_PROC_INST, pkginst,
4225 (a_uri && a_idsName) ? a_uri : a_device);
4226
4227 /*
4228 * If we're installing another package in the same
4229 * session, the second through nth pkginstall, must
4230 * continue from where the prior one left off. For this
4231 * reason, the continuation feature (implied by the
4232 * nature of the command) is used for the remaining
4233 * packages.
4234 */
4235
4236 if ((i == 1) && (pkgdrtarg != (char *)NULL)) {
4237 pkgcontsrc = pkgdrtarg;
4238 }
4239
4240 /* reset interrupted flag before calling pkginstall */
4241
4242 interrupted = 0; /* last action was NOT quit */
4243
4244 /* call pkginstall for this package */
4245
4246 n = pkgInstall(get_inst_root(), NULL,
4247 packageDir, a_altBinDir);
4248
4249 /* set success/fail condition variables */
4250
4251 ckreturn(n);
4252
4253 /* decrement number of packages left to install */
4254
4255 npkgs--;
4256
4257 /*
4258 * if no packages left to install, unmount package source
4259 * device if appropriate
4260 */
4261
4262 if ((npkgs <= 0) && (pkgdev.mount || a_idsName)) {
4263 (void) chdir("/");
4264 if (!a_idsName) {
4265 (void) pkgumount(&pkgdev);
4266 }
4267 }
4268 }
4269
4270 /*
4271 * all packages in the package list have been installed.
4272 * Continue with installation if:
4273 * -- immediate reboot is NOT required
4274 * -- there are more packages to install
4275 * -- the package source is a path to a file
4276 * else return do NOT continue.
4277 */
4278
4279 if ((ireboot == 0) && (a_repeat != 0) &&
4280 (pkgdev.pathname == (char *)NULL)) {
4281 return (B_TRUE);
4282 }
4283
4284 /* return 'dont continue' */
4285
4286 return (B_FALSE);
4287 }
4288
4289 /*
4290 * Function: add_packages_in_global_no_zones
4291 * Description: call this function to add a list of packages in the global zone
4292 * when no non-global zones exist
4293 * returns:
4294 * B_TRUE to process next data stream
4295 * B_FALSE to exit
4296 */
4297
4298 static boolean_t
add_packages_in_global_no_zones(char ** a_pkgList,char * a_uri,char * a_idsName,int a_repeat,char * a_altBinDir,char * a_device)4299 add_packages_in_global_no_zones(char **a_pkgList, char *a_uri,
4300 char *a_idsName, int a_repeat, char *a_altBinDir, char *a_device)
4301 {
4302 int n;
4303 int i;
4304 char respfile_path[PATH_MAX];
4305 CAF_T flags = 0;
4306
4307 /* entry assertions */
4308
4309 assert(a_pkgList != (char **)NULL);
4310
4311 echoDebug(DBG_ADDPACKAGES_GZ_NO_LZ_ENTRY);
4312 echoDebug(DBG_ADDPACKAGES_GZ_NO_LZ_ARGS, npkgs, PSTR(a_uri),
4313 PSTR(a_idsName), a_repeat, PSTR(a_device));
4314
4315 /*
4316 * set flags for applicability check
4317 */
4318
4319 /* in the global zone */
4320
4321 flags |= CAF_IN_GLOBAL_ZONE;
4322
4323 /* set -G flag */
4324
4325 if (globalZoneOnly == B_TRUE) {
4326 flags |= CAF_SCOPE_GLOBAL;
4327 }
4328
4329 /*
4330 * this is the main loop where all of the packages (as listed in the
4331 * package list) are added one at a time.
4332 */
4333
4334 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
4335 /*
4336 * if immediate reboot required from last package and this is
4337 * not 'pkgask' then suspend installation of remaining packages
4338 */
4339
4340 if ((ireboot != 0) && (askflag == 0)) {
4341 ptext(stderr, MSG_SUSPEND_ADD, pkginst);
4342 continue;
4343 }
4344
4345 /*
4346 * handle interrupt if the previous pkginstall was interrupted
4347 */
4348
4349 if (continue_installation() == B_FALSE) {
4350 return (B_FALSE);
4351 }
4352
4353 /*
4354 * check package applicability to install in this context
4355 */
4356
4357 if (check_applicability(pkgdev.dirname,
4358 pkginst, get_inst_root(), flags) == B_FALSE) {
4359 progerr(ERR_PKG_NOT_APPLICABLE, pkginst);
4360 quit(1);
4361 }
4362
4363 /*
4364 * if pkgask, handle response file creation:
4365 * - if the response file is a directory, then create a path to
4366 * -- a package instance within the response file directory.
4367 * - If the response file is NOT a directory, if more than one
4368 * -- package is to be installed.
4369 */
4370
4371 if ((askflag != 0) && (respdir != (char *)NULL)) {
4372 (void) snprintf(respfile_path, sizeof (respfile_path),
4373 "%s/%s", respdir, pkginst);
4374 respfile = respfile_path;
4375 }
4376
4377 echo(MSG_PROC_INST, pkginst,
4378 (a_uri && a_idsName) ? a_uri : a_device);
4379
4380 /*
4381 * If we're installing another package in the same
4382 * session, the second through nth pkginstall, must
4383 * continue from where the prior one left off. For this
4384 * reason, the continuation feature (implied by the
4385 * nature of the command) is used for the remaining
4386 * packages.
4387 */
4388
4389 if ((i == 1) && (pkgdrtarg != (char *)NULL)) {
4390 pkgcontsrc = pkgdrtarg;
4391 }
4392
4393 /* reset interrupted flag before calling pkginstall */
4394
4395 interrupted = 0; /* last action was NOT quit */
4396
4397 /* call pkginstall for this package */
4398
4399 n = pkgInstall(get_inst_root(), a_idsName,
4400 pkgdev.dirname, a_altBinDir);
4401
4402 /* set success/fail condition variables */
4403
4404 ckreturn(n);
4405
4406 /* decrement number of packages left to install */
4407
4408 npkgs--;
4409
4410 /*
4411 * if no packages left to install, unmount package source
4412 * device if appropriate
4413 */
4414
4415 if ((npkgs <= 0) && (pkgdev.mount || a_idsName)) {
4416 (void) chdir("/");
4417 if (!a_idsName) {
4418 (void) pkgumount(&pkgdev);
4419 }
4420 }
4421 }
4422
4423 /*
4424 * all packages in the package list have been installed.
4425 * Continue with installation if:
4426 * -- immediate reboot is NOT required
4427 * -- there are more packages to install
4428 * -- the package source is a path to a file
4429 * else return do NOT continue.
4430 */
4431
4432 if ((ireboot == 0) && (a_repeat != 0) &&
4433 (pkgdev.pathname == (char *)NULL)) {
4434 return (B_TRUE);
4435 }
4436
4437 /* return 'dont continue' */
4438
4439 return (B_FALSE);
4440 }
4441
4442 /*
4443 * returns:
4444 * B_TRUE to process next data stream
4445 * B_FALSE to exit
4446 */
4447
4448 static boolean_t
add_packages(char ** a_pkgList,char * a_uri,char * a_idsName,int a_repeat,char * a_altBinDir,char * a_device,boolean_t a_noZones)4449 add_packages(char **a_pkgList, char *a_uri,
4450 char *a_idsName, int a_repeat, char *a_altBinDir, char *a_device,
4451 boolean_t a_noZones)
4452 {
4453 zoneList_t zlst;
4454 boolean_t b;
4455
4456 /* entry assertions */
4457
4458 assert(a_pkgList != (char **)NULL);
4459
4460 echoDebug(DBG_ADDPACKAGES_ENTRY);
4461 echoDebug(DBG_ADDPACKAGES_ARGS, npkgs, PSTR(a_uri), PSTR(a_idsName),
4462 a_repeat, PSTR(a_altBinDir), PSTR(a_device));
4463
4464 /*
4465 * if running in the global zone AND one or more non-global
4466 * zones exist, add packages in a 'zones aware' manner, else
4467 * add packages in the standard 'non-zones aware' manner.
4468 */
4469
4470 if ((a_noZones == B_FALSE) && (z_running_in_global_zone() == B_FALSE)) {
4471 /* in non-global zone */
4472
4473 echoDebug(DBG_IN_LZ);
4474
4475 b = z_lock_this_zone(ZLOCKS_PKG_ADMIN);
4476 if (b != B_TRUE) {
4477 progerr(ERR_CANNOT_LOCK_THIS_ZONE);
4478 /* set fatal error return condition */
4479 ckreturn(1);
4480 return (B_FALSE);
4481 }
4482
4483 b = add_packages_in_nonglobal_zone(a_pkgList, a_uri, a_idsName,
4484 a_repeat, a_altBinDir, a_device);
4485
4486 (void) z_unlock_this_zone(ZLOCKS_ALL);
4487
4488 return (B_FALSE);
4489 }
4490
4491 /* running in the global zone */
4492
4493 b = z_non_global_zones_exist();
4494 if ((a_noZones == B_FALSE) && (b == B_TRUE) &&
4495 (globalZoneOnly == B_FALSE)) {
4496
4497 echoDebug(DBG_IN_GZ_WITH_LZ);
4498
4499 /* error if -V specified - what to use in non-global zone? */
4500
4501 if (vfstab_file) {
4502 progerr(ERR_V_USED_WITH_GZS);
4503 quit(1);
4504 }
4505
4506 /* get a list of all non-global zones */
4507 zlst = z_get_nonglobal_zone_list();
4508 if (zlst == (zoneList_t)NULL) {
4509 progerr(ERR_CANNOT_GET_ZONE_LIST);
4510 quit(1);
4511 }
4512
4513 /* need to lock all of the zones */
4514
4515 quitSetZonelist(zlst);
4516 b = z_lock_zones(zlst, ZLOCKS_PKG_ADMIN);
4517 if (b == B_FALSE) {
4518 z_free_zone_list(zlst);
4519 progerr(ERR_CANNOT_LOCK_ZONES);
4520 /* set fatal error return condition */
4521 ckreturn(1);
4522 return (B_FALSE);
4523 }
4524
4525 /* add packages to all zones */
4526
4527 b = add_packages_in_global_with_zones(a_pkgList, a_uri,
4528 a_idsName, a_repeat, a_altBinDir, a_device, zlst);
4529
4530 /* unlock all zones */
4531
4532 (void) z_unlock_zones(zlst, ZLOCKS_ALL);
4533 quitSetZonelist((zoneList_t)NULL);
4534
4535 /* free list of all non-global zones */
4536
4537 z_free_zone_list(zlst);
4538
4539 return (B_FALSE);
4540 }
4541
4542 /* in global zone no non-global zones */
4543
4544 echoDebug(DBG_IN_GZ_NO_LZ);
4545
4546 b = z_lock_this_zone(ZLOCKS_PKG_ADMIN);
4547 if (b != B_TRUE) {
4548 progerr(ERR_CANNOT_LOCK_THIS_ZONE);
4549 /* set fatal error return condition */
4550 ckreturn(1);
4551 return (B_FALSE);
4552 }
4553
4554 b = add_packages_in_global_no_zones(a_pkgList, a_uri, a_idsName,
4555 a_repeat, a_altBinDir, a_device);
4556
4557 (void) z_unlock_this_zone(ZLOCKS_ALL);
4558
4559 return (B_FALSE);
4560 }
4561