zones.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) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 27/* 28 * Module: zones.c 29 * Group: libinstzones 30 * Description: Provide "zones" interface for install consolidation code 31 * 32 * Public Methods: 33 * z_create_zone_admin_file - Given a location to create the file, and 34 * optionally an existing administration file, generate an 35 * administration file that can be used to perform "non-interactive" 36 * operations in a non-global zone. 37 * z_free_zone_list - free contents of zoneList_t object 38 * z_get_nonglobal_zone_list - return zoneList_t object describing all 39 * non-global native zones 40 * z_get_nonglobal_zone_list_by_brand - return zoneList_t object describing 41 * all non-global zones matching the list of zone brands passed in. 42 * z_free_brand_list - free contents of a zoneBrandList_t object 43 * z_make_brand_list - return a zoneBrandList_t object describing the list 44 * of all zone brands passed in. 45 * z_get_zonename - return the name of the current zone 46 * z_global_only - Determine if the global zone is only zone on the spec list 47 * z_lock_this_zone - lock this zone 48 * z_lock_zones - lock specified zones 49 * z_mount_in_lz - Mount global zone directory in specified zone's root file 50 * system 51 * z_non_global_zones_exist - Determine if any non-global native zones exist 52 * z_on_zone_spec - Determine if named zone is on the zone_spec list 53 * z_running_in_global_zone - Determine if running in the "global" zone 54 * z_set_output_functions - Link program specific output functions 55 * z_set_zone_root - Set root for zones library operations 56 * z_set_zone_spec - Set list of zones on which actions will be performed 57 * z_umount_lz_mount - Unmount directory mounted with z_mount_in_lz 58 * z_unlock_this_zone - unlock this zone 59 * z_unlock_zones - unlock specified zones 60 * z_verify_zone_spec - Verify list of zones on which actions will be performed 61 * z_zlist_change_zone_state - Change the current state of the specified zone 62 * z_zlist_get_current_state - Determine the current kernel state of the 63 * specified zone 64 * z_zlist_get_original_state - Return the original kernal state of the 65 * specified zone 66 * z_zlist_get_scratch - Determine name of scratch zone 67 * z_zlist_get_zonename - Determine name of specified zone 68 * z_zlist_get_zonepath - Determine zonepath of specified zone 69 * z_zlist_restore_zone_state - Return the zone to the state it was originally 70 * in 71 * z_zone_exec - Execute a Unix command in a specified zone and return results 72 * z_zones_are_implemented - Determine if any zone operations can be performed 73 * z_is_zone_branded - determine if zone has a non-native brand 74 * z_is_zone_brand_in_list - determine if the zone's brand matches the 75 * brand list passed in. 76 * z_brands_are_implemented - determine if branded zones are implemented on 77 * this system 78 */ 79 80/* 81 * System includes 82 */ 83 84#include <stdio.h> 85#include <stdlib.h> 86#include <unistd.h> 87#include <fcntl.h> 88#include <ctype.h> 89#include <sys/types.h> 90#include <sys/param.h> 91#include <sys/sysmacros.h> 92#include <string.h> 93#include <strings.h> 94#include <sys/stat.h> 95#include <stdarg.h> 96#include <limits.h> 97#include <errno.h> 98#include <time.h> 99#include <signal.h> 100#include <stropts.h> 101#include <wait.h> 102#include <zone.h> 103#include <sys/brand.h> 104#include <libintl.h> 105#include <locale.h> 106#include <libzonecfg.h> 107#include <libcontract.h> 108#include <sys/contract/process.h> 109#include <sys/ctfs.h> 110#include <assert.h> 111#include <dlfcn.h> 112#include <link.h> 113#include <time.h> 114 115/* 116 * local includes 117 */ 118 119/* 120 * When _INSTZONES_LIB_Z_DEFINE_GLOBAL_DATA is defined, 121 * instzones_lib.h will define the z_global_data structure. 122 * Otherwise an extern to the structure is inserted. 123 */ 124 125#define _INSTZONES_LIB_Z_DEFINE_GLOBAL_DATA 126#include "instzones_lib.h" 127#include "zones_strings.h" 128 129/* 130 * Private structures 131 */ 132 133#define CLUSTER_BRAND_NAME "cluster" 134 135/* maximum number of arguments to exec() call */ 136 137#define UUID_FORMAT "%02d%02d%02d%03d-%02d%02d%02d%d-%016llx" 138 139/* 140 * Library Function Prototypes 141 */ 142 143#define streq(a, b) (strcmp((a), (b)) == 0) 144 145/* 146 * Local Function Prototypes 147 */ 148 149/* 150 * global internal (private) declarations 151 */ 152 153/* 154 * ***************************************************************************** 155 * global external (public) functions 156 * ***************************************************************************** 157 */ 158 159/* 160 * Name: z_create_zone_admin_file 161 * Description: Given a location to create the file, and optionally an existing 162 * administration file, generate an administration file that 163 * can be used to perform "non-interactive" operations in a 164 * non-global zone. 165 * Arguments: a_zoneAdminFilename - pointer to string representing the 166 * full path of zone admin file to create 167 * a_userAdminFilename - pointer to string representing the path 168 * to an existing "user" administration file - the 169 * administration file created will contain the 170 * settings contained in this file, modified as 171 * appropriate to supress any interaction; 172 * If this is == NULL then the administration file 173 * created will not contain any extra settings 174 * Returns: boolean_t 175 * == B_TRUE - admin file created 176 * == B_FALSE - failed to create admin file 177 */ 178 179boolean_t 180z_create_zone_admin_file(char *a_zoneAdminFilename, char *a_userAdminFilename) 181{ 182 FILE *zFp; 183 FILE *uFp = (FILE *)NULL; 184 185 /* entry assertions */ 186 187 assert(a_zoneAdminFilename != NULL); 188 assert(*a_zoneAdminFilename != '\0'); 189 190 /* create temporary zone admin file */ 191 192 zFp = fopen(a_zoneAdminFilename, "w"); 193 if (zFp == (FILE *)NULL) { 194 return (B_FALSE); 195 } 196 197 /* open user admin file if specified */ 198 199 if (a_userAdminFilename != (char *)NULL) { 200 uFp = fopen(a_userAdminFilename, "r"); 201 } 202 203 /* create default admin file for zone pkg ops if no user admin file */ 204 205 if (uFp == (FILE *)NULL) { 206 /* create default admin file */ 207 (void) fprintf(zFp, "action=nocheck\nauthentication=nocheck\n" 208 "basedir=default\nconflict=nocheck\nidepend=nocheck\n" 209 "instance=unique\npartial=nocheck\nrdepend=nocheck\n" 210 "runlevel=nocheck\nsetuid=nocheck\nspace=nocheck\n" 211 "mail=\n"); 212 } else for (;;) { 213 /* copy user admin file substitute/change appropriate entries */ 214 char buf[LINE_MAX+1]; 215 char *p; 216 217 /* read next line of user admin file */ 218 219 p = fgets(buf, sizeof (buf), uFp); 220 if (p == (char *)NULL) { 221 (void) fclose(uFp); 222 break; 223 } 224 225 /* modify / replace / accept as appropriate */ 226 227 if (strncmp(buf, "instance=quit", 13) == 0) { 228 (void) fprintf(zFp, "%s", "instance=unique\n"); 229 /*LINTED*/ 230 } else if (strncmp(buf, "keystore=", 9) == 0) { 231 } else if (strncmp(buf, "action=", 7) == 0) { 232 (void) fprintf(zFp, "action=nocheck\n"); 233 } else if (strncmp(buf, "authentication=", 15) == 0) { 234 (void) fprintf(zFp, "authentication=nocheck\n"); 235 } else if (strncmp(buf, "conflict=", 9) == 0) { 236 (void) fprintf(zFp, "conflict=nocheck\n"); 237 } else if (strncmp(buf, "idepend=", 8) == 0) { 238 (void) fprintf(zFp, "idepend=nocheck\n"); 239 } else if (strncmp(buf, "mail=", 5) == 0) { 240 (void) fprintf(zFp, "mail=\n"); 241 } else if (strncmp(buf, "partial=", 8) == 0) { 242 (void) fprintf(zFp, "partial=nocheck\n"); 243 } else if (strncmp(buf, "rdepend=", 8) == 0) { 244 (void) fprintf(zFp, "rdepend=nocheck\n"); 245 } else if (strncmp(buf, "runlevel=", 9) == 0) { 246 (void) fprintf(zFp, "runlevel=nocheck\n"); 247 } else if (strncmp(buf, "setuid=", 7) == 0) { 248 (void) fprintf(zFp, "setuid=nocheck\n"); 249 } else if (strncmp(buf, "space=", 6) == 0) { 250 (void) fprintf(zFp, "space=nocheck\n"); 251 } else { 252 (void) fprintf(zFp, "%s", buf); 253 } 254 } 255 256 /* close admin file and return success */ 257 258 (void) fclose(zFp); 259 return (B_TRUE); 260} 261 262/* 263 * Name: z_brands_are_implemented 264 * Description: Determine if any branded zones may be present 265 * Arguments: void 266 * Returns: boolean_t 267 * == B_TRUE - branded zones are supported 268 * == B_FALSE - branded zones are not supported 269 */ 270 271boolean_t 272z_brands_are_implemented(void) 273{ 274static boolean_t _brandsImplementedDetermined = B_FALSE; 275static boolean_t _brandsAreImplemented = B_FALSE; 276 277 /* if availability has not been determined, cache it now */ 278 279 if (!_brandsImplementedDetermined) { 280 _brandsImplementedDetermined = B_TRUE; 281 _brandsAreImplemented = _z_brands_are_implemented(); 282 if (_brandsAreImplemented) { 283 _z_echoDebug(DBG_BRANDS_ARE_IMPLEMENTED); 284 } else { 285 _z_echoDebug(DBG_BRANDS_NOT_IMPLEMENTED); 286 } 287 } 288 289 /* return cached answer */ 290 291 return (_brandsAreImplemented); 292} 293 294/* 295 * Name: z_free_zone_list 296 * Description: free contents of zoneList_t object 297 * Arguments: a_zlst - handle to zoneList_t object to free 298 * Returns: void 299 */ 300 301void 302z_free_zone_list(zoneList_t a_zlst) 303{ 304 int numzones; 305 306 /* ignore empty list */ 307 308 if (a_zlst == (zoneList_t)NULL) { 309 return; 310 } 311 312 /* free each entry in the zone list */ 313 314 for (numzones = 0; a_zlst[numzones]._zlName != (char *)NULL; 315 numzones++) { 316 zoneListElement_t *zelm = &a_zlst[numzones]; 317 318 /* free zone name string */ 319 320 free(zelm->_zlName); 321 322 /* free zonepath string */ 323 324 if (zelm->_zlPath != (char *)NULL) { 325 free(zelm->_zlPath); 326 } 327 328 } 329 330 /* free handle to the list */ 331 332 free(a_zlst); 333} 334 335/* 336 * Name: z_get_nonglobal_zone_list 337 * Description: return zoneList_t object describing all non-global 338 * native zones - branded zones are not included in list 339 * Arguments: None. 340 * Returns: zoneList_t 341 * == NULL - error, list could not be generated 342 * != NULL - success, list returned 343 * NOTE: Any zoneList_t returned is placed in new storage for the 344 * calling function. The caller must use 'z_free_zone_list' to 345 * dispose of the storage once the list is no longer needed. 346 */ 347 348zoneList_t 349z_get_nonglobal_zone_list(void) 350{ 351 zoneList_t zones; 352 zoneBrandList_t *brands = NULL; 353 354 if ((brands = z_make_brand_list("native cluster", " ")) == NULL) 355 return (NULL); 356 357 zones = z_get_nonglobal_zone_list_by_brand(brands); 358 359 z_free_brand_list(brands); 360 361 return (zones); 362} 363 364/* 365 * Name: z_free_brand_list 366 * Description: Free contents of zoneBrandList_t object 367 * Arguments: brands - pointer to zoneBrandList_t object to free 368 * Returns: void 369 */ 370void 371z_free_brand_list(zoneBrandList_t *brands) 372{ 373 while (brands != NULL) { 374 zoneBrandList_t *temp = brands; 375 free(brands->string_ptr); 376 brands = brands->next; 377 free(temp); 378 } 379} 380 381/* 382 * Name: z_make_brand_list 383 * Description: Given a string with a list of brand name delimited by 384 * the delimeter passed in, build a zoneBrandList_t structure 385 * with the list of brand names and return it to the caller. 386 * Arguments: 387 * brands - const char pointer to string list of brand names 388 * delim - const char pointer to string representing the 389 * delimeter for brands string. 390 * Returns: zoneBrandList_t * 391 * == NULL - error, list could not be generated 392 * != NULL - success, list returned 393 * NOTE: Any zoneBrandList_t returned is placed in new storage for the 394 * calling function. The caller must use 'z_free_brand_list' to 395 * dispose of the storage once the list is no longer needed. 396 */ 397zoneBrandList_t * 398z_make_brand_list(const char *brands, const char *delim) 399{ 400 zoneBrandList_t *brand = NULL, *head = NULL; 401 char *blist = NULL; 402 char *str = NULL; 403 404 if ((blist = strdup(brands)) == NULL) 405 return (NULL); 406 407 if ((str = strtok(blist, delim)) != NULL) { 408 if ((brand = (zoneBrandList_t *) 409 malloc(sizeof (struct _zoneBrandList))) == NULL) { 410 return (NULL); 411 } 412 413 head = brand; 414 brand->string_ptr = strdup(str); 415 brand->next = NULL; 416 417 while ((str = strtok(NULL, delim)) != NULL) { 418 if ((brand->next = (zoneBrandList_t *) 419 malloc(sizeof (struct _zoneBrandList))) == NULL) { 420 return (NULL); 421 } 422 423 brand = brand->next; 424 brand->string_ptr = strdup(str); 425 brand->next = NULL; 426 } 427 } 428 429 free(blist); 430 return (head); 431} 432 433/* 434 * Name: z_get_nonglobal_zone_list_by_brand 435 * Description: return zoneList_t object describing all non-global 436 * zones matching the list of brands passed in. 437 * Arguments: brands - The list of zone brands to look for. 438 * Returns: zoneList_t 439 * == NULL - error, list could not be generated 440 * != NULL - success, list returned 441 * NOTE: Any zoneList_t returned is placed in new storage for the 442 * calling function. The caller must use 'z_free_zone_list' to 443 * dispose of the storage once the list is no longer needed. 444 */ 445zoneList_t 446z_get_nonglobal_zone_list_by_brand(zoneBrandList_t *brands) 447{ 448 FILE *zoneIndexFP; 449 int numzones = 0; 450 struct zoneent *ze; 451 zoneList_t zlst = NULL; 452 FILE *mapFP; 453 char zonename[ZONENAME_MAX]; 454 zone_spec_t *zent; 455 456 /* if zones are not implemented, return empty list */ 457 458 if (!z_zones_are_implemented()) { 459 return ((zoneList_t)NULL); 460 } 461 462 /* 463 * Open the zone index file. Note that getzoneent_private() handles 464 * NULL. 465 */ 466 zoneIndexFP = setzoneent(); 467 468 mapFP = zonecfg_open_scratch("", B_FALSE); 469 470 /* index file open; scan all zones; see if any are at least installed */ 471 472 while ((ze = getzoneent_private(zoneIndexFP)) != NULL) { 473 zone_state_t st; 474 475 /* skip the global zone */ 476 477 if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0) { 478 free(ze); 479 continue; 480 } 481 482 /* 483 * skip any zones with brands not on the brand list 484 */ 485 if (!z_is_zone_brand_in_list(ze->zone_name, brands)) { 486 free(ze); 487 continue; 488 } 489 490 /* 491 * If the user specified an explicit zone list, then ignore any 492 * zones that aren't on that list. 493 */ 494 if ((zent = _z_global_data._zone_spec) != NULL) { 495 while (zent != NULL) { 496 if (strcmp(zent->zl_name, ze->zone_name) == 0) 497 break; 498 zent = zent->zl_next; 499 } 500 if (zent == NULL) { 501 free(ze); 502 continue; 503 } 504 } 505 506 /* non-global zone: create entry for this zone */ 507 508 if (numzones == 0) { 509 zlst = (zoneList_t)_z_calloc( 510 sizeof (zoneListElement_t)*2); 511 } else { 512 zlst = (zoneList_t)_z_realloc(zlst, 513 sizeof (zoneListElement_t)*(numzones+2)); 514 (void) memset(&zlst[numzones], 0L, 515 sizeof (zoneListElement_t)*2); 516 } 517 518 /* 519 * remember the zone name, zonepath and the current 520 * zone state of the zone. 521 */ 522 zlst[numzones]._zlName = _z_strdup(ze->zone_name); 523 zlst[numzones]._zlPath = _z_strdup(ze->zone_path); 524 zlst[numzones]._zlOrigInstallState = ze->zone_state; 525 zlst[numzones]._zlCurrInstallState = ze->zone_state; 526 527 /* get the zone kernel status */ 528 529 if (zone_get_state(ze->zone_name, &st) != Z_OK) { 530 st = ZONE_STATE_INCOMPLETE; 531 } 532 533 _z_echoDebug(DBG_ZONES_NGZ_LIST_STATES, 534 ze->zone_name, ze->zone_state, st); 535 536 /* 537 * For a scratch zone, we need to know the kernel zone name. 538 */ 539 if (zonecfg_in_alt_root() && mapFP != NULL && 540 zonecfg_find_scratch(mapFP, ze->zone_name, 541 zonecfg_get_root(), zonename, sizeof (zonename)) != -1) { 542 free(zlst[numzones]._zlScratchName); 543 zlst[numzones]._zlScratchName = _z_strdup(zonename); 544 } 545 546 /* 547 * remember the current kernel status of the zone. 548 */ 549 550 zlst[numzones]._zlOrigKernelStatus = st; 551 zlst[numzones]._zlCurrKernelStatus = st; 552 553 numzones++; 554 free(ze); 555 } 556 557 /* close the index file */ 558 endzoneent(zoneIndexFP); 559 560 if (mapFP != NULL) 561 zonecfg_close_scratch(mapFP); 562 563 /* return generated list */ 564 565 return (zlst); 566} 567 568/* 569 * Name: z_get_zonename 570 * Description: return the name of the current zone 571 * Arguments: void 572 * Returns: char * 573 * - pointer to string representing the name of the current 574 * zone 575 * NOTE: Any string returned is placed in new storage for the 576 * calling function. The caller must use 'Free' to dispose 577 * of the storage once the string is no longer needed. 578 */ 579 580char * 581z_get_zonename(void) 582{ 583 ssize_t zonenameLen; 584 char zonename[ZONENAME_MAX]; 585 zoneid_t zoneid = (zoneid_t)-1; 586 587 /* if zones are not implemented, return "" */ 588 589 if (!z_zones_are_implemented()) { 590 return (_z_strdup("")); 591 } 592 593 /* get the zone i.d. of the current zone */ 594 595 zoneid = getzoneid(); 596 597 /* get the name of the current zone */ 598 599 zonenameLen = getzonenamebyid(zoneid, zonename, sizeof (zonename)); 600 601 /* return "" if could not get zonename */ 602 603 if (zonenameLen < 1) { 604 return (_z_strdup("")); 605 } 606 607 return (_z_strdup(zonename)); 608} 609 610/* 611 * Name: z_global_only 612 * Description: Determine if the global zone is only zone on the spec list. 613 * Arguments: None 614 * Returns: B_TRUE if global zone is the only zone on the list, 615 * B_FALSE otherwise. 616 */ 617 618boolean_t 619z_global_only(void) 620{ 621 /* return true if zones are not implemented - treate as global zone */ 622 623 if (!z_zones_are_implemented()) { 624 return (B_TRUE); 625 } 626 627 /* return true if this is the global zone */ 628 629 if (_z_global_data._zone_spec != NULL && 630 _z_global_data._zone_spec->zl_next == NULL && 631 strcmp(_z_global_data._zone_spec->zl_name, GLOBAL_ZONENAME) == 0) { 632 return (B_TRUE); 633 } 634 635 /* return false - not the global zone */ 636 637 return (B_FALSE); 638} 639 640/* 641 * Name: z_lock_this_zone 642 * Description: lock this zone 643 * Arguments: a_lflags - [RO, *RO] - (ZLOCKS_T) 644 * Flags indicating which locks to acquire 645 * Returns: boolean_t 646 * == B_TRUE - success specified locks acquired 647 * == B_FALSE - failure specified locks not acquired 648 * NOTE: the lock objects for "this zone" are maintained internally. 649 */ 650 651boolean_t 652z_lock_this_zone(ZLOCKS_T a_lflags) 653{ 654 boolean_t b; 655 char *zoneName; 656 pid_t pid = (pid_t)0; 657 658 /* entry assertions */ 659 660 assert(a_lflags != ZLOCKS_NONE); 661 662 /* entry debugging info */ 663 664 _z_echoDebug(DBG_ZONES_LCK_THIS, a_lflags); 665 666 zoneName = z_get_zonename(); 667 pid = getpid(); 668 669 /* lock zone administration */ 670 671 if (a_lflags & ZLOCKS_ZONE_ADMIN) { 672 b = _z_lock_zone_object(&_z_global_data._z_ObjectLocks, 673 zoneName, LOBJ_ZONEADMIN, pid, 674 MSG_ZONES_LCK_THIS_ZONEADM, 675 ERR_ZONES_LCK_THIS_ZONEADM); 676 if (!b) { 677 (void) free(zoneName); 678 return (B_FALSE); 679 } 680 } 681 682 /* lock package administration always */ 683 684 if (a_lflags & ZLOCKS_PKG_ADMIN) { 685 b = _z_lock_zone_object(&_z_global_data._z_ObjectLocks, 686 zoneName, LOBJ_PKGADMIN, pid, 687 MSG_ZONES_LCK_THIS_PKGADM, 688 ERR_ZONES_LCK_THIS_PKGADM); 689 if (!b) { 690 (void) z_unlock_this_zone(a_lflags); 691 (void) free(zoneName); 692 return (B_FALSE); 693 } 694 } 695 696 /* lock patch administration always */ 697 698 if (a_lflags & ZLOCKS_PATCH_ADMIN) { 699 b = _z_lock_zone_object(&_z_global_data._z_ObjectLocks, 700 zoneName, LOBJ_PATCHADMIN, pid, 701 MSG_ZONES_LCK_THIS_PATCHADM, 702 ERR_ZONES_LCK_THIS_PATCHADM); 703 if (!b) { 704 (void) z_unlock_this_zone(a_lflags); 705 (void) free(zoneName); 706 return (B_FALSE); 707 } 708 } 709 710 (void) free(zoneName); 711 712 return (B_TRUE); 713} 714 715/* 716 * Name: z_lock_zones 717 * Description: lock specified zones 718 * Arguments: a_zlst - zoneList_t object describing zones to lock 719 * a_lflags - [RO, *RO] - (ZLOCKS_T) 720 * Flags indicating which locks to acquire 721 * Returns: boolean_t 722 * == B_TRUE - success, zones locked 723 * == B_FALSE - failure, zones not locked 724 */ 725 726boolean_t 727z_lock_zones(zoneList_t a_zlst, ZLOCKS_T a_lflags) 728{ 729 boolean_t b; 730 int i; 731 732 /* entry assertions */ 733 734 assert(a_lflags != ZLOCKS_NONE); 735 736 /* entry debugging info */ 737 738 _z_echoDebug(DBG_ZONES_LCK_ZONES, a_lflags); 739 740 /* if zones are not implemented, return TRUE */ 741 742 if (z_zones_are_implemented() == B_FALSE) { 743 _z_echoDebug(DBG_ZONES_LCK_ZONES_UNIMP); 744 return (B_TRUE); 745 } 746 747 /* lock this zone first before locking other zones */ 748 749 b = z_lock_this_zone(a_lflags); 750 if (b == B_FALSE) { 751 return (b); 752 } 753 754 /* ignore empty list */ 755 756 if (a_zlst == (zoneList_t)NULL) { 757 _z_echoDebug(DBG_ZONES_LCK_ZONES_NOZONES); 758 return (B_FALSE); 759 } 760 761 /* zones exist */ 762 763 _z_echoDebug(DBG_ZONES_LCK_ZONES_EXIST); 764 765 /* 766 * lock each listed zone that is currently running 767 */ 768 769 for (i = 0; (a_zlst[i]._zlName != (char *)NULL); i++) { 770 /* ignore zone if already locked */ 771 if (a_zlst[i]._zlStatus & ZST_LOCKED) { 772 continue; 773 } 774 775 /* ignore zone if not running */ 776 if (a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_RUNNING && 777 a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_MOUNTED) { 778 continue; 779 } 780 781 /* 782 * mark zone locked - if interrupted out during lock, an attempt 783 * will be made to release the lock 784 */ 785 a_zlst[i]._zlStatus |= ZST_LOCKED; 786 787 /* lock this zone */ 788 b = _z_lock_zone(&a_zlst[i], a_lflags); 789 790 /* on failure unlock all zones and return error */ 791 if (b != B_TRUE) { 792 _z_program_error(ERR_ZONES_LCK_ZONES_FAILED, 793 a_zlst[i]._zlName); 794 (void) z_unlock_zones(a_zlst, a_lflags); 795 return (B_FALSE); 796 } 797 } 798 799 /* success */ 800 801 return (B_TRUE); 802} 803 804/* 805 * Name: z_mount_in_lz 806 * Description: Mount global zone directory in specified zone's root file system 807 * Arguments: r_lzMountPoint - pointer to handle to string - on success, the 808 * full path to the mount point relative to the global zone 809 * root file system is returned here - this is needed to 810 * unmount the directory when it is no longer needed 811 * r_lzRootPath - pointer to handle to string - on success, the 812 * full path to the mount point relative to the specified 813 * zone's root file system is returned here - this is 814 * passed to any command executing in the specified zone to 815 * access the directory mounted 816 * a_zoneName - pointer to string representing the name of the zone 817 * to mount the specified global zone directory in 818 * a_gzPath - pointer to string representing the full absolute path 819 * of the global zone directory to LOFS mount inside of the 820 * specified non-global zone 821 * a_mountPointPrefix - pointer to string representing the prefix 822 * to be used when creating the mount point name in the 823 * specified zone's root directory 824 * Returns: boolean_t 825 * == B_TRUE - global zone directory mounted successfully 826 * == B_FALSE - failed to mount directory in specified zone 827 * NOTE: Any strings returned is placed in new storage for the 828 * calling function. The caller must use 'Free' to dispose 829 * of the storage once the strings are no longer needed. 830 */ 831 832boolean_t 833z_mount_in_lz(char **r_lzMountPoint, char **r_lzRootPath, char *a_zoneName, 834 char *a_gzPath, char *a_mountPointPrefix) 835{ 836 char lzRootPath[MAXPATHLEN] = {'\0'}; 837 char uuid[MAXPATHLEN] = {'\0'}; 838 char gzMountPoint[MAXPATHLEN] = {'\0'}; 839 char lzMountPoint[MAXPATHLEN] = {'\0'}; 840 hrtime_t hretime; 841 int err; 842 int slen; 843 struct tm tstruct; 844 time_t thetime; 845 zoneid_t zid; 846 847 /* entry assertions */ 848 849 assert(a_zoneName != (char *)NULL); 850 assert(*a_zoneName != '\0'); 851 assert(a_gzPath != (char *)NULL); 852 assert(*a_gzPath != '\0'); 853 assert(r_lzMountPoint != (char **)NULL); 854 assert(r_lzRootPath != (char **)NULL); 855 856 /* entry debugging info */ 857 858 _z_echoDebug(DBG_ZONES_MOUNT_IN_LZ_ENTRY, a_zoneName, a_gzPath); 859 860 /* reset returned non-global zone mount point path handle */ 861 862 *r_lzMountPoint = (char *)NULL; 863 *r_lzRootPath = (char *)NULL; 864 865 /* if zones are not implemented, return FALSE */ 866 867 if (z_zones_are_implemented() == B_FALSE) { 868 return (B_FALSE); 869 } 870 871 /* error if global zone path is not absolute */ 872 873 if (*a_gzPath != '/') { 874 _z_program_error(ERR_GZPATH_NOT_ABSOLUTE, a_gzPath); 875 return (B_FALSE); 876 } 877 878 /* error if global zone path does not exist */ 879 880 if (_z_is_directory(a_gzPath) != 0) { 881 _z_program_error(ERR_GZPATH_NOT_DIR, a_gzPath, strerror(errno)); 882 return (B_FALSE); 883 } 884 885 /* verify that specified non-global zone exists */ 886 887 err = zone_get_id(a_zoneName, &zid); 888 if (err != Z_OK) { 889 _z_program_error(ERR_GET_ZONEID, a_zoneName, 890 zonecfg_strerror(err)); 891 return (B_FALSE); 892 } 893 894 /* obtain global zone path to non-global zones root file system */ 895 896 err = zone_get_rootpath(a_zoneName, lzRootPath, sizeof (lzRootPath)); 897 if (err != Z_OK) { 898 _z_program_error(ERR_NO_ZONE_ROOTPATH, a_zoneName, 899 zonecfg_strerror(err)); 900 return (B_FALSE); 901 } 902 903 if (lzRootPath[0] == '\0') { 904 _z_program_error(ERR_ROOTPATH_EMPTY, a_zoneName); 905 return (B_FALSE); 906 } 907 908 /* 909 * lofs resolve the non-global zone's root path first in case 910 * its in a path that's been lofs mounted read-only. 911 * (e.g. This happens when we're tyring to patch a zone in an ABE 912 * that lives on a filesystem that the ABE shares with the currently 913 * running BE.) 914 */ 915 z_resolve_lofs(lzRootPath, sizeof (lzRootPath)); 916 917 /* verify that the root path exists */ 918 919 if (_z_is_directory(lzRootPath) != 0) { 920 _z_program_error(ERR_LZROOT_NOTDIR, lzRootPath, 921 strerror(errno)); 922 return (B_FALSE); 923 } 924 925 /* 926 * generate a unique key - the key is the same length as unique uid 927 * but contains different information that is as unique as can be made; 928 * include current hires time (nanosecond real timer). Such a unique 929 * i.d. will look like: 930 * 0203104092-1145345-0004e94d6af481a0 931 */ 932 933 hretime = gethrtime(); 934 935 thetime = time((time_t *)NULL); 936 (void) localtime_r(&thetime, &tstruct); 937 938 slen = snprintf(uuid, sizeof (uuid), 939 UUID_FORMAT, 940 tstruct.tm_mday, tstruct.tm_mon, tstruct.tm_year, 941 tstruct.tm_yday, tstruct.tm_hour, tstruct.tm_min, 942 tstruct.tm_sec, tstruct.tm_wday, hretime); 943 if (slen > sizeof (uuid)) { 944 _z_program_error(ERR_GZMOUNT_SNPRINTFUUID_FAILED, 945 UUID_FORMAT, sizeof (uuid)); 946 return (B_FALSE); 947 } 948 949 /* create the global zone mount point */ 950 951 slen = snprintf(gzMountPoint, sizeof (gzMountPoint), "%s/.SUNW_%s_%s", 952 lzRootPath, 953 a_mountPointPrefix ? a_mountPointPrefix : "zones", uuid); 954 if (slen > sizeof (gzMountPoint)) { 955 _z_program_error(ERR_GZMOUNT_SNPRINTFGMP_FAILED, 956 "%s/.SUNW_%s_%s", lzRootPath, 957 a_mountPointPrefix ? a_mountPointPrefix : "zones", 958 uuid, sizeof (gzMountPoint)); 959 return (B_FALSE); 960 } 961 962 slen = snprintf(lzMountPoint, sizeof (lzMountPoint), "%s", 963 gzMountPoint+strlen(lzRootPath)); 964 if (slen > sizeof (lzMountPoint)) { 965 _z_program_error(ERR_GZMOUNT_SNPRINTFLMP_FAILED, 966 "%s", gzMountPoint+strlen(lzRootPath), 967 sizeof (lzMountPoint)); 968 return (B_FALSE); 969 } 970 971 _z_echoDebug(DBG_MNTPT_NAMES, a_gzPath, a_zoneName, gzMountPoint, 972 lzMountPoint); 973 974 /* error if the mount point already exists */ 975 976 if (_z_is_directory(gzMountPoint) == 0) { 977 _z_program_error(ERR_ZONEROOT_NOTDIR, gzMountPoint, 978 a_zoneName, strerror(errno)); 979 return (B_FALSE); 980 } 981 982 /* create the temporary mount point */ 983 984 if (mkdir(gzMountPoint, 0600) != 0) { 985 _z_program_error(ERR_MNTPT_MKDIR, gzMountPoint, a_zoneName, 986 strerror(errno)); 987 return (B_FALSE); 988 } 989 990 /* mount the global zone path on the non-global zone root file system */ 991 992 err = mount(a_gzPath, gzMountPoint, MS_RDONLY|MS_DATA, "lofs", 993 (char *)NULL, 0, (char *)NULL, 0); 994 if (err != 0) { 995 _z_program_error(ERR_GZMOUNT_FAILED, a_gzPath, 996 gzMountPoint, a_zoneName, strerror(errno)); 997 return (B_FALSE); 998 } 999 1000 /* success - return both mountpoints to caller */ 1001 1002 *r_lzMountPoint = _z_strdup(gzMountPoint); 1003 1004 *r_lzRootPath = _z_strdup(lzMountPoint); 1005 1006 /* return success */ 1007 1008 return (B_TRUE); 1009} 1010 1011/* 1012 * Name: z_non_global_zones_exist 1013 * Description: Determine if any non-global native zones exist 1014 * Arguments: None. 1015 * Returns: boolean_t 1016 * == B_TRUE - at least one non-global native zone exists 1017 * == B_FALSE - no non-global native zone exists 1018 */ 1019 1020boolean_t 1021z_non_global_zones_exist(void) 1022{ 1023 FILE *zoneIndexFP; 1024 boolean_t anyExist = B_FALSE; 1025 struct zoneent *ze; 1026 zone_spec_t *zent; 1027 1028 /* if zones are not implemented, return FALSE */ 1029 1030 if (z_zones_are_implemented() == B_FALSE) { 1031 return (B_FALSE); 1032 } 1033 1034 /* determine if any zones are configured */ 1035 zoneIndexFP = setzoneent(); 1036 if (zoneIndexFP == NULL) { 1037 return (B_FALSE); 1038 } 1039 1040 /* index file open; scan all zones; see if any are at least installed */ 1041 1042 while ((ze = getzoneent_private(zoneIndexFP)) != NULL) { 1043 /* 1044 * If the user specified an explicit zone list, then ignore any 1045 * zones that aren't on that list. 1046 */ 1047 if ((zent = _z_global_data._zone_spec) != NULL) { 1048 while (zent != NULL) { 1049 if (strcmp(zent->zl_name, ze->zone_name) == 0) 1050 break; 1051 zent = zent->zl_next; 1052 } 1053 if (zent == NULL) { 1054 free(ze); 1055 continue; 1056 } 1057 } 1058 1059 /* skip the global zone */ 1060 if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0) { 1061 free(ze); 1062 continue; 1063 } 1064 1065 /* skip any branded zones */ 1066 if (z_is_zone_branded(ze->zone_name)) { 1067 free(ze); 1068 continue; 1069 } 1070 1071 /* is this zone installed? */ 1072 if (ze->zone_state >= ZONE_STATE_INSTALLED) { 1073 free(ze); 1074 anyExist = B_TRUE; 1075 break; 1076 } 1077 free(ze); 1078 } 1079 1080 /* close the index file */ 1081 1082 endzoneent(zoneIndexFP); 1083 1084 /* return results */ 1085 1086 return (anyExist); 1087} 1088 1089/* 1090 * Name: z_on_zone_spec 1091 * Description: Determine if named zone is on the zone_spec list. 1092 * Arguments: Pointer to name to test. 1093 * Returns: B_TRUE if named zone is on the list or if the user specified 1094 * no list at all (all zones is the default), B_FALSE otherwise. 1095 */ 1096 1097boolean_t 1098z_on_zone_spec(const char *zonename) 1099{ 1100 zone_spec_t *zent; 1101 1102 /* entry assertions */ 1103 1104 assert(zonename != NULL); 1105 assert(*zonename != '\0'); 1106 1107 /* return true if zones not implemented or no zone spec list defined */ 1108 1109 if (!z_zones_are_implemented() || _z_global_data._zone_spec == NULL) { 1110 return (B_TRUE); 1111 } 1112 1113 /* return true if named zone is on the zone spec list */ 1114 1115 for (zent = _z_global_data._zone_spec; 1116 zent != NULL; zent = zent->zl_next) { 1117 if (strcmp(zent->zl_name, zonename) == 0) 1118 return (B_TRUE); 1119 } 1120 1121 /* named zone is not on the zone spec list */ 1122 1123 return (B_FALSE); 1124} 1125 1126/* 1127 * Name: z_running_in_global_zone 1128 * Description: Determine if running in the "global" zone 1129 * Arguments: void 1130 * Returns: boolean_t 1131 * == B_TRUE - running in global zone 1132 * == B_FALSE - not running in global zone 1133 */ 1134 1135boolean_t 1136z_running_in_global_zone(void) 1137{ 1138 static boolean_t _zoneIdDetermined = B_FALSE; 1139 static boolean_t _zoneIsGlobal = B_FALSE; 1140 1141 /* if ID has not been determined, cache it now */ 1142 1143 if (!_zoneIdDetermined) { 1144 _zoneIdDetermined = B_TRUE; 1145 _zoneIsGlobal = _z_running_in_global_zone(); 1146 } 1147 1148 return (_zoneIsGlobal); 1149} 1150 1151/* 1152 * Name: z_set_output_functions 1153 * Description: Link program specific output functions to this library. 1154 * Arguments: a_echo_fcn - (_z_printf_fcn_t) 1155 * Function to call to cause "normal operation" messages 1156 * to be output/displayed 1157 * a_echo_debug_fcn - (_z_printf_fcn_t) 1158 * Function to call to cause "debugging" messages 1159 * to be output/displayed 1160 * a_progerr_fcn - (_z_printf_fcn_t) 1161 * Function to call to cause "program error" messages 1162 * to be output/displayed 1163 * Returns: void 1164 * NOTE: If NULL is specified for any function, then the functionality 1165 * associated with that function is disabled. 1166 * NOTE: The function pointers provided must call a function that 1167 * takes two arguments: 1168 * function(char *format, char *message) 1169 * Any registered function will be called like: 1170 * function("%s", "message") 1171 */ 1172 1173void 1174z_set_output_functions(_z_printf_fcn_t a_echo_fcn, 1175 _z_printf_fcn_t a_echo_debug_fcn, 1176 _z_printf_fcn_t a_progerr_fcn) 1177{ 1178 _z_global_data._z_echo = a_echo_fcn; 1179 _z_global_data._z_echo_debug = a_echo_debug_fcn; 1180 _z_global_data._z_progerr = a_progerr_fcn; 1181} 1182 1183/* 1184 * Name: z_set_zone_root 1185 * Description: Set root for zones library operations 1186 * Arguments: Path to root of boot environment containing zone; must be 1187 * absolute. 1188 * Returns: None. 1189 * NOTE: Must be called before performing any zone-related operations. 1190 * (Currently called directly by set_inst_root() during -R 1191 * argument handling.) 1192 */ 1193 1194void 1195z_set_zone_root(const char *zroot) 1196{ 1197 char *rootdir; 1198 1199 /* if zones are not implemented, just return */ 1200 1201 if (!z_zones_are_implemented()) 1202 return; 1203 1204 /* entry assertions */ 1205 1206 assert(zroot != NULL); 1207 1208 rootdir = _z_strdup((char *)zroot); 1209 z_canoninplace(rootdir); 1210 1211 if (strcmp(rootdir, "/") == 0) { 1212 rootdir[0] = '\0'; 1213 } 1214 1215 /* free any existing cached root path */ 1216 if (*_z_global_data._z_root_dir != '\0') { 1217 free(_z_global_data._z_root_dir); 1218 _z_global_data._z_root_dir = NULL; 1219 } 1220 1221 /* store duplicate of new zone root path */ 1222 1223 if (*rootdir != '\0') { 1224 _z_global_data._z_root_dir = _z_strdup(rootdir); 1225 } else { 1226 _z_global_data._z_root_dir = ""; 1227 } 1228 1229 /* set zone root path */ 1230 1231 zonecfg_set_root(rootdir); 1232 1233 free(rootdir); 1234} 1235 1236/* 1237 * Name: z_set_zone_spec 1238 * Description: Set list of zones on which actions will be performed. 1239 * Arguments: Whitespace-separated list of zone names. 1240 * Returns: 0 on success, -1 on error. 1241 * NOTES: Will call _z_program_error if argument can't be parsed or 1242 * memory not available. 1243 */ 1244 1245int 1246z_set_zone_spec(const char *zlist) 1247{ 1248 const char *zend; 1249 ptrdiff_t zlen; 1250 zone_spec_t *zent; 1251 zone_spec_t *zhead; 1252 zone_spec_t **znextp = &zhead; 1253 1254 /* entry assertions */ 1255 1256 assert(zlist != NULL); 1257 1258 /* parse list to zone_spec_t list, store in global data */ 1259 1260 for (;;) { 1261 while (isspace(*zlist)) { 1262 zlist++; 1263 } 1264 if (*zlist == '\0') { 1265 break; 1266 } 1267 for (zend = zlist; *zend != '\0'; zend++) { 1268 if (isspace(*zend)) { 1269 break; 1270 } 1271 } 1272 zlen = ((ptrdiff_t)zend) - ((ptrdiff_t)zlist); 1273 if (zlen >= ZONENAME_MAX) { 1274 _z_program_error(ERR_ZONE_NAME_ILLEGAL, zlen, zlist); 1275 return (-1); 1276 } 1277 zent = _z_malloc(sizeof (*zent)); 1278 (void) memcpy(zent->zl_name, zlist, zlen); 1279 zent->zl_name[zlen] = '\0'; 1280 zent->zl_used = B_FALSE; 1281 *znextp = zent; 1282 znextp = &zent->zl_next; 1283 zlist = zend; 1284 } 1285 *znextp = NULL; 1286 1287 if (zhead == NULL) { 1288 _z_program_error(ERR_ZONE_LIST_EMPTY); 1289 return (-1); 1290 } 1291 1292 _z_global_data._zone_spec = zhead; 1293 return (0); 1294} 1295 1296/* 1297 * Name: z_umount_lz_mount 1298 * Description: Unmount directory mounted with z_mount_in_lz 1299 * Arguments: a_lzMountPointer - pointer to string returned by z_mount_in_lz 1300 * Returns: boolean_t 1301 * == B_TRUE - successfully unmounted directory 1302 * == B_FALSE - failed to unmount directory 1303 */ 1304 1305boolean_t 1306z_umount_lz_mount(char *a_lzMountPoint) 1307{ 1308 int err; 1309 1310 /* entry assertions */ 1311 1312 assert(a_lzMountPoint != (char *)NULL); 1313 assert(*a_lzMountPoint != '\0'); 1314 1315 /* entry debugging info */ 1316 1317 _z_echoDebug(DBG_ZONES_UNMOUNT_FROM_LZ_ENTRY, a_lzMountPoint); 1318 1319 /* if zones are not implemented, return TRUE */ 1320 1321 if (z_zones_are_implemented() == B_FALSE) { 1322 return (B_FALSE); 1323 } 1324 1325 /* error if global zone path is not absolute */ 1326 1327 if (*a_lzMountPoint != '/') { 1328 _z_program_error(ERR_LZMNTPT_NOT_ABSOLUTE, a_lzMountPoint); 1329 return (B_FALSE); 1330 } 1331 1332 /* verify mount point exists */ 1333 1334 if (_z_is_directory(a_lzMountPoint) != 0) { 1335 _z_program_error(ERR_LZMNTPT_NOTDIR, a_lzMountPoint, 1336 strerror(errno)); 1337 return (B_FALSE); 1338 } 1339 1340 /* unmount */ 1341 1342 err = umount2(a_lzMountPoint, 0); 1343 if (err != 0) { 1344 _z_program_error(ERR_GZUMOUNT_FAILED, a_lzMountPoint, 1345 strerror(errno)); 1346 return (B_FALSE); 1347 } 1348 1349 /* remove the mount point */ 1350 1351 (void) remove(a_lzMountPoint); 1352 1353 /* return success */ 1354 1355 return (B_TRUE); 1356} 1357 1358/* 1359 * Name: z_unlock_this_zone 1360 * Description: unlock this zone 1361 * Arguments: a_lflags - [RO, *RO] - (ZLOCKS_T) 1362 * Flags indicating which locks to release 1363 * Returns: boolean_t 1364 * == B_TRUE - success specified locks released 1365 * == B_FALSE - failure specified locks may not be released 1366 * NOTE: the lock objects for "this zone" are maintained internally. 1367 */ 1368 1369boolean_t 1370z_unlock_this_zone(ZLOCKS_T a_lflags) 1371{ 1372 boolean_t b; 1373 boolean_t errors = B_FALSE; 1374 char *zoneName; 1375 1376 /* entry assertions */ 1377 1378 assert(a_lflags != ZLOCKS_NONE); 1379 1380 /* entry debugging info */ 1381 1382 _z_echoDebug(DBG_ZONES_ULK_THIS, a_lflags); 1383 1384 /* return if no objects locked */ 1385 1386 if ((_z_global_data._z_ObjectLocks == (char *)NULL) || 1387 (*_z_global_data._z_ObjectLocks == '\0')) { 1388 return (B_TRUE); 1389 } 1390 1391 zoneName = z_get_zonename(); 1392 1393 /* unlock patch administration */ 1394 1395 if (a_lflags & ZLOCKS_PATCH_ADMIN) { 1396 b = _z_unlock_zone_object(&_z_global_data._z_ObjectLocks, 1397 zoneName, LOBJ_PATCHADMIN, ERR_ZONES_ULK_THIS_PATCH); 1398 if (!b) { 1399 errors = B_TRUE; 1400 } 1401 } 1402 1403 /* unlock package administration */ 1404 1405 if (a_lflags & ZLOCKS_PKG_ADMIN) { 1406 b = _z_unlock_zone_object(&_z_global_data._z_ObjectLocks, 1407 zoneName, LOBJ_PKGADMIN, ERR_ZONES_ULK_THIS_PACKAGE); 1408 if (!b) { 1409 errors = B_TRUE; 1410 } 1411 } 1412 1413 /* unlock zone administration */ 1414 1415 if (a_lflags & ZLOCKS_ZONE_ADMIN) { 1416 b = _z_unlock_zone_object(&_z_global_data._z_ObjectLocks, 1417 zoneName, LOBJ_ZONEADMIN, ERR_ZONES_ULK_THIS_ZONES); 1418 if (!b) { 1419 errors = B_TRUE; 1420 } 1421 } 1422 1423 (void) free(zoneName); 1424 return (!errors); 1425} 1426 1427/* 1428 * Name: z_unlock_zones 1429 * Description: unlock specified zones 1430 * Arguments: a_zlst - zoneList_t object describing zones to unlock 1431 * a_lflags - [RO, *RO] - (ZLOCKS_T) 1432 * Flags indicating which locks to release 1433 * Returns: boolean_t 1434 * == B_TRUE - success, zones unlocked 1435 * == B_FALSE - failure, zones not unlocked 1436 */ 1437 1438boolean_t 1439z_unlock_zones(zoneList_t a_zlst, ZLOCKS_T a_lflags) 1440{ 1441 boolean_t b; 1442 boolean_t errors = B_FALSE; 1443 int i; 1444 1445 /* entry assertions */ 1446 1447 assert(a_lflags != ZLOCKS_NONE); 1448 1449 /* entry debugging info */ 1450 1451 _z_echoDebug(DBG_ZONES_ULK_ZONES, a_lflags); 1452 1453 /* if zones are not implemented, return TRUE */ 1454 1455 if (z_zones_are_implemented() == B_FALSE) { 1456 _z_echoDebug(DBG_ZONES_ULK_ZONES_UNIMP); 1457 return (B_TRUE); 1458 } 1459 1460 /* ignore empty list */ 1461 1462 if (a_zlst == (zoneList_t)NULL) { 1463 _z_echoDebug(DBG_ZONES_ULK_ZONES_NOZONES); 1464 /* unlock this zone before returning */ 1465 return (z_unlock_this_zone(a_lflags)); 1466 } 1467 1468 /* zones exist */ 1469 1470 _z_echoDebug(DBG_ZONES_ULK_ZONES_EXIST); 1471 1472 /* 1473 * unlock each listed zone that is currently running 1474 */ 1475 1476 for (i = 0; (a_zlst[i]._zlName != (char *)NULL); i++) { 1477 /* ignore zone if not locked */ 1478 if (!(a_zlst[i]._zlStatus & ZST_LOCKED)) { 1479 continue; 1480 } 1481 1482 /* ignore zone if not running */ 1483 if (a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_RUNNING && 1484 a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_MOUNTED) { 1485 continue; 1486 } 1487 1488 /* unlock this zone */ 1489 b = _z_unlock_zone(&a_zlst[i], a_lflags); 1490 1491 if (b != B_TRUE) { 1492 errors = B_TRUE; 1493 } else { 1494 /* mark zone as unlocked */ 1495 a_zlst[i]._zlStatus &= ~ZST_LOCKED; 1496 } 1497 } 1498 1499 /* unlock this zone */ 1500 1501 if (z_unlock_this_zone(a_lflags) != B_TRUE) { 1502 errors = B_TRUE; 1503 } 1504 1505 return (errors); 1506} 1507 1508/* 1509 * Name: z_verify_zone_spec 1510 * Description: Verify list of zones on which actions will be performed. 1511 * Arguments: None. 1512 * Returns: 0 on success, -1 on error. 1513 * NOTES: Will call _z_program_error if there are zones on the specified 1514 * list that don't exist on the system. Requires that 1515 * z_set_zone_root is called first (if it is called at all). 1516 */ 1517 1518int 1519z_verify_zone_spec(void) 1520{ 1521 FILE *zoneIndexFP; 1522 boolean_t errors; 1523 char zoneIndexPath[MAXPATHLEN]; 1524 struct zoneent *ze; 1525 zone_spec_t *zent; 1526 1527 if (!z_zones_are_implemented()) { 1528 _z_program_error(ERR_ZONES_NOT_IMPLEMENTED); 1529 return (-1); 1530 } 1531 1532 zoneIndexFP = setzoneent(); 1533 if (zoneIndexFP == NULL) { 1534 _z_program_error(ERR_ZONEINDEX_OPEN, zoneIndexPath, 1535 strerror(errno)); 1536 return (-1); 1537 } 1538 1539 while ((ze = getzoneent_private(zoneIndexFP)) != NULL) { 1540 for (zent = _z_global_data._zone_spec; 1541 zent != NULL; zent = zent->zl_next) { 1542 if (strcmp(zent->zl_name, ze->zone_name) == 0) { 1543 zent->zl_used = B_TRUE; 1544 break; 1545 } 1546 } 1547 free(ze); 1548 } 1549 endzoneent(zoneIndexFP); 1550 1551 errors = B_FALSE; 1552 for (zent = _z_global_data._zone_spec; 1553 zent != NULL; zent = zent->zl_next) { 1554 if (!zent->zl_used) { 1555 _z_program_error(ERR_ZONE_NONEXISTENT, zent->zl_name); 1556 errors = B_TRUE; 1557 } 1558 } 1559 return (errors ? -1 : 0); 1560} 1561 1562/* 1563 * Name: z_zlist_change_zone_state 1564 * Description: Change the current state of the specified zone 1565 * Arguments: a_zlst - handle to zoneList_t object describing all zones 1566 * a_zoneIndex - index into a_zlst of the zone to return the 1567 * a_newState - the state to put the specified zone in 1568 * Returns: boolean_t 1569 * == B_TRUE - the zone is in the new state 1570 * == B_FALSE - unable to transition the zone to the 1571 * specified state 1572 * NOTE: This changes the "current kernel" state of the specified 1573 * zone. For example, to boot the zone, change the state 1574 * to "ZONE_STATE_RUNNING". To halt the zone, change the 1575 * state to "ZONE_STATE_INSTALLED". 1576 */ 1577 1578boolean_t 1579z_zlist_change_zone_state(zoneList_t a_zlst, int a_zoneIndex, 1580 zone_state_t a_newState) 1581{ 1582 int i; 1583 1584 /* entry debugging info */ 1585 1586 _z_echoDebug(DBG_ZONES_CHG_Z_STATE_ENTRY, a_zoneIndex, a_newState); 1587 1588 /* ignore empty list */ 1589 1590 if (a_zlst == (zoneList_t)NULL) { 1591 return (B_FALSE); 1592 } 1593 1594 /* find the specified zone in the list */ 1595 1596 for (i = 0; (i != a_zoneIndex) && 1597 (a_zlst[i]._zlName != (char *)NULL); i++) 1598 ; 1599 1600 /* return error if the specified zone does not exist */ 1601 1602 if (a_zlst[i]._zlName == (char *)NULL) { 1603 return (B_FALSE); 1604 } 1605 1606 /* return success if the zone is already in this state */ 1607 1608 if (a_zlst[i]._zlCurrKernelStatus == a_newState) { 1609 return (B_TRUE); 1610 } 1611 1612 /* take action on new state to set zone to */ 1613 1614 _z_echoDebug(DBG_ZONES_CHG_Z_STATE, a_zlst[i]._zlName, 1615 a_zlst[i]._zlCurrKernelStatus, a_newState); 1616 1617 switch (a_newState) { 1618 case ZONE_STATE_RUNNING: 1619 case ZONE_STATE_MOUNTED: 1620 /* these states mean "boot the zone" */ 1621 return (_z_make_zone_running(&a_zlst[i])); 1622 1623 case ZONE_STATE_DOWN: 1624 case ZONE_STATE_INSTALLED: 1625 /* these states mean "halt the zone" */ 1626 return (_z_make_zone_down(&a_zlst[i])); 1627 1628 case ZONE_STATE_READY: 1629 return (_z_make_zone_ready(&a_zlst[i])); 1630 1631 case ZONE_STATE_CONFIGURED: 1632 case ZONE_STATE_INCOMPLETE: 1633 case ZONE_STATE_SHUTTING_DOWN: 1634 default: 1635 /* do not know how to change zone to this state */ 1636 return (B_FALSE); 1637 } 1638} 1639 1640/* 1641 * Name: z_is_zone_branded 1642 * Description: Determine whether zone has a non-native brand 1643 * Arguments: a_zoneName - name of the zone to check for branding 1644 * Returns: boolean_t 1645 * == B_TRUE - zone has a non-native brand 1646 * == B_FALSE - zone is native 1647 */ 1648boolean_t 1649z_is_zone_branded(char *zoneName) 1650{ 1651 char brandname[MAXNAMELEN]; 1652 int err; 1653 1654 /* if zones are not implemented, return FALSE */ 1655 if (!z_zones_are_implemented()) { 1656 return (B_FALSE); 1657 } 1658 1659 /* if brands are not implemented, return FALSE */ 1660 if (!z_brands_are_implemented()) { 1661 return (B_FALSE); 1662 } 1663 1664 err = zone_get_brand(zoneName, brandname, sizeof (brandname)); 1665 if (err != Z_OK) { 1666 _z_program_error(ERR_BRAND_GETBRAND, zonecfg_strerror(err)); 1667 return (B_FALSE); 1668 } 1669 1670 /* 1671 * Both "native" and "cluster" are native brands 1672 * that use the standard facilities in the areas 1673 * of packaging/installation/patching/update. 1674 */ 1675 if (streq(brandname, NATIVE_BRAND_NAME) || 1676 streq(brandname, CLUSTER_BRAND_NAME)) { 1677 return (B_FALSE); 1678 } else { 1679 return (B_TRUE); 1680 } 1681} 1682 1683/* 1684 * Name: z_is_zone_brand_in_list 1685 * Description: Determine whether zone's brand has a match in the list 1686 * brands passed in. 1687 * Arguments: zoneName - name of the zone to check for branding 1688 * list - list of brands to check the zone against 1689 * Returns: boolean_t 1690 * == B_TRUE - zone has a matching brand 1691 * == B_FALSE - zone brand is not in list 1692 */ 1693boolean_t 1694z_is_zone_brand_in_list(char *zoneName, zoneBrandList_t *list) 1695{ 1696 char brandname[MAXNAMELEN]; 1697 int err; 1698 zoneBrandList_t *sp; 1699 1700 if (zoneName == NULL || list == NULL) 1701 return (B_FALSE); 1702 1703 /* if zones are not implemented, return FALSE */ 1704 if (!z_zones_are_implemented()) { 1705 return (B_FALSE); 1706 } 1707 1708 /* if brands are not implemented, return FALSE */ 1709 if (!z_brands_are_implemented()) { 1710 return (B_FALSE); 1711 } 1712 1713 err = zone_get_brand(zoneName, brandname, sizeof (brandname)); 1714 if (err != Z_OK) { 1715 _z_program_error(ERR_BRAND_GETBRAND, zonecfg_strerror(err)); 1716 return (B_FALSE); 1717 } 1718 1719 for (sp = list; sp != NULL; sp = sp->next) { 1720 if (sp->string_ptr != NULL && 1721 strcmp(sp->string_ptr, brandname) == 0) { 1722 return (B_TRUE); 1723 } 1724 } 1725 1726 return (B_FALSE); 1727} 1728 1729/* 1730 * Name: z_zlist_get_current_state 1731 * Description: Determine the current kernel state of the specified zone 1732 * Arguments: a_zlst - handle to zoneList_t object describing all zones 1733 * a_zoneIndex - index into a_zlst of the zone to return 1734 * Returns: zone_state_t 1735 * The current state of the specified zone is returned 1736 */ 1737 1738zone_state_t 1739z_zlist_get_current_state(zoneList_t a_zlst, int a_zoneIndex) 1740{ 1741 int i; 1742 1743 /* ignore empty list */ 1744 1745 if (a_zlst == (zoneList_t)NULL) { 1746 return (ZONE_STATE_INCOMPLETE); 1747 } 1748 1749 /* find the specified zone in the list */ 1750 1751 for (i = 0; (i != a_zoneIndex) && 1752 (a_zlst[i]._zlName != (char *)NULL); i++) 1753 ; 1754 1755 /* return error if the specified zone does not exist */ 1756 1757 if (a_zlst[i]._zlName == (char *)NULL) { 1758 return (ZONE_STATE_INCOMPLETE); 1759 } 1760 1761 /* return selected zone's current kernel state */ 1762 1763 _z_echoDebug(DBG_ZONES_GET_ZONE_STATE, 1764 a_zlst[i]._zlName ? a_zlst[i]._zlName : "", 1765 a_zlst[i]._zlCurrKernelStatus); 1766 1767 return (a_zlst[i]._zlCurrKernelStatus); 1768} 1769 1770/* 1771 * Name: z_zlist_get_original_state 1772 * Description: Return the original kernal state of the specified zone 1773 * Arguments: a_zlst - handle to zoneList_t object describing all zones 1774 * a_zoneIndex - index into a_zlst of the zone to return the 1775 * Returns: zone_state_t 1776 * The original state of the specified zone is returned. 1777 * This is the state of the zone when the zoneList_t 1778 * object was first generated. 1779 */ 1780 1781zone_state_t 1782z_zlist_get_original_state(zoneList_t a_zlst, int a_zoneIndex) 1783{ 1784 int i; 1785 1786 /* ignore empty list */ 1787 1788 if (a_zlst == (zoneList_t)NULL) { 1789 return (ZONE_STATE_INCOMPLETE); 1790 } 1791 1792 /* find the specified zone in the list */ 1793 1794 for (i = 0; (i != a_zoneIndex) && 1795 (a_zlst[i]._zlName != (char *)NULL); i++) 1796 ; 1797 1798 /* return error if the specified zone does not exist */ 1799 1800 if (a_zlst[i]._zlName == (char *)NULL) { 1801 return (ZONE_STATE_INCOMPLETE); 1802 } 1803 1804 /* return selected zone's original kernel state */ 1805 1806 return (a_zlst[i]._zlOrigKernelStatus); 1807} 1808 1809/* 1810 * Name: z_zlist_get_scratch 1811 * Description: Determine name of scratch zone 1812 * Arguments: a_zlst - handle to zoneList_t object describing all zones 1813 * a_zoneIndex - index into a_zlst of the zone to use 1814 * Return: char * 1815 * == NULL - zone name could not be determined 1816 * != NULL - pointer to string representing scratch zone 1817 * NOTE: Any name returned is placed in static storage that must 1818 * NEVER be free()ed by the caller. 1819 */ 1820 1821char * 1822z_zlist_get_scratch(zoneList_t a_zlst, int a_zoneIndex) 1823{ 1824 int i; 1825 1826 /* ignore empty list */ 1827 1828 if (a_zlst == NULL) 1829 return (NULL); 1830 1831 /* find the specified zone in the list */ 1832 1833 for (i = 0; i != a_zoneIndex; i++) { 1834 if (a_zlst[i]._zlName == NULL) 1835 return (NULL); 1836 } 1837 1838 /* return selected zone's scratch name */ 1839 1840 return (a_zlst[i]._zlScratchName == NULL ? a_zlst[i]._zlName : 1841 a_zlst[i]._zlScratchName); 1842} 1843 1844/* 1845 * Name: z_zlist_get_zonename 1846 * Description: Determine name of specified zone 1847 * Arguments: a_zlst - handle to zoneList_t object describing all zones 1848 * a_zoneIndex - index into a_zlst of the zone to return the 1849 * Return: char * 1850 * == NULL - zone name could not be determined 1851 * != NULL - pointer to string representing zone name 1852 * NOTE: Any zoneList_t returned is placed in static storage that must 1853 * NEVER be free()ed by the caller. 1854 */ 1855 1856char * 1857z_zlist_get_zonename(zoneList_t a_zlst, int a_zoneIndex) 1858{ 1859 int i; 1860 1861 /* ignore empty list */ 1862 1863 if (a_zlst == (zoneList_t)NULL) { 1864 return ((char *)NULL); 1865 } 1866 1867 /* find the specified zone in the list */ 1868 1869 for (i = 0; (i != a_zoneIndex) && 1870 (a_zlst[i]._zlName != (char *)NULL); i++) 1871 ; 1872 1873 /* return error if the specified zone does not exist */ 1874 1875 if (a_zlst[i]._zlName == (char *)NULL) { 1876 return (NULL); 1877 } 1878 1879 /* return selected zone's name */ 1880 1881 return (a_zlst[i]._zlName); 1882} 1883 1884/* 1885 * Name: z_zlist_get_zonepath 1886 * Description: Determine zonepath of specified zone 1887 * Arguments: a_zlst - handle to zoneList_t object describing all zones 1888 * a_zoneIndex - index into a_zlst of the zone to return 1889 * Return: char * 1890 * == NULL - zonepath could not be determined 1891 * != NULL - pointer to string representing zonepath 1892 * NOTE: Any zoneList_t returned is placed in static storage that must 1893 * NEVER be free()ed by the caller. 1894 */ 1895 1896char * 1897z_zlist_get_zonepath(zoneList_t a_zlst, int a_zoneIndex) 1898{ 1899 int i; 1900 1901 /* ignore empty list */ 1902 1903 if (a_zlst == (zoneList_t)NULL) { 1904 return ((char *)NULL); 1905 } 1906 1907 /* find the specified zone in the list */ 1908 1909 for (i = 0; (i != a_zoneIndex) && 1910 (a_zlst[i]._zlName != (char *)NULL); i++) 1911 ; 1912 1913 /* return error if the specified zone does not exist */ 1914 1915 if (a_zlst[i]._zlName == (char *)NULL) { 1916 return (NULL); 1917 } 1918 1919 /* return selected zone's zonepath */ 1920 1921 return (a_zlst[i]._zlPath); 1922} 1923 1924boolean_t 1925z_zlist_is_zone_runnable(zoneList_t a_zlst, int a_zoneIndex) 1926{ 1927 int i; 1928 1929 /* if zones are not implemented, return error */ 1930 1931 if (z_zones_are_implemented() == B_FALSE) { 1932 return (B_FALSE); 1933 } 1934 1935 /* ignore empty list */ 1936 1937 if (a_zlst == (zoneList_t)NULL) { 1938 return (B_FALSE); 1939 } 1940 1941 /* find the specified zone in the list */ 1942 1943 for (i = 0; (i != a_zoneIndex) && 1944 (a_zlst[i]._zlName != (char *)NULL); i++) 1945 ; 1946 1947 /* return error if the specified zone does not exist */ 1948 1949 if (a_zlst[i]._zlName == (char *)NULL) { 1950 return (B_FALSE); 1951 } 1952 1953 /* choose based on current state */ 1954 1955 switch (a_zlst[i]._zlCurrKernelStatus) { 1956 case ZONE_STATE_RUNNING: 1957 case ZONE_STATE_MOUNTED: 1958 /* already running */ 1959 return (B_TRUE); 1960 1961 case ZONE_STATE_INSTALLED: 1962 case ZONE_STATE_DOWN: 1963 case ZONE_STATE_READY: 1964 case ZONE_STATE_SHUTTING_DOWN: 1965 /* return false if the zone cannot be booted */ 1966 1967 if (a_zlst[i]._zlStatus & ZST_NOT_BOOTABLE) { 1968 return (B_FALSE); 1969 } 1970 1971 return (B_TRUE); 1972 1973 case ZONE_STATE_CONFIGURED: 1974 case ZONE_STATE_INCOMPLETE: 1975 default: 1976 /* cannot transition (boot) these states */ 1977 return (B_FALSE); 1978 } 1979} 1980 1981/* 1982 * Name: z_zlist_restore_zone_state 1983 * Description: Return the zone to the state it was originally in 1984 * Arguments: a_zlst - handle to zoneList_t object describing all zones 1985 * a_zoneIndex - index into a_zlst of the zone to return the 1986 * Returns: boolean_t 1987 * == B_TRUE - the zone's state has been restored 1988 * == B_FALSE - unable to transition the zone to its 1989 * original state 1990 */ 1991 1992boolean_t 1993z_zlist_restore_zone_state(zoneList_t a_zlst, int a_zoneIndex) 1994{ 1995 int i; 1996 1997 /* ignore empty list */ 1998 1999 if (a_zlst == (zoneList_t)NULL) { 2000 return (B_FALSE); 2001 } 2002 2003 /* find the specified zone in the list */ 2004 2005 for (i = 0; (i != a_zoneIndex) && 2006 (a_zlst[i]._zlName != (char *)NULL); i++) 2007 ; 2008 2009 /* return error if the specified zone does not exist */ 2010 2011 if (a_zlst[i]._zlName == (char *)NULL) { 2012 return (B_FALSE); 2013 } 2014 2015 /* transition the zone back to its original state */ 2016 2017 return (z_zlist_change_zone_state(a_zlst, 2018 a_zoneIndex, a_zlst[i]._zlOrigKernelStatus)); 2019} 2020 2021/* 2022 * Name: z_zone_exec 2023 * Description: Execute a Unix command in a specified zone and return results 2024 * Arguments: a_zoneName - pointer to string representing the name of the zone 2025 * to execute the specified command in 2026 * a_path - pointer to string representing the full path *in the 2027 * non-global zone named by a_zoneName* of the Unix command 2028 * to be executed 2029 * a_argv[] - Pointer to array of character strings representing 2030 * the arguments to be passed to the Unix command. The list 2031 * must be termianted with an element that is (char *)NULL 2032 * NOTE: a_argv[0] is the "command name" passed to the command 2033 * a_stdoutPath - Pointer to string representing the path to a file 2034 * into which all output to "stdout" from the Unix command 2035 * is placed. 2036 * == (char *)NULL - leave stdout open and pass through 2037 * == "/dev/null" - discard stdout output 2038 * a_strerrPath - Pointer to string representing the path to a file 2039 * into which all output to "stderr" from the Unix command 2040 * is placed. 2041 * == (char *)NULL - leave stderr open and pass through 2042 * == "/dev/null" - discard stderr output 2043 * a_fds - Pointer to array of integers representing file 2044 * descriptors to remain open during the call - all 2045 * file descriptors above STDERR_FILENO not in this 2046 * list will be closed. 2047 * Returns: int 2048 * The return (exit) code from the specified Unix command 2049 * Special return codes: 2050 * -1 : failure to exec process 2051 * -2 : could not create contract for greenline 2052 * -3 : fork() failed 2053 * -4 : could not open stdout capture file 2054 * -5 : error from 'waitpid' other than EINTR 2055 * -6 : zones are not supported 2056 * NOTE: All file descriptores other than 0, 1 and 2 are closed except 2057 * for those file descriptors listed in the a_fds array. 2058 */ 2059 2060int 2061z_zone_exec(const char *a_zoneName, const char *a_path, char *a_argv[], 2062 char *a_stdoutPath, char *a_stderrPath, int *a_fds) 2063{ 2064 int final_status; 2065 int lerrno; 2066 int status; 2067 int tmpl_fd; 2068 pid_t child_pid; 2069 pid_t result_pid; 2070 struct sigaction nact; 2071 struct sigaction oact; 2072 void (*funcSighup)(); 2073 void (*funcSigint)(); 2074 2075 /* if zones are not implemented, return TRUE */ 2076 2077 if (z_zones_are_implemented() == B_FALSE) { 2078 return (-6); /* -6 : zones are not supported */ 2079 } 2080 2081 if ((tmpl_fd = _zexec_init_template()) == -1) { 2082 _z_program_error(ERR_CANNOT_CREATE_CONTRACT, strerror(errno)); 2083 return (-2); /* -2 : could not create greenline contract */ 2084 } 2085 2086 /* 2087 * hold SIGINT/SIGHUP signals and reset signal received counter; 2088 * after the fork1() the parent and child need to setup their respective 2089 * interrupt handling and release the hold on the signals 2090 */ 2091 2092 (void) sighold(SIGINT); 2093 (void) sighold(SIGHUP); 2094 2095 _z_global_data._z_SigReceived = 0; /* no signals received */ 2096 2097 /* 2098 * fork off a new process to execute command in; 2099 * fork1() is used instead of vfork() so the child process can 2100 * perform operations that would modify the parent process if 2101 * vfork() were used 2102 */ 2103 2104 child_pid = fork1(); 2105 2106 if (child_pid < 0) { 2107 /* 2108 * ************************************************************* 2109 * fork failed! 2110 * ************************************************************* 2111 */ 2112 2113 (void) ct_tmpl_clear(tmpl_fd); 2114 (void) close(tmpl_fd); 2115 _z_program_error(ERR_FORK, strerror(errno)); 2116 2117 /* release hold on signals */ 2118 2119 (void) sigrelse(SIGHUP); 2120 (void) sigrelse(SIGINT); 2121 2122 return (-3); /* -3 : fork() failed */ 2123 } 2124 2125 if (child_pid == 0) { 2126 int i; 2127 2128 /* 2129 * ************************************************************* 2130 * This is the forked (child) process 2131 * ************************************************************* 2132 */ 2133 2134 (void) ct_tmpl_clear(tmpl_fd); 2135 (void) close(tmpl_fd); 2136 2137 /* reset any signals to default */ 2138 2139 for (i = 0; i < NSIG; i++) { 2140 (void) sigset(i, SIG_DFL); 2141 } 2142 2143 /* 2144 * close all file descriptors not in the a_fds list 2145 */ 2146 2147 (void) fdwalk(&_z_close_file_descriptors, (void *)a_fds); 2148 2149 /* 2150 * if a file for stdout is present, open the file and use the 2151 * file to capture stdout from the _zexec process 2152 */ 2153 2154 if (a_stdoutPath != (char *)NULL) { 2155 int stdoutfd; 2156 2157 stdoutfd = open(a_stdoutPath, 2158 O_WRONLY|O_CREAT|O_TRUNC, 0600); 2159 if (stdoutfd < 0) { 2160 _z_program_error(ERR_CAPTURE_FILE, a_stdoutPath, 2161 strerror(errno)); 2162 return (-4); 2163 } 2164 2165 (void) dup2(stdoutfd, STDOUT_FILENO); 2166 (void) close(stdoutfd); 2167 } 2168 2169 /* 2170 * if a file for stderr is present, open the file and use the 2171 * file to capture stderr from the _zexec process 2172 */ 2173 2174 if (a_stderrPath != (char *)NULL) { 2175 int stderrfd; 2176 2177 stderrfd = open(a_stderrPath, 2178 O_WRONLY|O_CREAT|O_TRUNC, 0600); 2179 if (stderrfd < 0) { 2180 _z_program_error(ERR_CAPTURE_FILE, a_stderrPath, 2181 strerror(errno)); 2182 return (-4); 2183 } 2184 2185 (void) dup2(stderrfd, STDERR_FILENO); 2186 (void) close(stderrfd); 2187 } 2188 2189 /* release all held signals */ 2190 2191 (void) sigrelse(SIGHUP); 2192 (void) sigrelse(SIGINT); 2193 2194 /* execute command in the specified non-global zone */ 2195 2196 _exit(_zexec(a_zoneName, a_path, a_argv)); 2197 } 2198 2199 /* 2200 * ********************************************************************* 2201 * This is the forking (parent) process 2202 * ********************************************************************* 2203 */ 2204 2205 /* register child process i.d. so signal handlers can pass signal on */ 2206 2207 _z_global_data._z_ChildProcessId = child_pid; 2208 2209 /* 2210 * setup signal handlers for SIGINT and SIGHUP and release hold 2211 */ 2212 2213 /* hook SIGINT to _z_sig_trap() */ 2214 2215 nact.sa_handler = _z_sig_trap; 2216 nact.sa_flags = SA_RESTART; 2217 (void) sigemptyset(&nact.sa_mask); 2218 2219 if (sigaction(SIGINT, &nact, &oact) < 0) { 2220 funcSigint = SIG_DFL; 2221 } else { 2222 funcSigint = oact.sa_handler; 2223 } 2224 2225 /* hook SIGHUP to _z_sig_trap() */ 2226 2227 nact.sa_handler = _z_sig_trap; 2228 nact.sa_flags = SA_RESTART; 2229 (void) sigemptyset(&nact.sa_mask); 2230 2231 if (sigaction(SIGHUP, &nact, &oact) < 0) { 2232 funcSighup = SIG_DFL; 2233 } else { 2234 funcSighup = oact.sa_handler; 2235 } 2236 2237 /* release hold on signals */ 2238 2239 (void) sigrelse(SIGHUP); 2240 (void) sigrelse(SIGINT); 2241 2242 (void) ct_tmpl_clear(tmpl_fd); 2243 (void) close(tmpl_fd); 2244 2245 /* 2246 * wait for the process to exit, reap child exit status 2247 */ 2248 2249 for (;;) { 2250 result_pid = waitpid(child_pid, &status, 0L); 2251 lerrno = (result_pid == -1 ? errno : 0); 2252 2253 /* break loop if child process status reaped */ 2254 2255 if (result_pid != -1) { 2256 break; 2257 } 2258 2259 /* break loop if not interrupted out of waitpid */ 2260 2261 if (errno != EINTR) { 2262 break; 2263 } 2264 } 2265 2266 /* reset child process i.d. so signal handlers do not pass signals on */ 2267 2268 _z_global_data._z_ChildProcessId = -1; 2269 2270 /* 2271 * If the child process terminated due to a call to exit(), then 2272 * set results equal to the 8-bit exit status of the child process; 2273 * otherwise, set the exit status to "-1" indicating that the child 2274 * exited via a signal. 2275 */ 2276 2277 if (WIFEXITED(status)) { 2278 final_status = WEXITSTATUS(status); 2279 if ((_z_global_data._z_SigReceived != 0) && 2280 (final_status == 0)) { 2281 final_status = 1; 2282 } 2283 } else { 2284 final_status = -1; /* -1 : failure to exec process */ 2285 } 2286 2287 /* determine proper exit code */ 2288 2289 if (result_pid == -1) { 2290 final_status = -5; /* -5 : error from waitpid not EINTR */ 2291 } else if (_z_global_data._z_SigReceived != 0) { 2292 final_status = -7; /* -7 : interrupt received */ 2293 } 2294 2295 /* 2296 * reset signal handlers 2297 */ 2298 2299 /* reset SIGINT */ 2300 2301 nact.sa_handler = funcSigint; 2302 nact.sa_flags = SA_RESTART; 2303 (void) sigemptyset(&nact.sa_mask); 2304 2305 (void) sigaction(SIGINT, &nact, (struct sigaction *)NULL); 2306 2307 /* reset SIGHUP */ 2308 2309 nact.sa_handler = funcSighup; 2310 nact.sa_flags = SA_RESTART; 2311 (void) sigemptyset(&nact.sa_mask); 2312 2313 (void) sigaction(SIGHUP, &nact, (struct sigaction *)NULL); 2314 2315 /* 2316 * if signal received during command execution, interrupt 2317 * this process now. 2318 */ 2319 2320 if (_z_global_data._z_SigReceived != 0) { 2321 (void) kill(getpid(), SIGINT); 2322 } 2323 2324 /* set errno and return */ 2325 2326 errno = lerrno; 2327 2328 return (final_status); 2329} 2330 2331/* 2332 * Name: z_zones_are_implemented 2333 * Description: Determine if any zone operations can be performed 2334 * Arguments: void 2335 * Returns: boolean_t 2336 * == B_TRUE - zone operations are available 2337 * == B_FALSE - no zone operations can be done 2338 */ 2339 2340boolean_t 2341z_zones_are_implemented(void) 2342{ 2343 static boolean_t _zonesImplementedDetermined = B_FALSE; 2344 static boolean_t _zonesAreImplemented = B_FALSE; 2345 2346 /* if availability has not been determined, cache it now */ 2347 2348 if (!_zonesImplementedDetermined) { 2349 _zonesImplementedDetermined = B_TRUE; 2350 _zonesAreImplemented = _z_zones_are_implemented(); 2351 if (!_zonesAreImplemented) { 2352 _z_echoDebug(DBG_ZONES_NOT_IMPLEMENTED); 2353 } else { 2354 _z_echoDebug(DBG_ZONES_ARE_IMPLEMENTED); 2355 } 2356 } 2357 2358 return (_zonesAreImplemented); 2359} 2360