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