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