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