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