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