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