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 char path[PATH_MAX]; 1112 1113 echoDebug(DBG_CANNOT_GET_PKGLIST); 1114 1115 progerr(ERR_NOPKGS, pkgdev.dirname); 1116 quit(1); 1117 /* NOTREACHED */ 1118 } 1119 1120 /* 1121 * count the number of packages to install 1122 * NOTE: npkgs is a global variable that is referenced by quit.c 1123 * when error messages are generated - it is referenced directly 1124 * by the other functions called below... 1125 */ 1126 1127 for (npkgs = 0; pkglist[npkgs] != (char *)NULL; /* void */) { 1128 echoDebug(DBG_PKG_SELECTED, npkgs, pkglist[npkgs]); 1129 npkgs++; 1130 } 1131 1132 /* output number of packages to be added */ 1133 1134 echoDebug(DBG_NUM_PKGS_TO_ADD, npkgs); 1135 1136 /* 1137 * if pkgask and response container is a file (not a directory), 1138 * and there is more than one package to install, then it is an 1139 * error - too many packages to install when response container 1140 * is a file. 1141 */ 1142 1143 if ((askflag != 0) && (respdir == (char *)NULL) && 1144 (npkgs > 1)) { 1145 progerr(ERR_TOO_MANY_PKGS); 1146 quit(1); 1147 /* NOTREACHED */ 1148 } 1149 1150 /* 1151 * package list generated - add packages 1152 */ 1153 1154 b = add_packages(pkglist, ids_name, repeat, 1155 altBinDir, device, noZones); 1156 1157 /* 1158 * close open input data stream (source package) if left open. 1159 */ 1160 1161 if (ids_name) { 1162 echoDebug(DBG_CLOSING_STREAM, ids_name, 1163 PSTR(pkgdev.dirname)); 1164 (void) ds_close(1); 1165 rrmdir(pkgdev.dirname); 1166 ids_name = NULL; 1167 quitSetIdsName(ids_name); 1168 } 1169 1170 /* 1171 * continue with next sequence of packages if continue set 1172 */ 1173 1174 if (b == B_TRUE) { 1175 continue; 1176 } 1177 1178 /* 1179 * not continuing - quit with 0 exit code 1180 */ 1181 1182 quit(0); 1183 /* NOTREACHED */ 1184 } 1185 1186 /* NOTREACHED */ 1187 } 1188 1189 /* 1190 * ***************************************************************************** 1191 * static internal (private) functions 1192 * ***************************************************************************** 1193 */ 1194 1195 /* 1196 * Name: pkgZoneCheckInstall 1197 * Description: Invoke pkginstall in a specified zone to perform a preinstall 1198 * check of the a single package in the specified zone 1199 * Arguments: a_zoneName - pointer to string representing the name of the 1200 * zone to check install the package in. 1201 * a_zoneState - current state of the zone; must be mounted or 1202 * running. 1203 * a_idsName - pointer to string representing the data stream 1204 * device (input data stream) containing the package to 1205 * be check installed. 1206 * a_altBinDir - pointer to string representing an alternative 1207 * binary location directory to pass to pkginstall. 1208 * If this is == NULL no alternative binary location is 1209 * passed to pkginstall. 1210 * a_adminFile - pointer to string representing the admin 1211 * file to pass to pkginstall when installing the package. 1212 * If this is == NULL no admin file is given to pkginstall. 1213 * a_stdoutPath - pointer to string representing the local path 1214 * into which all output written by pkginstall to stdout 1215 * is stored. 1216 * If this is == NULL stdout is redirected to /dev/null 1217 * a_tmpzn - B_TRUE when this zone is booted by the package 1218 * command or B_FALSE if it was running before. 1219 * Returns: int (see ckreturn() function for details) 1220 * 0 - success 1221 * 1 - package operation failed (fatal error) 1222 * 2 - non-fatal error (warning) 1223 * 3 - user selected quit (operation interrupted) 1224 * 4 - admin settings prevented operation 1225 * 5 - interaction required and -n (non-interactive) specified 1226 * "10" will be added to indicate "immediate reboot required" 1227 * "20" will be added to indicate "reboot after install required" 1228 */ 1229 1230 static int 1231 pkgZoneCheckInstall(char *a_zoneName, zone_state_t a_zoneState, 1232 char *a_idsName, char *a_altBinDir, char *a_adminFile, 1233 char *a_stdoutPath, boolean_t a_tmpzn) 1234 { 1235 char *arg[MAXARGS]; 1236 char *p; 1237 char adminfd_path[PATH_MAX]; 1238 char path[PATH_MAX]; 1239 char pkgstreamfd_path[PATH_MAX]; 1240 int fds[MAX_FDS]; 1241 int maxfds; 1242 int n; 1243 int nargs; 1244 1245 /* entry assertions */ 1246 1247 assert(a_zoneName != (char *)NULL); 1248 assert(*a_zoneName != '\0'); 1249 1250 /* entry debugging info */ 1251 1252 echoDebug(DBG_PKGZONECHECKINSTALL_ENTRY); 1253 echoDebug(DBG_PKGZONECHECKINSTALL_ARGS, a_zoneName, PSTR(pkginst), 1254 PSTR(pkgdev.dirname), PSTR(pkgdev.mount), PSTR(pkgdev.bdevice), 1255 a_zoneState == ZONE_STATE_MOUNTED ? "/a" : "/", 1256 PSTR(a_idsName), PSTR(a_adminFile), PSTR(a_stdoutPath)); 1257 1258 /* generate full path to 'phatinstall' to run in zone */ 1259 1260 (void) snprintf(path, sizeof (path), "%s/pkginstall", 1261 "/usr/sadm/install/bin"); 1262 1263 /* start at first file descriptor */ 1264 1265 maxfds = 0; 1266 1267 /* 1268 * generate argument list for call to pkginstall 1269 */ 1270 1271 /* start at argument 0 */ 1272 1273 nargs = 0; 1274 1275 /* first argument is always: full path to executable */ 1276 1277 arg[nargs++] = path; 1278 1279 /* 1280 * second argument is always: pass -O debug to pkginstall: debug mode 1281 */ 1282 if (debugFlag == B_TRUE) { 1283 arg[nargs++] = "-O"; 1284 arg[nargs++] = "debug"; 1285 } 1286 1287 /* pkgadd -G: pass -G to pkginstall */ 1288 1289 if (globalZoneOnly == B_TRUE) { 1290 arg[nargs++] = "-G"; 1291 } 1292 1293 /* pkgadd -b dir: pass -b to pkginstall */ 1294 1295 if (a_altBinDir != (char *)NULL) { 1296 arg[nargs++] = "-b"; 1297 arg[nargs++] = a_altBinDir; 1298 } 1299 1300 /* pkgadd -C: pass -C to pkginstall: disable checksum */ 1301 1302 if (disableChecksum) { 1303 arg[nargs++] = "-C"; 1304 } 1305 1306 /* pkgadd -A: pass -A to pkginstall: disable attribute checking */ 1307 1308 if (disableAttributes) { 1309 arg[nargs++] = "-A"; 1310 } 1311 1312 /* 1313 * NONABI_SCRIPTS defined: pass -o to pkginstall; refers to a 1314 * pkg requiring operator interaction during a procedure script 1315 * (common before on1093) 1316 */ 1317 1318 if (old_pkg) { 1319 arg[nargs++] = "-o"; 1320 } 1321 1322 /* 1323 * PKG_NONABI_SYMLINKS defined: pass -y to pkginstall; process 1324 * symlinks consistent with old behavior 1325 */ 1326 1327 if (old_symlinks) { 1328 arg[nargs++] = "-y"; 1329 } 1330 1331 /* 1332 * PKG_ABI_NAMELENGTH defined: pass -e to pkginstall; causes 1333 * package name length to be restricted 1334 */ 1335 1336 if (ABI_namelength) { 1337 arg[nargs++] = "-e"; 1338 } 1339 1340 /* pkgadd -S: pass -S to pkginstall: suppress copyright notices */ 1341 1342 arg[nargs++] = "-S"; 1343 1344 /* pkgadd -M: pass -M to pkginstall: dont mount client file systems */ 1345 1346 arg[nargs++] = "-M"; 1347 1348 /* pkgadd -v: pass -v to pkginstall: never trace scripts */ 1349 1350 /* if running pkgask, pass -i to pkginstall: running pkgask */ 1351 1352 if (askflag) { 1353 return (0); 1354 } 1355 1356 /* pass "-O enable-hollow-package-support" */ 1357 1358 if (is_depend_pkginfo_DB()) { 1359 arg[nargs++] = "-O"; 1360 arg[nargs++] = "enable-hollow-package-support"; 1361 } 1362 1363 /* check is always in non-interactive mode */ 1364 1365 arg[nargs++] = "-n"; 1366 1367 /* pkgadd -a admin: pass -a admin to pkginstall in zone: admin file */ 1368 1369 if (a_adminFile) { 1370 int fd; 1371 fd = openLocal(a_adminFile, O_RDONLY, tmpdir); 1372 if (fd < 0) { 1373 progerr(ERR_CANNOT_COPY_LOCAL, a_adminFile, 1374 errno, strerror(errno)); 1375 return (1); 1376 } 1377 (void) snprintf(adminfd_path, sizeof (adminfd_path), 1378 "/proc/self/fd/%d", fd); 1379 fds[maxfds++] = fd; 1380 arg[nargs++] = "-a"; 1381 arg[nargs++] = adminfd_path; 1382 } 1383 1384 /* pkgadd -R root: pass -R /a to pkginstall when zone is mounted */ 1385 1386 if (a_zoneState == ZONE_STATE_MOUNTED) { 1387 arg[nargs++] = "-R"; 1388 arg[nargs++] = "/a"; 1389 } 1390 1391 /* pass -N to pkginstall: program name to report */ 1392 1393 arg[nargs++] = "-N"; 1394 arg[nargs++] = get_prog_name(); 1395 1396 /* pass "-O preinstallcheck" */ 1397 1398 arg[nargs++] = "-O"; 1399 arg[nargs++] = "preinstallcheck"; 1400 1401 /* add "-O addzonename" */ 1402 1403 arg[nargs++] = "-O"; 1404 arg[nargs++] = "addzonename"; 1405 1406 /* 1407 * add parent zone info/type 1408 */ 1409 1410 p = z_get_zonename(); 1411 if ((p != NULL) && (*p != '\0')) { 1412 char zn[MAXPATHLEN]; 1413 (void) snprintf(zn, sizeof (zn), 1414 "parent-zone-name=%s", p); 1415 arg[nargs++] = "-O"; 1416 arg[nargs++] = strdup(zn); 1417 } 1418 1419 /* current zone type */ 1420 1421 arg[nargs++] = "-O"; 1422 if (z_running_in_global_zone() == B_TRUE) { 1423 char zn[MAXPATHLEN]; 1424 (void) snprintf(zn, sizeof (zn), 1425 "parent-zone-type=%s", 1426 TAG_VALUE_GLOBAL_ZONE); 1427 arg[nargs++] = strdup(zn); 1428 } else { 1429 char zn[MAXPATHLEN]; 1430 (void) snprintf(zn, sizeof (zn), 1431 "parent-zone-type=%s", 1432 TAG_VALUE_NONGLOBAL_ZONE); 1433 arg[nargs++] = strdup(zn); 1434 } 1435 1436 /* Add the pkgserv options */ 1437 arg[nargs++] = "-O"; 1438 arg[nargs++] = pkgmodeargument(a_tmpzn ? RUN_ONCE : pkgservergetmode()); 1439 1440 /* add in the package stream file */ 1441 1442 if (a_idsName != NULL) { 1443 int fd; 1444 fd = openLocal(a_idsName, O_RDONLY, tmpdir); 1445 if (fd < 0) { 1446 progerr(ERR_STREAM_UNAVAILABLE, a_idsName, 1447 pkginst, strerror(errno)); 1448 quit(1); 1449 } 1450 (void) snprintf(pkgstreamfd_path, sizeof (pkgstreamfd_path), 1451 "/proc/self/fd/%d", fd); 1452 fds[maxfds++] = fd; 1453 arg[nargs++] = pkgstreamfd_path; 1454 } else { 1455 progerr(ERR_PKGZONEINSTALL_NO_STREAM); 1456 quit(1); 1457 } 1458 1459 /* add package instance name */ 1460 1461 arg[nargs++] = pkginst; 1462 1463 /* terminate the argument list */ 1464 1465 arg[nargs++] = NULL; 1466 1467 /* 1468 * run the appropriate pkginstall command in the specified zone 1469 */ 1470 1471 if (debugFlag == B_TRUE) { 1472 echoDebug(DBG_ZONE_EXEC_ENTER, a_zoneName, arg[0]); 1473 for (n = 0; arg[n]; n++) { 1474 echoDebug(DBG_ARG, n, arg[n]); 1475 } 1476 } 1477 1478 /* terminate file descriptor list */ 1479 1480 fds[maxfds] = -1; 1481 1482 /* exec command in zone */ 1483 1484 n = z_zone_exec(a_zoneName, path, arg, a_stdoutPath, (char *)NULL, fds); 1485 1486 echoDebug(DBG_ZONE_EXEC_EXIT, a_zoneName, arg[0], n, 1487 PSTR(a_stdoutPath)); 1488 1489 /* 1490 * close any files that were opened for use by the 1491 * /proc/self/fd interface so they could be passed to programs 1492 * via the z_zone_exec() interface 1493 */ 1494 1495 for (; maxfds > 0; maxfds--) { 1496 (void) close(fds[maxfds-1]); 1497 } 1498 1499 /* return results of pkginstall in zone execution */ 1500 1501 return (n); 1502 } 1503 1504 /* 1505 * Name: pkgZoneInstall 1506 * Description: Invoke pkginstall in a specified zone to perform an install 1507 * of a single package in the specified zone 1508 * Arguments: a_zoneName - pointer to string representing the name of the 1509 * zone to install the package in. 1510 * a_zoneState - current state of the zone; must be mounted or 1511 * running. 1512 * a_idsName - pointer to string representing the data stream 1513 * device (input data stream) containing the package to 1514 * be installed. 1515 * a_altBinDir - pointer to string representing an alternative 1516 * binary location directory to pass to pkginstall. 1517 * If this is == NULL no alternative binary location is 1518 * passed to pkginstall. 1519 * a_adminFile - pointer to string representing the admin 1520 * file to pass to pkginstall when installing the package. 1521 * If this is == NULL no admin file is given to pkginstall. 1522 * a_stdoutPath - pointer to string representing the local path 1523 * into which all output written by pkginstall to stdout 1524 * is stored. 1525 * If this is == NULL stdout is redirected to /dev/null 1526 * a_tmpzn - B_TRUE when this zone is booted by the package 1527 * command or B_FALSE if it was running before. 1528 * Returns: int (see ckreturn() function for details) 1529 * 0 - success 1530 * 1 - package operation failed (fatal error) 1531 * 2 - non-fatal error (warning) 1532 * 3 - user selected quit (operation interrupted) 1533 * 4 - admin settings prevented operation 1534 * 5 - interaction required and -n (non-interactive) specified 1535 * "10" will be added to indicate "immediate reboot required" 1536 * "20" will be added to indicate "reboot after install required" 1537 */ 1538 1539 static int 1540 pkgZoneInstall(char *a_zoneName, zone_state_t a_zoneState, char *a_idsName, 1541 char *a_altBinDir, char *a_adminFile, boolean_t a_tmpzn) 1542 { 1543 char *arg[MAXARGS]; 1544 char *p; 1545 char adminfd_path[PATH_MAX]; 1546 char path[PATH_MAX]; 1547 char pkgstreamfd_path[PATH_MAX]; 1548 char respfilefd_path[PATH_MAX]; 1549 int fds[MAX_FDS]; 1550 int maxfds; 1551 int n; 1552 int nargs; 1553 1554 /* entry assertions */ 1555 1556 assert(a_zoneName != (char *)NULL); 1557 assert(*a_zoneName != '\0'); 1558 1559 /* entry debugging info */ 1560 1561 echoDebug(DBG_PKGZONEINSTALL_ENTRY); 1562 echoDebug(DBG_PKGZONEINSTALL_ARGS, a_zoneName, PSTR(pkginst), 1563 PSTR(pkgdev.dirname), PSTR(pkgdev.mount), PSTR(pkgdev.bdevice), 1564 a_zoneState == ZONE_STATE_MOUNTED ? "/a" : "", PSTR(a_idsName), 1565 a_adminFile); 1566 1567 /* generate path to pkginstall */ 1568 1569 (void) snprintf(path, sizeof (path), "%s/pkginstall", PKGBIN); 1570 1571 /* start at first file descriptor */ 1572 1573 maxfds = 0; 1574 1575 /* 1576 * generate argument list for call to pkginstall 1577 */ 1578 1579 /* start at argument 0 */ 1580 1581 nargs = 0; 1582 1583 /* first argument is path to executable */ 1584 1585 arg[nargs++] = path; 1586 1587 /* 1588 * second argument is always: pass -O debug to pkginstall: debug mode 1589 */ 1590 if (debugFlag == B_TRUE) { 1591 arg[nargs++] = "-O"; 1592 arg[nargs++] = "debug"; 1593 } 1594 1595 /* pkgadd -G: pass -G to pkginstall */ 1596 1597 if (globalZoneOnly == B_TRUE) { 1598 arg[nargs++] = "-G"; 1599 } 1600 1601 /* pkgadd -b dir: pass -b to pkginstall in zone */ 1602 1603 if (a_altBinDir != (char *)NULL) { 1604 arg[nargs++] = "-b"; 1605 arg[nargs++] = a_altBinDir; 1606 } 1607 1608 /* pkgadd -B blocksize: pass -B to pkginstall in zone */ 1609 1610 if (rw_block_size != NULL) { 1611 arg[nargs++] = "-B"; 1612 arg[nargs++] = rw_block_size; 1613 } 1614 1615 /* pkgadd -C: pass -C to pkgadd in zone: disable checksum */ 1616 1617 if (disableChecksum) { 1618 arg[nargs++] = "-C"; 1619 } 1620 1621 /* pkgadd -A: pass -A to pkgadd in zone: disable attribute checking */ 1622 1623 if (disableAttributes) { 1624 arg[nargs++] = "-A"; 1625 } 1626 1627 /* pkgadd -S: pass -S to pkgadd in zone: suppress copyright notices */ 1628 1629 arg[nargs++] = "-S"; 1630 1631 /* pkgadd -I: pass -I to pkgadd in zone: initial install */ 1632 1633 if (init_install) { 1634 arg[nargs++] = "-I"; 1635 } 1636 1637 /* pkgadd -M: pass -M to pkgadd in zone: dont mount client file sys */ 1638 1639 arg[nargs++] = "-M"; 1640 1641 /* pkgadd -v: pass -v to pkgadd in zone: trace scripts */ 1642 1643 if (pkgverbose) { 1644 arg[nargs++] = "-v"; 1645 } 1646 1647 /* pkgadd -z: pass -z to pkgadd in zone fresh inst from pkg save area */ 1648 1649 if (saveSpoolInstall) { 1650 arg[nargs++] = "-z"; 1651 } 1652 1653 /* pass "-O enable-hollow-package-support" */ 1654 1655 if (is_depend_pkginfo_DB()) { 1656 arg[nargs++] = "-O"; 1657 arg[nargs++] = "enable-hollow-package-support"; 1658 } 1659 1660 /* pkgadd -t pass -t to pkgadd in zone disable save spool area create */ 1661 1662 if (disableSaveSpool) { 1663 arg[nargs++] = "-t"; 1664 } 1665 1666 /* if running pkgask, pass -i to pkgadd in zone: running pkgask */ 1667 1668 if (askflag) { 1669 echo(MSG_BYPASSING_ZONE, a_zoneName); 1670 return (0); 1671 } 1672 1673 /* 1674 * pkgadd -n (not pkgask): pass -n to pkginstall: noninteractive mode 1675 */ 1676 if (nointeract && !askflag) { 1677 arg[nargs++] = "-n"; 1678 } 1679 1680 /* pkgadd -a admin: pass -a admin to pkginstall in zone: admin file */ 1681 1682 if (a_adminFile) { 1683 int fd; 1684 fd = openLocal(a_adminFile, O_RDONLY, tmpdir); 1685 if (fd < 0) { 1686 progerr(ERR_CANNOT_COPY_LOCAL, a_adminFile, 1687 errno, strerror(errno)); 1688 return (1); 1689 } 1690 (void) snprintf(adminfd_path, sizeof (adminfd_path), 1691 "/proc/self/fd/%d", fd); 1692 fds[maxfds++] = fd; 1693 arg[nargs++] = "-a"; 1694 arg[nargs++] = adminfd_path; 1695 } 1696 1697 /* pkgadd -R root: pass -R /a to pkginstall when zone is mounted */ 1698 if (a_zoneState == ZONE_STATE_MOUNTED) { 1699 arg[nargs++] = "-R"; 1700 arg[nargs++] = "/a"; 1701 } 1702 1703 /* 1704 * pkgadd -D arg: pass -D dryrun to pkginstall in zone: dryrun 1705 * mode/file 1706 */ 1707 if (pkgdrtarg) { 1708 arg[nargs++] = "-D"; 1709 arg[nargs++] = pkgdrtarg; 1710 } 1711 1712 /* 1713 * pkgadd -c cont: pass -c cont to pkginstall in zone: continuation 1714 * file 1715 */ 1716 if (pkgcontsrc) { 1717 arg[nargs++] = "-c"; 1718 arg[nargs++] = pkgcontsrc; 1719 } 1720 1721 /* pkgadd -r resp: pass -r resp to pkginstall in zone: response file */ 1722 1723 if (respfile) { 1724 int fd; 1725 fd = openLocal(respfile, O_RDONLY, tmpdir); 1726 if (fd < 0) { 1727 progerr(ERR_CANNOT_COPY_LOCAL, a_adminFile, 1728 errno, strerror(errno)); 1729 return (1); 1730 } 1731 (void) snprintf(respfilefd_path, 1732 sizeof (respfilefd_path), 1733 "/proc/self/fd/%d", fd); 1734 fds[maxfds++] = fd; 1735 arg[nargs++] = "-r"; 1736 arg[nargs++] = respfilefd_path; 1737 } 1738 1739 /* add "-O addzonename" */ 1740 1741 arg[nargs++] = "-O"; 1742 arg[nargs++] = "addzonename"; 1743 1744 /* 1745 * add parent zone info/type 1746 */ 1747 1748 p = z_get_zonename(); 1749 if ((p != NULL) && (*p != '\0')) { 1750 char zn[MAXPATHLEN]; 1751 (void) snprintf(zn, sizeof (zn), 1752 "parent-zone-name=%s", p); 1753 arg[nargs++] = "-O"; 1754 arg[nargs++] = strdup(zn); 1755 } 1756 1757 /* current zone type */ 1758 1759 arg[nargs++] = "-O"; 1760 if (z_running_in_global_zone() == B_TRUE) { 1761 char zn[MAXPATHLEN]; 1762 (void) snprintf(zn, sizeof (zn), 1763 "parent-zone-type=%s", 1764 TAG_VALUE_GLOBAL_ZONE); 1765 arg[nargs++] = strdup(zn); 1766 } else { 1767 char zn[MAXPATHLEN]; 1768 (void) snprintf(zn, sizeof (zn), 1769 "parent-zone-type=%s", 1770 TAG_VALUE_NONGLOBAL_ZONE); 1771 arg[nargs++] = strdup(zn); 1772 } 1773 1774 /* Add the pkgserv options */ 1775 arg[nargs++] = "-O"; 1776 arg[nargs++] = pkgmodeargument(a_tmpzn ? RUN_ONCE : pkgservergetmode()); 1777 1778 /* add in the package stream file */ 1779 1780 if (a_idsName != NULL) { 1781 int fd; 1782 fd = openLocal(a_idsName, O_RDONLY, tmpdir); 1783 if (fd < 0) { 1784 progerr(ERR_STREAM_UNAVAILABLE, a_idsName, 1785 pkginst, strerror(errno)); 1786 quit(1); 1787 } 1788 (void) snprintf(pkgstreamfd_path, sizeof (pkgstreamfd_path), 1789 "/proc/self/fd/%d", fd); 1790 fds[maxfds++] = fd; 1791 arg[nargs++] = pkgstreamfd_path; 1792 } else { 1793 progerr(ERR_PKGZONEINSTALL_NO_STREAM); 1794 quit(1); 1795 } 1796 1797 /* add package instance name */ 1798 1799 arg[nargs++] = pkginst; 1800 1801 /* terminate the argument list */ 1802 1803 arg[nargs++] = NULL; 1804 1805 /* 1806 * run the appropriate pkginstall command in the specified zone 1807 */ 1808 1809 if (debugFlag == B_TRUE) { 1810 echoDebug(DBG_ZONE_EXEC_ENTER, a_zoneName, arg[0]); 1811 for (n = 0; arg[n]; n++) { 1812 echoDebug(DBG_ARG, n, arg[n]); 1813 } 1814 } 1815 1816 /* terminate file descriptor list */ 1817 1818 fds[maxfds] = -1; 1819 1820 /* exec command in zone */ 1821 1822 n = z_zone_exec(a_zoneName, path, arg, (char *)NULL, (char *)NULL, fds); 1823 1824 echoDebug(DBG_ZONE_EXEC_EXIT, a_zoneName, arg[0], n, ""); 1825 1826 /* 1827 * close any files that were opened for use by the 1828 * /proc/self/fd interface so they could be passed to programs 1829 * via the z_zone_exec() interface 1830 */ 1831 1832 for (; maxfds > 0; maxfds--) { 1833 (void) close(fds[maxfds-1]); 1834 } 1835 1836 /* return results of pkginstall in zone execution */ 1837 1838 return (n); 1839 } 1840 1841 /* 1842 * Name: pkgInstall 1843 * Description: Invoke pkginstall in the current zone to perform an install 1844 * of a single package to the current zone or standalone system 1845 * Arguments: a_altRoot - pointer to string representing the alternative 1846 * root to use for the install 1847 * a_idsName - pointer to string representing the data stream 1848 * device (input data stream) containing the package to 1849 * be installed. 1850 * a_pkgDir - pointer to string representing the path to the 1851 * directory containing the package 1852 * a_altBinDir - pointer to string representing location of the 1853 * pkginstall executable to run. If not NULL, then pass 1854 * the path specified to the -b option to pkginstall. 1855 * Returns: int (see ckreturn() function for details) 1856 * 0 - success 1857 * 1 - package operation failed (fatal error) 1858 * 2 - non-fatal error (warning) 1859 * 3 - user selected quit (operation interrupted) 1860 * 4 - admin settings prevented operation 1861 * 5 - interaction required and -n (non-interactive) specified 1862 * "10" will be added to indicate "immediate reboot required" 1863 * "20" will be added to indicate "reboot after install required" 1864 * NOTE: Both a_idsName and a_pkgDir are used to determine where the 1865 * package to be installed is located. If a_idsName is != NULL 1866 * then it must be the path to a device containing a package 1867 * stream that contains the package to be installed. If a_idsName 1868 * is == NULL then a_pkgDir must contain a full path to a directory 1869 * that contains the package to be installed. 1870 */ 1871 1872 static int 1873 pkgInstall(char *a_altRoot, char *a_idsName, char *a_pkgDir, char *a_altBinDir) 1874 { 1875 char *arg[MAXARGS]; 1876 char *p; 1877 char path[PATH_MAX]; 1878 char buffer[256]; 1879 int n, nargs; 1880 1881 /* entry debugging info */ 1882 1883 echoDebug(DBG_PKGINSTALL_ENTRY); 1884 echoDebug(DBG_PKGINSTALL_ARGS, PSTR(pkginst), PSTR(pkgdev.dirname), 1885 PSTR(pkgdev.mount), PSTR(pkgdev.bdevice), PSTR(a_altRoot), 1886 PSTR(a_idsName), PSTR(a_pkgDir)); 1887 1888 /* generate full path to 'pkginstall' to run in zone */ 1889 1890 (void) snprintf(path, sizeof (path), "%s/pkginstall", 1891 a_altBinDir == (char *)NULL ? PKGBIN : a_altBinDir); 1892 /* 1893 * generate argument list for call to pkginstall 1894 */ 1895 1896 /* start at argument 0 */ 1897 1898 nargs = 0; 1899 1900 /* first argument is path to executable */ 1901 1902 arg[nargs++] = path; 1903 1904 /* 1905 * second argument is always: pass -O debug to pkginstall: debug mode 1906 */ 1907 if (debugFlag == B_TRUE) { 1908 arg[nargs++] = "-O"; 1909 arg[nargs++] = "debug"; 1910 } 1911 1912 arg[nargs++] = "-O"; 1913 arg[nargs++] = pkgmodeargument(pkgservergetmode()); 1914 1915 /* 1916 * pkgadd -G: pass -G to pkginstall if: 1917 * - the -G option is specified on the pkgadd command line 1918 * - this package is marked 'this zone only': 1919 * -- package has SUNW_PKG_THISZONE=true, or 1920 * -- package has a request script 1921 * Setting -G for pkginstall causes pkginstall to install the package 1922 * in the target zone. If running in the global zone, will install the 1923 * package and mark the package as installed "in the global zone only". 1924 * If running in a non-global zone, will just install the package. 1925 */ 1926 1927 if (globalZoneOnly == B_TRUE) { 1928 arg[nargs++] = "-G"; 1929 } else if (pkgPackageIsThisZone(pkginst) == B_TRUE) { 1930 arg[nargs++] = "-G"; 1931 } 1932 1933 /* pkgadd -b dir: pass -b to pkginstall */ 1934 1935 if (a_altBinDir != (char *)NULL) { 1936 arg[nargs++] = "-b"; 1937 arg[nargs++] = a_altBinDir; 1938 } 1939 1940 /* pkgadd -B blocksize: pass -B to pkginstall */ 1941 1942 if (rw_block_size != NULL) { 1943 arg[nargs++] = "-B"; 1944 arg[nargs++] = rw_block_size; 1945 } 1946 1947 /* pkgadd -C: pass -C to pkginstall: disable checksum */ 1948 1949 if (disableChecksum) { 1950 arg[nargs++] = "-C"; 1951 } 1952 1953 /* pkgadd -A: pass -A to pkginstall: disable attribute checking */ 1954 1955 if (disableAttributes) { 1956 arg[nargs++] = "-A"; 1957 } 1958 1959 /* 1960 * NONABI_SCRIPTS defined: pass -o to pkginstall; refers to a 1961 * pkg requiring operator interaction during a procedure script 1962 * (common before on1093) 1963 */ 1964 1965 if (old_pkg) { 1966 arg[nargs++] = "-o"; 1967 } 1968 1969 /* 1970 * PKG_NONABI_SYMLINKS defined: pass -y to pkginstall; process 1971 * symlinks consistent with old behavior 1972 */ 1973 1974 if (old_symlinks) { 1975 arg[nargs++] = "-y"; 1976 } 1977 1978 /* 1979 * PKG_ABI_NAMELENGTH defined: pass -e to pkginstall; causes 1980 * package name length to be restricted 1981 */ 1982 1983 if (ABI_namelength) { 1984 arg[nargs++] = "-e"; 1985 } 1986 1987 /* pkgadd -S: pass -S to pkginstall: suppress copyright notices */ 1988 1989 if (suppressCopyright) { 1990 arg[nargs++] = "-S"; 1991 } 1992 1993 /* pkgadd -I: pass -I to pkginstall: initial install being performed */ 1994 1995 if (init_install) { 1996 arg[nargs++] = "-I"; 1997 } 1998 1999 /* pkgadd -M: pass -M to pkginstall: dont mount client file systems */ 2000 2001 if (no_map_client) { 2002 arg[nargs++] = "-M"; 2003 } 2004 2005 /* pkgadd -v: pass -v to pkginstall: trace scripts */ 2006 2007 if (pkgverbose) { 2008 arg[nargs++] = "-v"; 2009 } 2010 2011 /* pkgadd -z: pass -z to pkginstall: fresh install from pkg save area */ 2012 2013 if (saveSpoolInstall) { 2014 arg[nargs++] = "-z"; 2015 } 2016 2017 /* 2018 * if running in a non-global zone and the 'hollow' attribute is 2019 * passed in, then pass -h to pkginstall so that it knows how to 2020 * handle hollow packages for this local zone. 2021 */ 2022 2023 if (!z_running_in_global_zone() && is_depend_pkginfo_DB()) { 2024 arg[nargs++] = "-h"; 2025 } 2026 2027 /* pkgadd -t: pass -t to pkginstall: disable save spool area creation */ 2028 2029 if (disableSaveSpool) { 2030 arg[nargs++] = "-t"; 2031 } 2032 2033 /* if running pkgask, pass -i to pkginstall: running pkgask */ 2034 2035 if (askflag) { 2036 arg[nargs++] = "-i"; 2037 } 2038 2039 /* pkgadd -n (not pkgask): pass -n to pkginstall: noninteractive mode */ 2040 2041 if (nointeract && !askflag) { 2042 arg[nargs++] = "-n"; 2043 } 2044 2045 /* pkgadd -a admin: pass -a admin to pkginstall: admin file */ 2046 2047 if (admnfile) { 2048 arg[nargs++] = "-a"; 2049 arg[nargs++] = admnfile; 2050 } 2051 2052 /* pkgadd -D dryrun: pass -D dryrun to pkginstall: dryrun mode/file */ 2053 2054 if (pkgdrtarg) { 2055 arg[nargs++] = "-D"; 2056 arg[nargs++] = pkgdrtarg; 2057 } 2058 2059 /* pkgadd -c cont: pass -c cont to pkginstall: continuation file */ 2060 2061 if (pkgcontsrc) { 2062 arg[nargs++] = "-c"; 2063 arg[nargs++] = pkgcontsrc; 2064 } 2065 2066 /* pkgadd -V vfstab: pass -V vfstab to pkginstall: alternate vfstab */ 2067 2068 if (vfstab_file) { 2069 arg[nargs++] = "-V"; 2070 arg[nargs++] = vfstab_file; 2071 } 2072 2073 /* pkgadd -r resp: pass -r resp to pkginstall: response file */ 2074 2075 if (respfile) { 2076 arg[nargs++] = "-r"; 2077 arg[nargs++] = respfile; 2078 } 2079 2080 /* pkgadd -R root: pass -R root to pkginstall: alternative root */ 2081 2082 if (a_altRoot && *a_altRoot) { 2083 arg[nargs++] = "-R"; 2084 arg[nargs++] = a_altRoot; 2085 } 2086 2087 /* 2088 * If input data stream is available, 2089 * - add: -d ids_name -p number_of_parts 2090 * else, 2091 * - add: -d device -m mount [-f type] 2092 */ 2093 2094 if (a_idsName != NULL) { 2095 arg[nargs++] = "-d"; 2096 arg[nargs++] = a_idsName; 2097 arg[nargs++] = "-p"; 2098 ds_close(1); 2099 ds_putinfo(buffer, sizeof (buffer)); 2100 arg[nargs++] = buffer; 2101 } else if (pkgdev.mount != NULL) { 2102 arg[nargs++] = "-d"; 2103 arg[nargs++] = pkgdev.bdevice; 2104 arg[nargs++] = "-m"; 2105 arg[nargs++] = pkgdev.mount; 2106 if (pkgdev.fstyp != NULL) { 2107 arg[nargs++] = "-f"; 2108 arg[nargs++] = pkgdev.fstyp; 2109 } 2110 } 2111 2112 /* 2113 * add parent zone info/type 2114 */ 2115 2116 p = z_get_zonename(); 2117 if ((p != NULL) && (*p != '\0')) { 2118 char zn[MAXPATHLEN]; 2119 (void) snprintf(zn, sizeof (zn), 2120 "parent-zone-name=%s", p); 2121 arg[nargs++] = "-O"; 2122 arg[nargs++] = strdup(zn); 2123 } 2124 2125 /* current zone type */ 2126 2127 arg[nargs++] = "-O"; 2128 if (z_running_in_global_zone() == B_TRUE) { 2129 char zn[MAXPATHLEN]; 2130 (void) snprintf(zn, sizeof (zn), 2131 "parent-zone-type=%s", 2132 TAG_VALUE_GLOBAL_ZONE); 2133 arg[nargs++] = strdup(zn); 2134 } else { 2135 char zn[MAXPATHLEN]; 2136 (void) snprintf(zn, sizeof (zn), 2137 "parent-zone-type=%s", 2138 TAG_VALUE_NONGLOBAL_ZONE); 2139 arg[nargs++] = strdup(zn); 2140 } 2141 2142 /* pass -N to pkginstall: program name to report */ 2143 2144 arg[nargs++] = "-N"; 2145 arg[nargs++] = get_prog_name(); 2146 2147 /* add package directory name */ 2148 2149 arg[nargs++] = a_pkgDir; 2150 2151 /* add package instance name */ 2152 2153 arg[nargs++] = pkginst; 2154 2155 /* terminate the argument list */ 2156 2157 arg[nargs++] = NULL; 2158 2159 /* 2160 * run the appropriate pkginstall command in the specified zone 2161 */ 2162 2163 if (debugFlag == B_TRUE) { 2164 echoDebug(DBG_ZONE_EXEC_ENTER, "global", arg[0]); 2165 for (n = 0; arg[n]; n++) { 2166 echoDebug(DBG_ARG, n, arg[n]); 2167 } 2168 } 2169 2170 /* execute pkginstall command */ 2171 2172 n = pkgexecv(NULL, NULL, NULL, NULL, arg); 2173 2174 /* return results of pkginstall execution */ 2175 2176 return (n); 2177 } 2178 2179 /* 2180 * function to clear out any exisiting error return conditions that may have 2181 * been set by previous calls to ckreturn() 2182 */ 2183 static void 2184 resetreturn() 2185 { 2186 admnflag = 0; /* != 0 if any pkg op admin setting failure (4) */ 2187 doreboot = 0; /* != 0 if reboot required after installation (>= 10) */ 2188 failflag = 0; /* != 0 if fatal error has occurred (1) */ 2189 intrflag = 0; /* != 0 if user selected quit (3) */ 2190 ireboot = 0; /* != 0 if immediate reboot required (>= 20) */ 2191 nullflag = 0; /* != 0 if admin interaction required (5) */ 2192 warnflag = 0; /* != 0 if non-fatal error has occurred (2) */ 2193 interrupted = 0; /* last pkg op was quit (1,2,3,4,5) */ 2194 needconsult = 0; /* essential ask admin now (1,2,3,5) */ 2195 } 2196 2197 /* 2198 * function which checks the indicated return value 2199 * and indicates disposition of installation 2200 */ 2201 static void 2202 ckreturn(int retcode) 2203 { 2204 /* 2205 * entry debugging info 2206 */ 2207 2208 echoDebug(DBG_PKGADD_CKRETURN, retcode, PSTR(pkginst)); 2209 2210 /* reset needconsult so it only reflects this call to ckreturn */ 2211 needconsult = 0; 2212 2213 switch (retcode) { 2214 case 0: /* successful */ 2215 case 10: 2216 case 20: 2217 break; /* empty case */ 2218 2219 case 1: /* package operation failed (fatal error) */ 2220 case 11: 2221 case 21: 2222 failflag++; 2223 interrupted++; 2224 needconsult++; 2225 break; 2226 2227 case 2: /* non-fatal error (warning) */ 2228 case 12: 2229 case 22: 2230 warnflag++; 2231 interrupted++; 2232 needconsult++; 2233 break; 2234 2235 case 3: /* user selected quit; operation interrupted */ 2236 case 13: 2237 case 23: 2238 intrflag++; 2239 interrupted++; 2240 needconsult++; 2241 break; 2242 2243 case 4: /* admin settings prevented operation */ 2244 case 14: 2245 case 24: 2246 admnflag++; 2247 interrupted++; 2248 break; 2249 2250 case 5: /* administration: interaction req (no -n) */ 2251 case 15: 2252 case 25: 2253 nullflag++; 2254 interrupted++; 2255 needconsult++; 2256 break; 2257 2258 default: 2259 failflag++; 2260 interrupted++; 2261 needconsult++; 2262 return; 2263 } 2264 2265 if (retcode >= 20) { 2266 ireboot++; 2267 } else if (retcode >= 10) { 2268 doreboot++; 2269 } 2270 } 2271 2272 static void 2273 usage(void) 2274 { 2275 char *prog = get_prog_name(); 2276 2277 if (askflag) { 2278 (void) fprintf(stderr, ERR_USAGE_PKGASK, prog); 2279 } else if (z_running_in_global_zone() == B_FALSE) { 2280 (void) fprintf(stderr, ERR_USAGE_PKGADD_NONGLOBALZONE, 2281 prog, prog); 2282 } else { 2283 (void) fprintf(stderr, ERR_USAGE_PKGADD_GLOBALZONE, 2284 prog, prog); 2285 } 2286 } 2287 2288 /* 2289 * Name: check_applicability 2290 * Description: determine if a package is installable in this zone; that is, 2291 * does the scope of install conflict with existing installation 2292 * or can the package be installed 2293 * Arguments: a_packageDir - [RO, *RO] - (char *) 2294 * Pointer to string representing the directory where the 2295 * package is located 2296 * a_pkgInst - [RO, *RO] - (char *) 2297 * Pointer to string representing the name of the package 2298 * to check 2299 * a_rootPath - [RO, *RO] - (char *) 2300 * Pointer to string representing path to the root of the 2301 * file system where the package is to be installed - this 2302 * is usually the same as the "-R" argument to pkgadd 2303 * a_flags - [RO, *RO] - (CAF_T) 2304 * Flags set by the caller to indicate the conditions 2305 * under which the package is to be installed: 2306 * CAF_IN_GLOBAL_ZONE - in global zone 2307 * CAF_SCOPE_GLOBAL - -G specified 2308 * CAF_SCOPE_NONGLOBAL - -Z specified 2309 * Returns: boolean_t 2310 * B_TRUE - the package can be installed 2311 * B_FALSE - the package can not be installed 2312 */ 2313 2314 static boolean_t 2315 check_applicability(char *a_packageDir, char *a_pkgInst, char *a_rootPath, 2316 CAF_T a_flags) 2317 { 2318 FILE *pkginfoFP; 2319 FILE *pkgmapFP; 2320 boolean_t all_zones; /* pkg is "all zones" only */ 2321 boolean_t in_gz_only; /* pkg installed in global zone only */ 2322 boolean_t is_hollow; /* pkg is "hollow" */ 2323 boolean_t pkg_installed; /* pkg is installed */ 2324 boolean_t this_zone; /* pkg is "this zone" only */ 2325 boolean_t reqfile_found = B_FALSE; 2326 char instPkg[PKGSIZ+1]; /* installed pkg instance nam */ 2327 char instPkgPath[PATH_MAX]; /* installed pkg toplevel dir */ 2328 char pkginfoPath[PATH_MAX]; /* pkg 2 install pkginfo file */ 2329 char pkgmapPath[PATH_MAX]; /* pkg 2 install pkgmap file */ 2330 char pkgpath[PATH_MAX]; /* pkg 2 install toplevel dir */ 2331 int len; 2332 char line[LINE_MAX]; 2333 2334 /* entry assertions */ 2335 2336 assert(a_packageDir != (char *)NULL); 2337 assert(*a_packageDir != '\0'); 2338 assert(a_pkgInst != (char *)NULL); 2339 assert(*a_pkgInst != '\0'); 2340 2341 /* normalize root path */ 2342 2343 if (a_rootPath == (char *)NULL) { 2344 a_rootPath = ""; 2345 } 2346 2347 /* entry debugging info */ 2348 2349 echoDebug(DBG_CHECKAPP_ENTRY); 2350 echoDebug(DBG_CHECKAPP_ARGS, a_pkgInst, a_packageDir, a_rootPath); 2351 2352 /* 2353 * calculate paths to various objects 2354 */ 2355 2356 /* path to package to be installed top level (main) directory */ 2357 2358 len = snprintf(pkgpath, sizeof (pkgpath), "%s/%s", a_packageDir, 2359 a_pkgInst); 2360 if (len > sizeof (pkgpath)) { 2361 progerr(ERR_CREATE_PATH_2, a_packageDir, a_pkgInst); 2362 return (B_FALSE); 2363 } 2364 2365 /* error if package top level directory does not exist */ 2366 2367 if (isdir(pkgpath) != 0) { 2368 progerr(ERR_NO_PKGDIR, pkgpath, a_pkgInst, strerror(errno)); 2369 return (B_FALSE); 2370 } 2371 2372 /* path to pkginfo file within the package to be installed */ 2373 2374 len = snprintf(pkginfoPath, sizeof (pkginfoPath), "%s/pkginfo", 2375 pkgpath); 2376 if (len > sizeof (pkginfoPath)) { 2377 progerr(ERR_CREATE_PATH_2, pkgpath, "pkginfo"); 2378 return (B_FALSE); 2379 } 2380 2381 /* path to highest instance of package currently installed */ 2382 2383 pkgLocateHighestInst(instPkgPath, sizeof (instPkgPath), 2384 instPkg, sizeof (instPkg), a_rootPath, a_pkgInst); 2385 2386 /* 2387 * gather information from this package's pkginfo file 2388 */ 2389 2390 pkginfoFP = fopen(pkginfoPath, "r"); 2391 2392 if (pkginfoFP == (FILE *)NULL) { 2393 progerr(ERR_NO_PKG_INFOFILE, a_pkgInst, pkginfoPath, 2394 strerror(errno)); 2395 return (B_FALSE); 2396 } 2397 2398 /* determine "HOLLOW" setting for this package */ 2399 2400 is_hollow = pkginfoParamTruth(pkginfoFP, PKG_HOLLOW_VARIABLE, 2401 "true", B_FALSE); 2402 2403 /* determine "ALLZONES" setting for this package */ 2404 2405 all_zones = pkginfoParamTruth(pkginfoFP, PKG_ALLZONES_VARIABLE, 2406 "true", B_FALSE); 2407 2408 /* determine "THISZONE" setting for this package */ 2409 2410 this_zone = pkginfoParamTruth(pkginfoFP, PKG_THISZONE_VARIABLE, 2411 "true", B_FALSE); 2412 2413 /* close pkginfo file */ 2414 2415 (void) fclose(pkginfoFP); 2416 2417 /* 2418 * If request file is not found, it may be in the datastream which 2419 * is not yet unpacked. Check in the pkgmap file. 2420 */ 2421 if (isfile(pkgpath, REQUEST_FILE) != 0) { 2422 2423 /* path to pkgmap file within the package to be installed */ 2424 (void) snprintf(pkgmapPath, sizeof (pkgmapPath), "%s/pkgmap", 2425 pkgpath); 2426 2427 pkgmapFP = fopen(pkgmapPath, "r"); 2428 2429 if (pkgmapFP == NULL) { 2430 progerr(ERR_NO_PKG_MAPFILE, a_pkgInst, 2431 pkgmapPath, strerror(errno)); 2432 return (B_FALSE); 2433 } 2434 2435 while (fgets(line, LINE_MAX, pkgmapFP) != NULL) { 2436 if (strstr(line, " i request") != NULL) { 2437 reqfile_found = B_TRUE; 2438 break; 2439 } 2440 } 2441 (void) fclose(pkgmapFP); 2442 } else { 2443 reqfile_found = B_TRUE; 2444 } 2445 2446 /* 2447 * If this package is not marked for installation in this zone only, 2448 * check to see if this package has a request script. If this package 2449 * does have a request script, then mark the package for installation 2450 * in this zone only. Any package with a request script cannot be 2451 * installed outside of the zone the pkgadd command is being run in, 2452 * nor can such a package be installed as part of a new zone install. 2453 * A new zone install must be non-interactive, which is required 2454 * by all packages integrated into the Solaris WOS. 2455 */ 2456 2457 if ((!this_zone) && (reqfile_found)) { 2458 if (a_flags & CAF_IN_GLOBAL_ZONE) { 2459 echoDebug(DBG_CHECKAPP_THISZONE_REQUEST, a_pkgInst); 2460 } 2461 this_zone = B_TRUE; 2462 } 2463 2464 /* 2465 * If this package is already installed, see if the current installation 2466 * of the package has a request file - if it does, then act as though 2467 * the current package to be added has a request file - install the 2468 * package in the current zone only. 2469 */ 2470 2471 if ((!this_zone) && (instPkgPath[0] != '\0') && 2472 (isfile(instPkgPath, REQUEST_FILE) == 0)) { 2473 if (a_flags & CAF_IN_GLOBAL_ZONE) { 2474 echoDebug(DBG_CHECKAPP_THISZONE_INSTREQ, 2475 a_pkgInst, instPkg); 2476 } 2477 this_zone = B_TRUE; 2478 } 2479 2480 /* gather information from the global zone only file */ 2481 2482 in_gz_only = B_FALSE; 2483 if (a_flags & CAF_IN_GLOBAL_ZONE) { 2484 in_gz_only = pkgIsPkgInGzOnly(a_rootPath, a_pkgInst); 2485 } 2486 2487 /* determine if this package is currently installed */ 2488 2489 pkg_installed = pkginfoIsPkgInstalled((struct pkginfo **)NULL, 2490 a_pkgInst); 2491 2492 /* 2493 * verify package applicability based on information gathered, 2494 * and validate the three SUNW_PKG_ options: 2495 * 2496 * -----------|--------------|-------------|-------------|----------- 2497 * - - - - - -| GLOBAL ZONE -| GLOBAL ZONE | LOCAL ZONE | LOCAL ZONE 2498 * - - - - - -| - - pkgadd - | pkgadd -G | pkgadd | pkgadd -G 2499 * ----1------|--------------|-------------|-------------|------------ 2500 * ALLZONES f | add to gz | add to gz | add to ls | add to ls 2501 * HOLLOW f | current lz | not to curr | only - - - -| only - - - 2502 * THISZONE f | futr lz - - -| or futr lz | - - - - - - | - - - - - - 2503 * ----2------|--------------|-------------|-------------|------------ 2504 * ALLZONES T | add to gz | operation | operation | operation 2505 * HOLLOW f | current lz | not allowed | not allowed | not allowed 2506 * THISZONE f | future lz | - - - - - - | - - - - - - | - - - - - - 2507 * ----3------|--------------|-------------|-------------|------------ 2508 * ALLZONES T | add to gz | operation | operation | operation 2509 * HOLLOW T | pkg db only | not allowed | not allowed | not allowed 2510 * THISZONE f | curr/futr lz | - - - - - - | - - - - - - | - - - - - - 2511 * ----4------|--------------|-------------|-------------|------------ 2512 * ALLZONES T | bad option | bad option | bad option | bad option 2513 * HOLLOW * | combo - - - -| combo - - - | combo - - - | combo - - 2514 * THISZONE T | - - - - - - -|- - - - - - -|- - - - - - -|- - - - - - 2515 * ----5------|--------------|-------------|-------------|------------ 2516 * ALLZONES f | bad option | bad option | bad option | bad option 2517 * HOLLOW T | combo - - - -| combo - - - | combo - - - | combo - - - 2518 * THISZONE * | - - - - - - -| - - - - - - | - - - - - - | - - - - - - 2519 * ----6------|--------------|-------------|-------------|------------ 2520 * ALLZONES f | add to gz | add to gz | add to lz | add to lz 2521 * HOLLOW f | not current | not current | only - - - | only - - - 2522 * THISZONE T | or future lz | or futr lz | - - - - - - | - - - - - - 2523 * -----------|--------------|-------------|-------------|----------- 2524 */ 2525 2526 /* pkg "all zones" && "this zone" (#4) */ 2527 2528 if (all_zones && this_zone) { 2529 progerr(ERR_ALLZONES_AND_THISZONE, a_pkgInst, 2530 PKG_ALLZONES_VARIABLE, PKG_THISZONE_VARIABLE); 2531 return (B_FALSE); 2532 } 2533 2534 /* pkg "!all zones" && "hollow" (#5) */ 2535 2536 if ((!all_zones) && is_hollow) { 2537 progerr(ERR_NOW_ALLZONES_AND_HOLLOW, a_pkgInst, 2538 PKG_ALLZONES_VARIABLE, PKG_HOLLOW_VARIABLE); 2539 return (B_FALSE); 2540 } 2541 2542 /* pkg ALLZONES=true && -Z specified */ 2543 2544 if (all_zones && (a_flags & CAF_SCOPE_NONGLOBAL)) { 2545 progerr(ERR_ALLZONES_AND_Z_USED, a_pkgInst); 2546 return (B_FALSE); 2547 } 2548 2549 /* pkg ALLZONES=true & not running in global zone (#2/#3) */ 2550 2551 if (all_zones && (!(a_flags & CAF_IN_GLOBAL_ZONE))) { 2552 progerr(ERR_ALLZONES_AND_IN_LZ, a_pkgInst); 2553 return (B_FALSE); 2554 } 2555 2556 /* pkg "in gz only" & pkg "NOT installed" */ 2557 2558 if (in_gz_only && (!pkg_installed)) { 2559 /* MAKE A WARNING */ 2560 echo(ERR_IN_GZ_AND_NOT_INSTALLED, a_pkgInst, 2561 pkgGetGzOnlyPath()); 2562 } 2563 2564 /* pkg ALLZONES=true & pkg "in gz only" & pkg "is installed" */ 2565 2566 if (all_zones && in_gz_only && pkg_installed) { 2567 progerr(ERR_IN_GZ_AND_ALLZONES_AND_INSTALLED, a_pkgInst); 2568 return (B_FALSE); 2569 } 2570 2571 /* pkg ALLZONES=true && -G specified (#2/#3) */ 2572 2573 if (all_zones && (a_flags & CAF_SCOPE_GLOBAL)) { 2574 progerr(ERR_ALLZONES_AND_G_USED, a_pkgInst); 2575 return (B_FALSE); 2576 } 2577 2578 /* pkg "!this zone" && "in gz only" & -G not specified */ 2579 2580 if ((!this_zone) && in_gz_only && (!(a_flags & CAF_SCOPE_GLOBAL))) { 2581 progerr(ERR_IN_GZ_AND_NO_G_USED, a_pkgInst); 2582 return (B_FALSE); 2583 } 2584 2585 /* pkg "NOT in gz only" & -Z specified */ 2586 2587 if ((!in_gz_only) && (a_flags & CAF_SCOPE_NONGLOBAL)) { 2588 progerr(ERR_NOT_IN_GZ_AND_Z_USED, a_pkgInst); 2589 return (B_FALSE); 2590 } 2591 2592 /* pkg "this zone" && -Z specified */ 2593 2594 if (this_zone && (a_flags & CAF_SCOPE_NONGLOBAL)) { 2595 progerr(ERR_THISZONE_AND_Z_USED, PKG_THISZONE_VARIABLE, 2596 a_pkgInst); 2597 return (B_FALSE); 2598 } 2599 2600 /* 2601 * If this package is marked 'this zone only', then mark the package 2602 * as "add to this zone only". This is referenced by the various 2603 * add_package_... functions to determine if the package should be 2604 * added to the current zone, or to all zones, depending on the 2605 * zone in which the command is being run. 2606 */ 2607 2608 if (this_zone) { 2609 pkgAddThisZonePackage(a_pkgInst); 2610 } 2611 2612 return (B_TRUE); 2613 } 2614 2615 /* 2616 * Name: create_zone_adminfile 2617 * Description: Given a zone temporary directory and optionally an existing 2618 * administration file, generate an administration file that 2619 * can be used to perform "non-interactive" operations in a 2620 * non-global zone. 2621 * Arguments: r_zoneAdminFile - pointer to handle that will contain a 2622 * string representing the path to the temporary 2623 * administration file created - this must be NULL 2624 * before the first call to this function - on 2625 * subsequent calls if the pointer is NOT null then 2626 * the existing string will NOT be overwritten. 2627 * a_zoneTempDir - pointer to string representing the path 2628 * to the zone temporary directory to create the 2629 * temporary administration file in 2630 * a_admnfile - pointer to string representing the path to 2631 * an existing "user" administration file - the 2632 * administration file created will contain the 2633 * settings contained in this file, modified as 2634 * appropriate to supress any interaction; 2635 * If this is == NULL then the administration file 2636 * created will not contain any extra settings 2637 * Returns: void 2638 * NOTE: Any string returned is placed in new storage for the 2639 * calling method. The caller must use 'free' to dispose 2640 * of the storage once the string is no longer needed. 2641 * NOTE: On any error this function will call 'quit(1)' 2642 */ 2643 2644 static void 2645 create_zone_adminfile(char **r_zoneAdminFile, char *a_zoneTempDir, 2646 char *a_admnfile) 2647 { 2648 boolean_t b; 2649 2650 /* entry assertions */ 2651 2652 assert(r_zoneAdminFile != (char **)NULL); 2653 assert(a_zoneTempDir != (char *)NULL); 2654 assert(*a_zoneTempDir != '\0'); 2655 2656 /* entry debugging info */ 2657 2658 echoDebug(DBG_CREATE_ZONE_ADMINFILE, a_zoneTempDir, PSTR(a_admnfile)); 2659 2660 /* if temporary name already exists, do not overwrite */ 2661 2662 if (*r_zoneAdminFile != (char *)NULL) { 2663 return; 2664 } 2665 2666 /* create temporary name */ 2667 2668 *r_zoneAdminFile = tempnam(a_zoneTempDir, "zadmn"); 2669 b = z_create_zone_admin_file(*r_zoneAdminFile, a_admnfile); 2670 if (b == B_FALSE) { 2671 progerr(ERR_CREATE_TMPADMIN, *r_zoneAdminFile, 2672 strerror(errno)); 2673 quit(1); 2674 /* NOTREACHED */ 2675 } 2676 2677 echoDebug(DBG_CREATED_ZONE_ADMINFILE, *r_zoneAdminFile); 2678 } 2679 2680 /* 2681 * Name: create_zone_tempdir 2682 * Description: Given a system temporary directory, create a "zone" specific 2683 * temporary directory and return the path to the directory 2684 * created. 2685 * Arguments: r_zoneTempDir - pointer to handle that will contain a 2686 * string representing the path to the temporary 2687 * directory created - this must be NULL before the 2688 * first call to this function - on subsequent calls 2689 * if the pointer is NOT null then the existing string 2690 * will NOT be overwritten. 2691 * a_zoneTempDir - pointer to string representing the path 2692 * to the system temporary directory to create the 2693 * temporary zone directory in 2694 * Returns: void 2695 * NOTE: Any string returned is placed in new storage for the 2696 * calling method. The caller must use 'free' to dispose 2697 * of the storage once the string is no longer needed. 2698 * NOTE: On any error this function will call 'quit(1)' 2699 * NOTE: This function calls "quitSetZoneTmpdir" on success to 2700 * register the directory created with quit() so that the 2701 * directory will be automatically deleted on exit. 2702 */ 2703 2704 static void 2705 create_zone_tempdir(char **r_zoneTempDir, char *a_tmpdir) 2706 { 2707 boolean_t b; 2708 2709 /* entry assertions */ 2710 2711 assert(r_zoneTempDir != (char **)NULL); 2712 assert(a_tmpdir != (char *)NULL); 2713 assert(*a_tmpdir != '\0'); 2714 2715 /* entry debugging info */ 2716 2717 echoDebug(DBG_CREATE_ZONE_TEMPDIR, a_tmpdir); 2718 2719 /* if temporary directory already exists, do not overwrite */ 2720 2721 if (*r_zoneTempDir != (char *)NULL) { 2722 return; 2723 } 2724 2725 /* create temporary directory */ 2726 2727 b = setup_temporary_directory(r_zoneTempDir, a_tmpdir, "ztemp"); 2728 if (b == B_FALSE) { 2729 progerr(ERR_ZONETEMPDIR, a_tmpdir, strerror(errno)); 2730 quit(1); 2731 /* NOTREACHED */ 2732 } 2733 2734 /* register with quit() so directory is removed on exit */ 2735 2736 quitSetZoneTmpdir(*r_zoneTempDir); 2737 2738 /* exit debugging info */ 2739 2740 echoDebug(DBG_CREATED_ZONE_TEMPDIR, *r_zoneTempDir); 2741 } 2742 2743 /* 2744 * Name: continue_installation 2745 * Description: Called from within a loop that is installing packages, 2746 * this function examines various global variables and decides 2747 * whether or not to ask an appropriate question, and wait for 2748 * and appropriate reply. 2749 * Arguments: <<global variables>> 2750 * Returns: B_TRUE - continue processing with next package 2751 * B_FALSE - do not continue processing with next package 2752 */ 2753 2754 static boolean_t 2755 continue_installation(void) 2756 { 2757 char ans[MAX_INPUT]; 2758 int n; 2759 2760 /* return TRUE if not interrupted */ 2761 2762 if (!interrupted) { 2763 return (B_TRUE); 2764 } 2765 2766 /* 2767 * process interrupted - determine whether or not to continue 2768 */ 2769 2770 /* output appropriate interrupted message */ 2771 2772 if (askflag) { 2773 echo(npkgs == 1 ? MSG_1MORE_PROC : MSG_MORE_PROC, npkgs); 2774 } else { 2775 echo(npkgs == 1 ? MSG_1MORE_INST : MSG_MORE_INST, npkgs); 2776 } 2777 2778 /* if running with no interaction (-n) do not ask question */ 2779 2780 if (nointeract) { 2781 /* if admin required return 'dont continue' */ 2782 if (needconsult) { 2783 return (B_FALSE); 2784 } 2785 ckquit = 1; 2786 return (B_TRUE); 2787 } 2788 2789 /* interaction possible: ask question */ 2790 2791 ckquit = 0; 2792 n = ckyorn(ans, NULL, NULL, NULL, ASK_CONTINUE_ADD); 2793 if (n != 0) { 2794 quit(n); 2795 /* NOTREACHED */ 2796 } 2797 ckquit = 1; 2798 if (strchr("yY", *ans) == NULL) { 2799 return (B_FALSE); 2800 } 2801 return (B_TRUE); 2802 } 2803 2804 /* 2805 * package can be in a number of formats: 2806 * - file containing package stream (pkgadd -d file [pkgs]) 2807 * - directory containing packages (pkgadd -d /dir [pkgs]) 2808 * - device containing packages (pkgadd -d diskette1 [pkgs]) 2809 * non-global zones can be passed open files and strings as arguments 2810 * - for file containing package stream 2811 * -- the stream can be passed directly to the non-global zone 2812 * - for directory 2813 * -- convert packages to datastream to pass to the non-global zone 2814 * - for device 2815 * -- ? 2816 */ 2817 2818 static boolean_t 2819 unpack_and_check_packages(char **a_pkgList, char *a_idsName, char *a_packageDir) 2820 { 2821 int savenpkgs = npkgs; 2822 int i; 2823 CAF_T flags = 0; 2824 2825 /* entry assertions */ 2826 2827 assert(a_pkgList != (char **)NULL); 2828 2829 /* entry debugging info */ 2830 2831 echoDebug(DBG_UNPACKCHECK_ENTRY); 2832 echoDebug(DBG_UNPACKCHECK_ARGS, PSTR(a_idsName), PSTR(a_packageDir)); 2833 2834 /* 2835 * set flags for applicability check 2836 */ 2837 2838 /* determine if running in the global zone */ 2839 2840 if (z_running_in_global_zone() == B_TRUE) { 2841 flags |= CAF_IN_GLOBAL_ZONE; 2842 } 2843 2844 /* set -G flag */ 2845 2846 if (globalZoneOnly == B_TRUE) { 2847 flags |= CAF_SCOPE_GLOBAL; 2848 } 2849 2850 /* 2851 * for each package to install: 2852 * - if packages from datastream, unpack package into package dir 2853 * - check applicability of installing package on this system/zone 2854 */ 2855 2856 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) { 2857 if (a_idsName != (char *)NULL) { 2858 /* create stream out of package if not already one */ 2859 if (unpack_package_from_stream(a_idsName, pkginst, 2860 a_packageDir) == B_FALSE) { 2861 progerr(ERR_CANNOT_UNPACK_PKGSTRM, 2862 PSTR(pkginst), PSTR(a_idsName), 2863 PSTR(a_packageDir)); 2864 2865 npkgs = savenpkgs; 2866 return (B_FALSE); 2867 } 2868 } else { 2869 echoDebug(DBG_PKG_IN_DIR, pkginst, a_packageDir); 2870 } 2871 2872 /* check package applicability */ 2873 if (check_applicability(a_packageDir, 2874 pkginst, get_inst_root(), flags) == B_FALSE) { 2875 progerr(ERR_PKG_NOT_INSTALLABLE, pkginst); 2876 npkgs = savenpkgs; 2877 return (B_FALSE); 2878 } 2879 npkgs--; 2880 } 2881 2882 npkgs = savenpkgs; 2883 return (B_TRUE); 2884 } 2885 2886 /* 2887 * returns: 2888 * B_TRUE - package list generated 2889 * B_FALSE - failed to generate package list 2890 * Will call quit(n) on fatal error. 2891 */ 2892 2893 static boolean_t 2894 get_package_list(char ***r_pkgList, char **a_argv, char *a_categories, 2895 char **a_categoryList, char *a_idsName, int *r_repeat) 2896 { 2897 int n; 2898 2899 /* entry assertions */ 2900 2901 assert(r_repeat != (int *)NULL); 2902 2903 /* entry debugging info */ 2904 2905 echoDebug(DBG_GETPKGLIST_ENTRY); 2906 echoDebug(DBG_GETPKGLIST_ARGS, PSTR(a_idsName), PSTR(pkgdev.dirname), 2907 *r_repeat); 2908 2909 /* 2910 * get the list of the packages to add 2911 */ 2912 2913 n = pkgGetPackageList(r_pkgList, a_argv, optind, a_categories, 2914 a_categoryList, &pkgdev); 2915 2916 switch (n) { 2917 case -1: /* no packages found */ 2918 echoDebug(DBG_PKGLIST_NONFOUND, PSTR(a_idsName), 2919 pkgdev.dirname); 2920 return (B_FALSE); 2921 2922 case 0: /* packages found */ 2923 break; 2924 2925 default: /* "quit" error */ 2926 echoDebug(DBG_PKGLIST_ERROR, PSTR(a_idsName), 2927 pkgdev.dirname, n); 2928 quit(n); 2929 /* NOTREACHED */ 2930 } 2931 2932 /* order package list if input data stream specified */ 2933 2934 if (a_idsName) { 2935 ds_order(*r_pkgList); 2936 } 2937 2938 return (B_TRUE); 2939 } 2940 2941 /* 2942 * Name: install_in_one_zone 2943 * Description: Install a single package in a single zone 2944 * Arguments: a_zoneName - pointer to string representing the name of the 2945 * zone to install the package into. 2946 * a_idsName - pointer to string representing the data stream 2947 * device (input data stream) containing the package to 2948 * be installed. 2949 * If this is == NULL the package is assumed to be 2950 * spooled in the zone temporary directory. 2951 * a_zoneAdminFile - pointer to string representing the admin 2952 * file to pass to pkginstall when installing the package. 2953 * If this is == NULL no admin file is given to pkginstall. 2954 * a_zoneTempDir - pointer to string representing the temporary 2955 * directory in which spooled packages can be found if 2956 * a_idsName is == NULL. 2957 * a_altBinDir - pointer to string representing an alternative 2958 * binary location directory to pass to pkginstall. 2959 * If this is == NULL no alternative binary location is 2960 * passed to pkginstall. 2961 * a_scratchName - pointer to string representing the name of the 2962 * scratch zone to use for installation. 2963 * a_zoneState - state of the zone; must be mounted or running. 2964 * a_tmpzn - B_TRUE when this zone is booted by the package 2965 * command or B_FALSE if it was running before. 2966 * Returns: void 2967 * NOTE: As a side effect, "ckreturn" is called on the result returned 2968 * from running 'pkginstall' in the zone; this sets several global 2969 * variables which allows the caller to determine the result of 2970 * the installation operation. 2971 */ 2972 2973 static void 2974 install_in_one_zone(char *a_zoneName, char *a_idsName, 2975 char *a_zoneAdminFile, char *a_zoneTempDir, 2976 char *a_altBinDir, zone_state_t a_zoneState, boolean_t a_tmpzn) 2977 { 2978 char zoneStreamName[PATH_MAX] = {'\0'}; 2979 int n; 2980 2981 /* entry assertions */ 2982 2983 assert(a_zoneName != (char *)NULL); 2984 assert(*a_zoneName != '\0'); 2985 2986 /* entry debugging info */ 2987 2988 echoDebug(DBG_INSTINONEZONE_ENTRY); 2989 echoDebug(DBG_INSTINONEZONE_ARGS, a_zoneName, PSTR(a_idsName), 2990 PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir), 2991 PSTR(a_altBinDir)); 2992 2993 /* echo operation to perform to stdout */ 2994 2995 echo(MSG_INSTALL_PKG_IN_ZONE, pkginst, a_zoneName); 2996 2997 /* determine path to the package stream */ 2998 2999 if (a_idsName == (char *)NULL) { 3000 /* locate temp stream created earlier */ 3001 (void) snprintf(zoneStreamName, sizeof (zoneStreamName), 3002 "%s/%s.dstream", a_zoneTempDir, pkginst); 3003 } else { 3004 /* use stream passed in on command line */ 3005 (void) snprintf(zoneStreamName, sizeof (zoneStreamName), 3006 "%s", a_idsName); 3007 } 3008 3009 echoDebug(DBG_INSTALL_IN_ZONE, pkginst, a_zoneName, zoneStreamName); 3010 3011 n = pkgZoneInstall(a_zoneName, a_zoneState, zoneStreamName, 3012 a_altBinDir, a_zoneAdminFile, a_tmpzn); 3013 3014 /* set success/fail condition variables */ 3015 3016 ckreturn(n); 3017 3018 /* exit debugging info */ 3019 3020 echoDebug(DBG_INSTALL_FLAG_VALUES, "after install", admnflag, doreboot, 3021 failflag, interrupted, intrflag, ireboot, needconsult, 3022 nullflag, warnflag); 3023 } 3024 3025 /* 3026 * Name: install_in_zones 3027 * Description: Install a single package in the zones that are running from 3028 * a list of zones 3029 * Arguments: a_zlst - list of zones to install the package into 3030 * a_idsName - pointer to string representing the data stream 3031 * device (input data stream) containing the package to 3032 * be installed. 3033 * If this is == NULL the package is assumed to be 3034 * spooled in the zone temporary directory. 3035 * a_altBinDir - pointer to string representing an alternative 3036 * binary location directory to pass to pkginstall. 3037 * If this is == NULL no alternative binary location is 3038 * passed to pkginstall. 3039 * a_zoneAdminFile - pointer to string representing the admin 3040 * file to pass to pkginstall when installing the package. 3041 * If this is == NULL no admin file is given to pkginstall. 3042 * a_zoneTempDir - pointer to string representing the temporary 3043 * directory in which spooled packages can be found if 3044 * a_idsName is == NULL. 3045 */ 3046 3047 static int 3048 install_in_zones(zoneList_t a_zlst, char *a_idsName, char *a_altBinDir, 3049 char *a_zoneAdminFile, char *a_zoneTempDir) 3050 { 3051 char *zoneName; 3052 int zoneIndex; 3053 int zonesSkipped = 0; 3054 zone_state_t zst; 3055 3056 /* entry assertions */ 3057 3058 assert(a_zlst != (zoneList_t)NULL); 3059 3060 /* entry debugging info */ 3061 3062 echoDebug(DBG_INSTALLINZONES_ENTRY); 3063 echoDebug(DBG_INSTALLINZONES_ARGS, PSTR(a_idsName), 3064 PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir)); 3065 3066 /* process each zone in the list */ 3067 3068 for (zoneIndex = 0; 3069 (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL; 3070 zoneIndex++) { 3071 3072 /* skip the zone if it is NOT running */ 3073 3074 zst = z_zlist_get_current_state(a_zlst, zoneIndex); 3075 if (zst != ZONE_STATE_RUNNING && zst != ZONE_STATE_MOUNTED) { 3076 zonesSkipped++; 3077 echoDebug(DBG_SKIPPING_ZONE, zoneName); 3078 continue; 3079 } 3080 3081 /* install the package in this zone */ 3082 3083 install_in_one_zone(z_zlist_get_scratch(a_zlst, zoneIndex), 3084 a_idsName, a_zoneAdminFile, a_zoneTempDir, a_altBinDir, 3085 zst, B_FALSE); 3086 } 3087 3088 return (zonesSkipped); 3089 } 3090 3091 /* 3092 * Name: boot_and_install_in_zones 3093 * Description: Install a single package in the zones that are NOT running from 3094 * a list of zones - each zone is booted, the package installed, 3095 * and the zone is halted 3096 * Arguments: a_zlst - list of zones to install the package into 3097 * a_idsName - pointer to string representing the data stream 3098 * device (input data stream) containing the package to 3099 * be installed. 3100 * If this is == NULL the package is assumed to be 3101 * spooled in the zone temporary directory. 3102 * a_altBinDir - pointer to string representing an alternative 3103 * binary location directory to pass to pkginstall. 3104 * If this is == NULL no alternative binary location is 3105 * passed to pkginstall. 3106 * a_zoneAdminFile - pointer to string representing the admin 3107 * file to pass to pkginstall when installing the package. 3108 * If this is == NULL no admin file is given to pkginstall. 3109 * a_zoneTempDir - pointer to string representing the temporary 3110 * directory in which spooled packages can be found if 3111 * a_idsName is == NULL. 3112 */ 3113 3114 static int 3115 boot_and_install_in_zones(zoneList_t a_zlst, char *a_idsName, char *a_altBinDir, 3116 char *a_zoneAdminFile, char *a_zoneTempDir) 3117 { 3118 boolean_t b; 3119 char *zoneName; 3120 int zoneIndex; 3121 int zonesSkipped = 0; 3122 zone_state_t zst; 3123 3124 /* entry assertions */ 3125 3126 assert(a_zlst != (zoneList_t)NULL); 3127 3128 /* entry debugging info */ 3129 3130 echoDebug(DBG_BOOTINSTALLINZONES_ENTRY); 3131 echoDebug(DBG_BOOTINSTALLINZONES_ARGS, PSTR(a_idsName), 3132 PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir)); 3133 3134 /* process each zone in the list */ 3135 3136 for (zoneIndex = 0; 3137 (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL; 3138 zoneIndex++) { 3139 3140 /* skip the zone if it IS running */ 3141 3142 zst = z_zlist_get_current_state(a_zlst, zoneIndex); 3143 if (zst == ZONE_STATE_RUNNING || zst == ZONE_STATE_MOUNTED) { 3144 echoDebug(DBG_SKIPPING_ZONE_BOOT, zoneName); 3145 continue; 3146 } 3147 3148 /* skip the zone if it is NOT bootable */ 3149 3150 if (z_zlist_is_zone_runnable(a_zlst, zoneIndex) == B_FALSE) { 3151 echo(MSG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName); 3152 echoDebug(DBG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName); 3153 continue; 3154 } 3155 3156 /* mount up the zone */ 3157 3158 echo(MSG_BOOTING_ZONE, zoneName); 3159 echoDebug(DBG_BOOTING_ZONE, zoneName); 3160 3161 b = z_zlist_change_zone_state(a_zlst, zoneIndex, 3162 ZONE_STATE_MOUNTED); 3163 if (b == B_FALSE) { 3164 progerr(ERR_CANNOT_BOOT_ZONE, zoneName); 3165 /* set fatal error return condition */ 3166 ckreturn(1); 3167 zonesSkipped++; 3168 continue; 3169 } 3170 3171 /* install the package in this zone */ 3172 3173 install_in_one_zone(z_zlist_get_scratch(a_zlst, zoneIndex), 3174 a_idsName, a_zoneAdminFile, a_zoneTempDir, a_altBinDir, 3175 ZONE_STATE_MOUNTED, B_TRUE); 3176 3177 /* restore original state of zone */ 3178 3179 echo(MSG_RESTORE_ZONE_STATE, zoneName); 3180 echoDebug(DBG_RESTORE_ZONE_STATE, zoneName); 3181 3182 b = z_zlist_restore_zone_state(a_zlst, zoneIndex); 3183 } 3184 3185 return (zonesSkipped); 3186 } 3187 3188 /* 3189 * Name: pkginstall_check_in_one_zone 3190 * Description: Do a pre install check of a single package in a single zone 3191 * Arguments: a_zoneName - pointer to string representing the name of the 3192 * zone to check install the package in. 3193 * a_idsName - pointer to string representing the data stream 3194 * device (input data stream) containing the package to 3195 * be check installed. 3196 * If this is == NULL the package is assumed to be 3197 * spooled in the zone temporary directory. 3198 * a_zoneAdminFile - pointer to string representing the admin 3199 * file to pass to pkginstall when installing the package. 3200 * If this is == NULL no admin file is given to pkginstall. 3201 * a_zoneTempDir - pointer to string representing the temporary 3202 * directory in which spooled packages can be found if 3203 * a_idsName is == NULL. 3204 * a_altBinDir - pointer to string representing an alternative 3205 * binary location directory to pass to pkginstall. 3206 * If this is == NULL no alternative binary location is 3207 * passed to pkginstall. 3208 * a_scratchName - pointer to string representing the name of the 3209 * scratch zone to use for installation. 3210 * a_zoneState - state of the zone; must be mounted or running. 3211 * a_tmpzn - B_TRUE when this zone is booted by the package 3212 * command or B_FALSE if it was running before. 3213 * Returns: void 3214 * NOTE: As a side effect, "ckreturn" is called on the result returned 3215 * from running 'pkginstall' in the zone; this sets several global 3216 * variables which allows the caller to determine the result of 3217 * the pre installation check operation. 3218 */ 3219 3220 static void 3221 pkginstall_check_in_one_zone(char *a_zoneName, 3222 char *a_idsName, char *a_zoneAdminFile, char *a_zoneTempDir, 3223 char *a_altBinDir, char *a_scratchName, zone_state_t a_zoneState, 3224 boolean_t a_tmpzn) 3225 { 3226 char preinstallcheckPath[PATH_MAX+1]; 3227 char zoneStreamName[PATH_MAX] = {'\0'}; 3228 int n; 3229 3230 echo(MSG_CHECKINSTALL_PKG_IN_ZONE, pkginst, a_zoneName); 3231 echoDebug(MSG_CHECKINSTALL_PKG_IN_ZONE, pkginst, a_zoneName); 3232 3233 (void) snprintf(preinstallcheckPath, sizeof (preinstallcheckPath), 3234 "%s/%s.%s.preinstallcheck.txt", a_zoneTempDir, pkginst, 3235 a_zoneName); 3236 3237 if (a_idsName == (char *)NULL) { 3238 /* locate temporary stream created earlier */ 3239 (void) snprintf(zoneStreamName, sizeof (zoneStreamName), 3240 "%s/%s.dstream", a_zoneTempDir, pkginst); 3241 } else { 3242 (void) snprintf(zoneStreamName, sizeof (zoneStreamName), 3243 "%s", a_idsName); 3244 } 3245 3246 echoDebug(DBG_CHECKINSTALL_IN_ZONE, pkginst, a_zoneName, 3247 zoneStreamName); 3248 3249 n = pkgZoneCheckInstall(a_scratchName, a_zoneState, zoneStreamName, 3250 a_altBinDir, a_zoneAdminFile, preinstallcheckPath, a_tmpzn); 3251 3252 /* set success/fail condition variables */ 3253 3254 ckreturn(n); 3255 3256 echoDebug(DBG_INSTALL_FLAG_VALUES, "after preinstall check", 3257 admnflag, doreboot, failflag, interrupted, intrflag, 3258 ireboot, needconsult, nullflag, warnflag); 3259 } 3260 3261 /* 3262 * Name: pkginstall_check_in_zones 3263 * Description: Check installation of a single package in the zones that 3264 * are running from a list of zones 3265 * Arguments: a_zlst - list of zones to check install the package 3266 * a_idsName - pointer to string representing the data stream 3267 * device (input data stream) containing the package to 3268 * be check installed. 3269 * If this is == NULL the package is assumed to be 3270 * spooled in the zone temporary directory. 3271 * a_altBinDir - pointer to string representing an alternative 3272 * binary location directory to pass to pkginstall. 3273 * If this is == NULL no alternative binary location is 3274 * passed to pkginstall. 3275 * a_zoneAdminFile - pointer to string representing the admin 3276 * file to pass to pkginstall when checking the installing 3277 * of the package. 3278 * If this is == NULL no admin file is given to pkginstall. 3279 * a_zoneTempDir - pointer to string representing the temporary 3280 * directory in which spooled packages can be found if 3281 * a_idsName is == NULL. 3282 */ 3283 3284 static int 3285 pkginstall_check_in_zones(zoneList_t a_zlst, char *a_idsName, char *a_altBinDir, 3286 char *a_zoneAdminFile, char *a_zoneTempDir) 3287 { 3288 char *zoneName; 3289 int zoneIndex; 3290 int zonesSkipped = 0; 3291 zone_state_t zst; 3292 3293 for (zoneIndex = 0; 3294 (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL; 3295 zoneIndex++) { 3296 3297 zst = z_zlist_get_current_state(a_zlst, zoneIndex); 3298 if (zst != ZONE_STATE_RUNNING && zst != ZONE_STATE_MOUNTED) { 3299 zonesSkipped++; 3300 echoDebug(DBG_SKIPPING_ZONE, zoneName); 3301 continue; 3302 } 3303 3304 pkginstall_check_in_one_zone(zoneName, a_idsName, 3305 a_zoneAdminFile, a_zoneTempDir, a_altBinDir, 3306 z_zlist_get_scratch(a_zlst, zoneIndex), zst, B_FALSE); 3307 } 3308 3309 return (zonesSkipped); 3310 } 3311 3312 /* 3313 * Name: boot_and_pkginstall_check_in_zones 3314 * Description: Check installation of a single package in the zones that 3315 * are NOT running from a list of zones - each zone is booted, 3316 * the package installation is checked, and the zone is halted. 3317 * Arguments: a_zlst - list of zones to install the package into 3318 * a_idsName - pointer to string representing the data stream 3319 * device (input data stream) containing the package to 3320 * be check installed. 3321 * If this is == NULL the package is assumed to be 3322 * spooled in the zone temporary directory. 3323 * a_altBinDir - pointer to string representing an alternative 3324 * binary location directory to pass to pkginstall. 3325 * If this is == NULL no alternative binary location is 3326 * passed to pkginstall. 3327 * a_zoneAdminFile - pointer to string representing the admin 3328 * file to pass to pkginstall when check installing the 3329 * package. 3330 * If this is == NULL no admin file is given to pkginstall. 3331 * a_zoneTempDir - pointer to string representing the temporary 3332 * directory in which spooled packages can be found if 3333 * a_idsName is == NULL. 3334 */ 3335 3336 static int 3337 boot_and_pkginstall_check_in_zones(zoneList_t a_zlst, char *a_idsName, 3338 char *a_altBinDir, char *a_zoneAdminFile, char *a_zoneTempDir) 3339 { 3340 int zoneIndex; 3341 int zonesSkipped = 0; 3342 char *zoneName; 3343 boolean_t b; 3344 zone_state_t zst; 3345 3346 /* entry assertions */ 3347 3348 assert(a_zlst != (zoneList_t)NULL); 3349 3350 /* entry debugging info */ 3351 3352 echoDebug(DBG_BOOTCHECKINSTALLINZONES_ENTRY); 3353 echoDebug(DBG_BOOTCHECKINSTALLINZONES_ARGS, PSTR(a_idsName), 3354 PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir)); 3355 3356 /* process each zone in the list */ 3357 3358 for (zoneIndex = 0; 3359 (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL; 3360 zoneIndex++) { 3361 3362 /* skip the zone if it IS running */ 3363 3364 zst = z_zlist_get_current_state(a_zlst, zoneIndex); 3365 if (zst == ZONE_STATE_RUNNING || zst == ZONE_STATE_MOUNTED) { 3366 echoDebug(DBG_SKIPPING_ZONE_BOOT, zoneName); 3367 continue; 3368 } 3369 3370 /* skip the zone if it is NOT bootable */ 3371 3372 if (z_zlist_is_zone_runnable(a_zlst, zoneIndex) == B_FALSE) { 3373 echo(MSG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName); 3374 echoDebug(DBG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName); 3375 continue; 3376 } 3377 3378 /* mount up the zone */ 3379 3380 echo(MSG_BOOTING_ZONE, zoneName); 3381 echoDebug(DBG_BOOTING_ZONE, zoneName); 3382 3383 b = z_zlist_change_zone_state(a_zlst, zoneIndex, 3384 ZONE_STATE_MOUNTED); 3385 if (b == B_FALSE) { 3386 progerr(ERR_CANNOT_BOOT_ZONE, zoneName); 3387 /* set fatal error return condition */ 3388 ckreturn(1); 3389 zonesSkipped++; 3390 continue; 3391 } 3392 3393 /* pre-installation check of the package in this zone */ 3394 3395 pkginstall_check_in_one_zone(zoneName, a_idsName, 3396 a_zoneAdminFile, a_zoneTempDir, a_altBinDir, 3397 z_zlist_get_scratch(a_zlst, zoneIndex), 3398 ZONE_STATE_MOUNTED, B_TRUE); 3399 3400 /* restore original state of zone */ 3401 3402 echo(MSG_RESTORE_ZONE_STATE, zoneName); 3403 echoDebug(DBG_RESTORE_ZONE_STATE, zoneName); 3404 3405 b = z_zlist_restore_zone_state(a_zlst, zoneIndex); 3406 } 3407 3408 return (zonesSkipped); 3409 } 3410 3411 /* 3412 * Function: add_packages_in_global_with_zones 3413 * Description: call this function to add a list of packages in the global zone 3414 * when one or more non-global zones exist 3415 * returns: 3416 * B_TRUE to process next data stream 3417 * B_FALSE to exit 3418 */ 3419 3420 static boolean_t 3421 add_packages_in_global_with_zones(char **a_pkgList, 3422 char *a_idsName, int a_repeat, char *a_altBinDir, 3423 char *a_device, zoneList_t a_zlst) 3424 { 3425 static char *zoneTempDir = (char *)NULL; 3426 static char *zoneAdminFile = (char *)NULL; 3427 3428 boolean_t b; 3429 char *packageDir; 3430 char instdir[PATH_MAX]; 3431 char respfile_path[PATH_MAX]; 3432 char zoneStreamName[PATH_MAX] = {'\0'}; 3433 int i; 3434 int n; 3435 int savenpkgs = npkgs; 3436 int zonesSkipped; 3437 boolean_t globalPresent; 3438 3439 /* entry assertions */ 3440 3441 assert(a_pkgList != (char **)NULL); 3442 assert(a_zlst != (zoneList_t)NULL); 3443 3444 echoDebug(DBG_ADDPACKAGES_GZ_W_LZ_ENTRY); 3445 echoDebug(DBG_ADDPACKAGES_GZ_W_LZ_ARGS, npkgs, 3446 PSTR(a_idsName), a_repeat, PSTR(a_device)); 3447 3448 /* create temporary directory for use by zone operations */ 3449 3450 create_zone_tempdir(&zoneTempDir, tmpdir); 3451 3452 /* create hands off settings admin file for use in a non-global zone */ 3453 3454 create_zone_adminfile(&zoneAdminFile, zoneTempDir, admnfile); 3455 3456 /* determine directory where packages can be found */ 3457 3458 if (a_idsName == (char *)NULL) { 3459 /* no stream - directory containing packages provided */ 3460 packageDir = pkgdev.dirname; 3461 } else { 3462 packageDir = zoneTempDir; 3463 } 3464 3465 /* unpack and check all packages */ 3466 3467 b = unpack_and_check_packages(a_pkgList, a_idsName, packageDir); 3468 if (b != B_TRUE) { 3469 quit(1); 3470 } 3471 3472 /* 3473 * if the packages are contained in a directory, convert the 3474 * packages into individual streams because pkgZoneInstall is only able 3475 * to pass a stream to the non-global zone's pkginstall command. 3476 * After this code is executed: 3477 * if the original input was a datastream: 3478 * -> that datastream has been unpacked into "instdir" 3479 * if the original input was a directory with packages in it: 3480 * -> those packages have been placed into a single datastream 3481 */ 3482 3483 if (a_idsName == (char *)NULL) { 3484 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) { 3485 char *pkgs[2]; 3486 3487 /* package is not a stream - create one */ 3488 3489 (void) snprintf(zoneStreamName, sizeof (zoneStreamName), 3490 "%s/%s.dstream", zoneTempDir, pkginst); 3491 3492 echoDebug(DBG_CONVERTING_PKG, packageDir, pkginst, 3493 zoneStreamName); 3494 3495 /* set up list of packages to be this package only */ 3496 3497 pkgs[0] = pkginst; 3498 pkgs[1] = (char *)NULL; 3499 3500 n = pkgtrans(packageDir, zoneStreamName, pkgs, 3501 PT_SILENT|PT_ODTSTREAM); 3502 if (n != 0) { 3503 progerr(ERR_CANNOT_CONVERT_PKGSTRM, 3504 pkginst, packageDir, zoneStreamName); 3505 quit(1); 3506 } 3507 npkgs--; 3508 } 3509 npkgs = savenpkgs; 3510 } 3511 3512 /* 3513 * Phase I - run collect dependency information for all packages for all 3514 * zones - this involves running pkginstall with the "preinstallcheck" 3515 * option which causes all dependency checks to be performed without 3516 * actually doing the installation of the packages. This information is 3517 * gathered in the zone temporary directory and is used later to present 3518 * the dependency check results to the system administrator depending 3519 * on the administration settings. 3520 */ 3521 3522 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) { 3523 3524 /* reset interrupted flag before calling pkginstall */ 3525 3526 interrupted = 0; /* last action was NOT quit */ 3527 3528 /* 3529 * if this package is marked "install in this zone only", then 3530 * do not check dependencies in any other zone 3531 */ 3532 3533 if (pkgPackageIsThisZone(pkginst) == B_TRUE) { 3534 echoDebug(DBG_VERIFY_SKIP_THISZONE, pkginst); 3535 npkgs--; 3536 continue; 3537 } 3538 3539 /* 3540 * if operation failed in global zone do not propagate 3541 * to any non-global zones 3542 */ 3543 3544 if (interrupted != 0) { 3545 echo(MSG_CHECKINSTALL_INTERRUPT_B4_Z, pkginst); 3546 echoDebug(MSG_CHECKINSTALL_INTERRUPT_B4_Z, pkginst); 3547 break; 3548 } 3549 3550 echoDebug(DBG_INSTALL_FLAG_VALUES, "after pkginstall", 3551 admnflag, doreboot, failflag, interrupted, intrflag, 3552 ireboot, needconsult, nullflag, warnflag); 3553 3554 /* 3555 * call pkginstall to verify this package for all non-global 3556 * zones that are currently booted 3557 */ 3558 3559 zonesSkipped = pkginstall_check_in_zones(a_zlst, a_idsName, 3560 a_altBinDir, admnfile, zoneTempDir); 3561 3562 /* 3563 * if any zones were skipped (becuase they are not currently 3564 * booted), boot each zone one at a time and call pkginstall 3565 * to verify this package for each such non-global zone 3566 */ 3567 3568 if (zonesSkipped > 0) { 3569 echoDebug(DBG_ZONES_SKIPPED, zonesSkipped); 3570 3571 zonesSkipped = 3572 boot_and_pkginstall_check_in_zones(a_zlst, 3573 a_idsName, a_altBinDir, admnfile, 3574 zoneTempDir); 3575 3576 if (zonesSkipped > 0) { 3577 progerr(ERR_INSTALL_ZONES_SKIPPED, 3578 zonesSkipped); 3579 } 3580 } 3581 3582 npkgs--; 3583 } 3584 3585 /* 3586 * At this point, all of the dependency information has been gathered 3587 * and is ready to be analyzed. This function processes all of that 3588 * dependency information and presents the results to the system 3589 * administrator, depending on the current administration settings. 3590 */ 3591 3592 i = preinstall_verify(a_pkgList, a_zlst, zoneTempDir); 3593 if (i != 0) { 3594 /* dependency checks failed - exit */ 3595 quit(i); 3596 } 3597 3598 npkgs = savenpkgs; 3599 3600 /* 3601 * reset all error return condition variables that may have been 3602 * set during package installation dependency checking so that they 3603 * do not reflect on the success/failure of the actual package 3604 * installation operations 3605 */ 3606 3607 resetreturn(); 3608 3609 /* 3610 * At this point, all of the dependency checking is completed, and 3611 * the installation of the packages can proceed. Install each package 3612 * one at a time, starting with the global zone, and the for each 3613 * non-global zone that is booted, and then for each non-global zone 3614 * that is not currently booted. 3615 */ 3616 3617 globalPresent = z_on_zone_spec(GLOBAL_ZONENAME); 3618 3619 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) { 3620 /* 3621 * if immediate reboot required from last package and this is 3622 * not 'pkgask' then suspend installation of remaining packages 3623 */ 3624 3625 if ((ireboot != 0) && (askflag == 0)) { 3626 ptext(stderr, MSG_SUSPEND_ADD, pkginst); 3627 continue; 3628 } 3629 3630 /* 3631 * handle interrupt if the previous pkginstall was interrupted 3632 */ 3633 3634 if (continue_installation() == B_FALSE) { 3635 return (B_FALSE); 3636 } 3637 3638 /* 3639 * if pkgask, handle response file creation: 3640 * - if the response file is a directory, then create a path to 3641 * -- a package instance within the response file directory. 3642 * - If the response file is NOT a directory, if more than one 3643 * -- package is to be installed. 3644 */ 3645 3646 if ((askflag != 0) && (respdir != (char *)NULL)) { 3647 (void) snprintf(respfile_path, sizeof (respfile_path), 3648 "%s/%s", respdir, pkginst); 3649 respfile = respfile_path; 3650 } 3651 3652 echo(MSG_PROC_INST, pkginst, a_device); 3653 3654 /* 3655 * If we're installing another package in the same 3656 * session, the second through nth pkginstall, must 3657 * continue from where the prior one left off. For this 3658 * reason, the continuation feature (implied by the 3659 * nature of the command) is used for the remaining 3660 * packages. 3661 */ 3662 3663 if ((i == 1) && (pkgdrtarg != (char *)NULL)) { 3664 pkgcontsrc = pkgdrtarg; 3665 } 3666 3667 if (globalPresent) { 3668 /* 3669 * call pkginstall for this package for the global zone 3670 */ 3671 3672 echo(MSG_INSTALLING_PKG_IN_GZ, pkginst); 3673 3674 /* reset interrupted flag before calling pkginstall */ 3675 3676 interrupted = 0; /* last action was NOT quit */ 3677 3678 n = pkgInstall(get_inst_root(), NULL, packageDir, 3679 a_altBinDir); 3680 3681 /* set success/fail condition variables */ 3682 3683 ckreturn(n); 3684 3685 /* 3686 * if operation failed in global zone do not propagate 3687 * to any non-global zones 3688 */ 3689 3690 if (interrupted != 0) { 3691 echo(MSG_INSTALL_INTERRUPT_B4_ZONES, pkginst); 3692 echoDebug(MSG_INSTALL_INTERRUPT_B4_ZONES, 3693 pkginst); 3694 break; 3695 } 3696 } 3697 3698 /* 3699 * if this package is marked "install in this zone only", 3700 * then only need to install the package in the global zone; 3701 * skip installation in any non-global zones. 3702 */ 3703 3704 if (pkgPackageIsThisZone(pkginst) == B_TRUE) { 3705 echoDebug(DBG_INSTALL_SKIP_THISZONE, pkginst); 3706 npkgs--; 3707 continue; 3708 } 3709 3710 echoDebug(DBG_INSTALL_FLAG_VALUES, "install in running zones", 3711 admnflag, doreboot, failflag, interrupted, intrflag, 3712 ireboot, needconsult, nullflag, warnflag); 3713 3714 /* install package in currently booted zones */ 3715 3716 zonesSkipped = install_in_zones(a_zlst, a_idsName, a_altBinDir, 3717 zoneAdminFile, zoneTempDir); 3718 3719 /* install package in zones that are not currently booted */ 3720 3721 if (zonesSkipped > 0) { 3722 echoDebug(DBG_ZONES_SKIPPED, zonesSkipped); 3723 3724 zonesSkipped = boot_and_install_in_zones(a_zlst, 3725 a_idsName, a_altBinDir, zoneAdminFile, 3726 zoneTempDir); 3727 3728 if (zonesSkipped > 0) { 3729 progerr(ERR_INSTALL_ZONES_SKIPPED, 3730 zonesSkipped); 3731 } 3732 } 3733 3734 /* 3735 * package completely installed - remove any temporary stream 3736 * of the package that might have been created 3737 */ 3738 3739 if (a_idsName == (char *)NULL) { 3740 /* locate temporary stream created earlier */ 3741 (void) snprintf(zoneStreamName, sizeof (zoneStreamName), 3742 "%s/%s.dstream", zoneTempDir, pkginst); 3743 /* remove stream - no longer needed */ 3744 echoDebug(DBG_REMOVING_DSTREAM_PKGDIR, zoneStreamName, 3745 pkginst); 3746 (void) remove(zoneStreamName); 3747 } else { 3748 /* remove package - no longer needed */ 3749 if (snprintf(instdir, sizeof (instdir), "%s/%s", 3750 zoneTempDir, pkginst) >= PATH_MAX) { 3751 progerr(ERR_CANNOT_CREATE_PKGPATH, tmpdir); 3752 quit(1); 3753 } 3754 echoDebug(DBG_REMOVING_PKG_TMPDIR, instdir, pkginst); 3755 (void) remove(instdir); 3756 } 3757 3758 /* decrement number of packages left to install */ 3759 3760 npkgs--; 3761 3762 /* 3763 * if no packages left to install, unmount package source 3764 * device if appropriate 3765 */ 3766 3767 if ((npkgs <= 0) && (pkgdev.mount || a_idsName)) { 3768 (void) chdir("/"); 3769 if (!a_idsName) { 3770 echoDebug(DBG_UNMOUNTING_DEV, 3771 PSTR(pkgdev.mount)); 3772 (void) pkgumount(&pkgdev); 3773 } 3774 } 3775 } 3776 3777 /* 3778 * all packages in the package list have been installed. 3779 * Continue with installation if: 3780 * -- immediate reboot is NOT required 3781 * -- there are more packages to install 3782 * -- the package source is a path to a file 3783 * else return do NOT continue. 3784 */ 3785 3786 if ((ireboot == 0) && (a_repeat != 0) && 3787 (pkgdev.pathname == (char *)NULL)) { 3788 return (B_TRUE); 3789 } 3790 3791 /* return 'dont continue' */ 3792 3793 return (B_FALSE); 3794 } 3795 3796 /* 3797 * Function: add_packages_in_nonglobal_zone 3798 * Description: call this function to add a list of packages in a non-global 3799 * zone 3800 * returns: 3801 * B_TRUE to process next data stream 3802 * B_FALSE to exit 3803 */ 3804 3805 static boolean_t 3806 add_packages_in_nonglobal_zone(char **a_pkgList, 3807 char *a_idsName, int a_repeat, char *a_altBinDir, char *a_device) 3808 { 3809 static char *zoneTempDir = (char *)NULL; 3810 3811 char *packageDir; 3812 char respfile_path[PATH_MAX]; 3813 int i; 3814 int n; 3815 boolean_t b; 3816 int savenpkgs = npkgs; 3817 3818 /* entry assertions */ 3819 3820 assert(a_pkgList != (char **)NULL); 3821 3822 /* entry debugging info */ 3823 3824 echoDebug(DBG_ADDPACKAGES_LZ_ENTRY); 3825 echoDebug(DBG_ADDPACKAGES_LZ_ARGS, npkgs, PSTR(a_idsName), 3826 a_repeat, PSTR(a_device)); 3827 3828 /* create temporary directory for use by zone operations */ 3829 3830 create_zone_tempdir(&zoneTempDir, tmpdir); 3831 3832 /* 3833 * package can be in a number of formats: 3834 * - file containing package stream (pkgadd -d file [pkgs]) 3835 * - directory containing packages (pkgadd -d /dir [pkgs]) 3836 * - device containing packages (pkgadd -d diskette1 [pkgs]) 3837 * non-global zones can be passed open file drescriptors and 3838 * strings as arguments 3839 * - for file containing package stream 3840 * -- the stream can be passed directly to the non-global zone 3841 * - for directory 3842 * -- convert packages to datastream to pass to the non-global zone 3843 * - for device 3844 */ 3845 3846 /* determine directory where packages can be found */ 3847 3848 if (a_idsName == (char *)NULL) { 3849 /* no stream - directory containing packages provided */ 3850 packageDir = pkgdev.dirname; 3851 } else { 3852 packageDir = zoneTempDir; 3853 } 3854 3855 b = unpack_and_check_packages(a_pkgList, a_idsName, packageDir); 3856 if (b != B_TRUE) { 3857 quit(1); 3858 } 3859 3860 /* 3861 * this is the main loop where all of the packages (as listed in the 3862 * package list) are added one at a time. 3863 */ 3864 3865 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) { 3866 npkgs--; 3867 } 3868 3869 npkgs = savenpkgs; 3870 3871 /* 3872 * this is the main loop where all of the packages (as listed in the 3873 * package list) are added one at a time. 3874 */ 3875 3876 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) { 3877 /* 3878 * if immediate reboot required from last package and this is 3879 * not 'pkgask' then suspend installation of remaining packages 3880 */ 3881 3882 if ((ireboot != 0) && (askflag == 0)) { 3883 ptext(stderr, MSG_SUSPEND_ADD, pkginst); 3884 continue; 3885 } 3886 3887 /* 3888 * handle interrupt if the previous pkginstall was interrupted 3889 */ 3890 3891 if (continue_installation() == B_FALSE) { 3892 return (B_FALSE); 3893 } 3894 3895 /* 3896 * if pkgask, handle response file creation: 3897 * - if the response file is a directory, then create a path to 3898 * -- a package instance within the response file directory. 3899 * - If the response file is NOT a directory, if more than one 3900 * -- package is to be installed. 3901 */ 3902 3903 if ((askflag != 0) && (respdir != (char *)NULL)) { 3904 (void) snprintf(respfile_path, sizeof (respfile_path), 3905 "%s/%s", respdir, pkginst); 3906 respfile = respfile_path; 3907 } 3908 3909 echo(MSG_PROC_INST, pkginst, a_device); 3910 3911 /* 3912 * If we're installing another package in the same 3913 * session, the second through nth pkginstall, must 3914 * continue from where the prior one left off. For this 3915 * reason, the continuation feature (implied by the 3916 * nature of the command) is used for the remaining 3917 * packages. 3918 */ 3919 3920 if ((i == 1) && (pkgdrtarg != (char *)NULL)) { 3921 pkgcontsrc = pkgdrtarg; 3922 } 3923 3924 /* reset interrupted flag before calling pkginstall */ 3925 3926 interrupted = 0; /* last action was NOT quit */ 3927 3928 /* call pkginstall for this package */ 3929 3930 n = pkgInstall(get_inst_root(), NULL, 3931 packageDir, a_altBinDir); 3932 3933 /* set success/fail condition variables */ 3934 3935 ckreturn(n); 3936 3937 /* decrement number of packages left to install */ 3938 3939 npkgs--; 3940 3941 /* 3942 * if no packages left to install, unmount package source 3943 * device if appropriate 3944 */ 3945 3946 if ((npkgs <= 0) && (pkgdev.mount || a_idsName)) { 3947 (void) chdir("/"); 3948 if (!a_idsName) { 3949 (void) pkgumount(&pkgdev); 3950 } 3951 } 3952 } 3953 3954 /* 3955 * all packages in the package list have been installed. 3956 * Continue with installation if: 3957 * -- immediate reboot is NOT required 3958 * -- there are more packages to install 3959 * -- the package source is a path to a file 3960 * else return do NOT continue. 3961 */ 3962 3963 if ((ireboot == 0) && (a_repeat != 0) && 3964 (pkgdev.pathname == (char *)NULL)) { 3965 return (B_TRUE); 3966 } 3967 3968 /* return 'dont continue' */ 3969 3970 return (B_FALSE); 3971 } 3972 3973 /* 3974 * Function: add_packages_in_global_no_zones 3975 * Description: call this function to add a list of packages in the global zone 3976 * when no non-global zones exist 3977 * returns: 3978 * B_TRUE to process next data stream 3979 * B_FALSE to exit 3980 */ 3981 3982 static boolean_t 3983 add_packages_in_global_no_zones(char **a_pkgList, 3984 char *a_idsName, int a_repeat, char *a_altBinDir, char *a_device) 3985 { 3986 int n; 3987 int i; 3988 char respfile_path[PATH_MAX]; 3989 CAF_T flags = 0; 3990 3991 /* entry assertions */ 3992 3993 assert(a_pkgList != (char **)NULL); 3994 3995 echoDebug(DBG_ADDPACKAGES_GZ_NO_LZ_ENTRY); 3996 echoDebug(DBG_ADDPACKAGES_GZ_NO_LZ_ARGS, npkgs, 3997 PSTR(a_idsName), a_repeat, PSTR(a_device)); 3998 3999 /* 4000 * set flags for applicability check 4001 */ 4002 4003 /* in the global zone */ 4004 4005 flags |= CAF_IN_GLOBAL_ZONE; 4006 4007 /* set -G flag */ 4008 4009 if (globalZoneOnly == B_TRUE) { 4010 flags |= CAF_SCOPE_GLOBAL; 4011 } 4012 4013 /* 4014 * this is the main loop where all of the packages (as listed in the 4015 * package list) are added one at a time. 4016 */ 4017 4018 for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) { 4019 /* 4020 * if immediate reboot required from last package and this is 4021 * not 'pkgask' then suspend installation of remaining packages 4022 */ 4023 4024 if ((ireboot != 0) && (askflag == 0)) { 4025 ptext(stderr, MSG_SUSPEND_ADD, pkginst); 4026 continue; 4027 } 4028 4029 /* 4030 * handle interrupt if the previous pkginstall was interrupted 4031 */ 4032 4033 if (continue_installation() == B_FALSE) { 4034 return (B_FALSE); 4035 } 4036 4037 /* 4038 * check package applicability to install in this context 4039 */ 4040 4041 if (check_applicability(pkgdev.dirname, 4042 pkginst, get_inst_root(), flags) == B_FALSE) { 4043 progerr(ERR_PKG_NOT_APPLICABLE, pkginst); 4044 quit(1); 4045 } 4046 4047 /* 4048 * if pkgask, handle response file creation: 4049 * - if the response file is a directory, then create a path to 4050 * -- a package instance within the response file directory. 4051 * - If the response file is NOT a directory, if more than one 4052 * -- package is to be installed. 4053 */ 4054 4055 if ((askflag != 0) && (respdir != (char *)NULL)) { 4056 (void) snprintf(respfile_path, sizeof (respfile_path), 4057 "%s/%s", respdir, pkginst); 4058 respfile = respfile_path; 4059 } 4060 4061 echo(MSG_PROC_INST, pkginst, a_device); 4062 4063 /* 4064 * If we're installing another package in the same 4065 * session, the second through nth pkginstall, must 4066 * continue from where the prior one left off. For this 4067 * reason, the continuation feature (implied by the 4068 * nature of the command) is used for the remaining 4069 * packages. 4070 */ 4071 4072 if ((i == 1) && (pkgdrtarg != (char *)NULL)) { 4073 pkgcontsrc = pkgdrtarg; 4074 } 4075 4076 /* reset interrupted flag before calling pkginstall */ 4077 4078 interrupted = 0; /* last action was NOT quit */ 4079 4080 /* call pkginstall for this package */ 4081 4082 n = pkgInstall(get_inst_root(), a_idsName, 4083 pkgdev.dirname, a_altBinDir); 4084 4085 /* set success/fail condition variables */ 4086 4087 ckreturn(n); 4088 4089 /* decrement number of packages left to install */ 4090 4091 npkgs--; 4092 4093 /* 4094 * if no packages left to install, unmount package source 4095 * device if appropriate 4096 */ 4097 4098 if ((npkgs <= 0) && (pkgdev.mount || a_idsName)) { 4099 (void) chdir("/"); 4100 if (!a_idsName) { 4101 (void) pkgumount(&pkgdev); 4102 } 4103 } 4104 } 4105 4106 /* 4107 * all packages in the package list have been installed. 4108 * Continue with installation if: 4109 * -- immediate reboot is NOT required 4110 * -- there are more packages to install 4111 * -- the package source is a path to a file 4112 * else return do NOT continue. 4113 */ 4114 4115 if ((ireboot == 0) && (a_repeat != 0) && 4116 (pkgdev.pathname == (char *)NULL)) { 4117 return (B_TRUE); 4118 } 4119 4120 /* return 'dont continue' */ 4121 4122 return (B_FALSE); 4123 } 4124 4125 /* 4126 * returns: 4127 * B_TRUE to process next data stream 4128 * B_FALSE to exit 4129 */ 4130 4131 static boolean_t 4132 add_packages(char **a_pkgList, 4133 char *a_idsName, int a_repeat, char *a_altBinDir, char *a_device, 4134 boolean_t a_noZones) 4135 { 4136 zoneList_t zlst; 4137 boolean_t b; 4138 4139 /* entry assertions */ 4140 4141 assert(a_pkgList != (char **)NULL); 4142 4143 echoDebug(DBG_ADDPACKAGES_ENTRY); 4144 echoDebug(DBG_ADDPACKAGES_ARGS, npkgs, PSTR(a_idsName), 4145 a_repeat, PSTR(a_altBinDir), PSTR(a_device)); 4146 4147 /* 4148 * if running in the global zone AND one or more non-global 4149 * zones exist, add packages in a 'zones aware' manner, else 4150 * add packages in the standard 'non-zones aware' manner. 4151 */ 4152 4153 if ((a_noZones == B_FALSE) && (z_running_in_global_zone() == B_FALSE)) { 4154 /* in non-global zone */ 4155 4156 echoDebug(DBG_IN_LZ); 4157 4158 b = z_lock_this_zone(ZLOCKS_PKG_ADMIN); 4159 if (b != B_TRUE) { 4160 progerr(ERR_CANNOT_LOCK_THIS_ZONE); 4161 /* set fatal error return condition */ 4162 ckreturn(1); 4163 return (B_FALSE); 4164 } 4165 4166 b = add_packages_in_nonglobal_zone(a_pkgList, a_idsName, 4167 a_repeat, a_altBinDir, a_device); 4168 4169 (void) z_unlock_this_zone(ZLOCKS_ALL); 4170 4171 return (B_FALSE); 4172 } 4173 4174 /* running in the global zone */ 4175 4176 b = z_non_global_zones_exist(); 4177 if ((a_noZones == B_FALSE) && (b == B_TRUE) && 4178 (globalZoneOnly == B_FALSE)) { 4179 4180 echoDebug(DBG_IN_GZ_WITH_LZ); 4181 4182 /* error if -V specified - what to use in non-global zone? */ 4183 4184 if (vfstab_file) { 4185 progerr(ERR_V_USED_WITH_GZS); 4186 quit(1); 4187 } 4188 4189 /* get a list of all non-global zones */ 4190 zlst = z_get_nonglobal_zone_list(); 4191 if (zlst == (zoneList_t)NULL) { 4192 progerr(ERR_CANNOT_GET_ZONE_LIST); 4193 quit(1); 4194 } 4195 4196 /* need to lock all of the zones */ 4197 4198 quitSetZonelist(zlst); 4199 b = z_lock_zones(zlst, ZLOCKS_PKG_ADMIN); 4200 if (b == B_FALSE) { 4201 z_free_zone_list(zlst); 4202 progerr(ERR_CANNOT_LOCK_ZONES); 4203 /* set fatal error return condition */ 4204 ckreturn(1); 4205 return (B_FALSE); 4206 } 4207 4208 /* add packages to all zones */ 4209 4210 b = add_packages_in_global_with_zones(a_pkgList, 4211 a_idsName, a_repeat, a_altBinDir, a_device, zlst); 4212 4213 /* unlock all zones */ 4214 4215 (void) z_unlock_zones(zlst, ZLOCKS_ALL); 4216 quitSetZonelist((zoneList_t)NULL); 4217 4218 /* free list of all non-global zones */ 4219 4220 z_free_zone_list(zlst); 4221 4222 return (B_FALSE); 4223 } 4224 4225 /* in global zone no non-global zones */ 4226 4227 echoDebug(DBG_IN_GZ_NO_LZ); 4228 4229 b = z_lock_this_zone(ZLOCKS_PKG_ADMIN); 4230 if (b != B_TRUE) { 4231 progerr(ERR_CANNOT_LOCK_THIS_ZONE); 4232 /* set fatal error return condition */ 4233 ckreturn(1); 4234 return (B_FALSE); 4235 } 4236 4237 b = add_packages_in_global_no_zones(a_pkgList, a_idsName, 4238 a_repeat, a_altBinDir, a_device); 4239 4240 (void) z_unlock_this_zone(ZLOCKS_ALL); 4241 4242 return (B_FALSE); 4243 } 4244