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