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