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 179 boolean_t 180 z_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 271 boolean_t 272 z_brands_are_implemented(void) 273 { 274 static boolean_t _brandsImplementedDetermined = B_FALSE; 275 static 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 301 void 302 z_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 348 zoneList_t 349 z_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 */ 370 void 371 z_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 */ 397 zoneBrandList_t * 398 z_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 */ 445 zoneList_t 446 z_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 580 char * 581 z_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 618 boolean_t 619 z_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 651 boolean_t 652 z_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 (void) free(zoneName); 697 698 return (B_TRUE); 699 } 700 701 /* 702 * Name: z_lock_zones 703 * Description: lock specified zones 704 * Arguments: a_zlst - zoneList_t object describing zones to lock 705 * a_lflags - [RO, *RO] - (ZLOCKS_T) 706 * Flags indicating which locks to acquire 707 * Returns: boolean_t 708 * == B_TRUE - success, zones locked 709 * == B_FALSE - failure, zones not locked 710 */ 711 712 boolean_t 713 z_lock_zones(zoneList_t a_zlst, ZLOCKS_T a_lflags) 714 { 715 boolean_t b; 716 int i; 717 718 /* entry assertions */ 719 720 assert(a_lflags != ZLOCKS_NONE); 721 722 /* entry debugging info */ 723 724 _z_echoDebug(DBG_ZONES_LCK_ZONES, a_lflags); 725 726 /* if zones are not implemented, return TRUE */ 727 728 if (z_zones_are_implemented() == B_FALSE) { 729 _z_echoDebug(DBG_ZONES_LCK_ZONES_UNIMP); 730 return (B_TRUE); 731 } 732 733 /* lock this zone first before locking other zones */ 734 735 b = z_lock_this_zone(a_lflags); 736 if (b == B_FALSE) { 737 return (b); 738 } 739 740 /* ignore empty list */ 741 742 if (a_zlst == (zoneList_t)NULL) { 743 _z_echoDebug(DBG_ZONES_LCK_ZONES_NOZONES); 744 return (B_FALSE); 745 } 746 747 /* zones exist */ 748 749 _z_echoDebug(DBG_ZONES_LCK_ZONES_EXIST); 750 751 /* 752 * lock each listed zone that is currently running 753 */ 754 755 for (i = 0; (a_zlst[i]._zlName != (char *)NULL); i++) { 756 /* ignore zone if already locked */ 757 if (a_zlst[i]._zlStatus & ZST_LOCKED) { 758 continue; 759 } 760 761 /* ignore zone if not running */ 762 if (a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_RUNNING && 763 a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_MOUNTED) { 764 continue; 765 } 766 767 /* 768 * mark zone locked - if interrupted out during lock, an attempt 769 * will be made to release the lock 770 */ 771 a_zlst[i]._zlStatus |= ZST_LOCKED; 772 773 /* lock this zone */ 774 b = _z_lock_zone(&a_zlst[i], a_lflags); 775 776 /* on failure unlock all zones and return error */ 777 if (b != B_TRUE) { 778 _z_program_error(ERR_ZONES_LCK_ZONES_FAILED, 779 a_zlst[i]._zlName); 780 (void) z_unlock_zones(a_zlst, a_lflags); 781 return (B_FALSE); 782 } 783 } 784 785 /* success */ 786 787 return (B_TRUE); 788 } 789 790 /* 791 * Name: z_mount_in_lz 792 * Description: Mount global zone directory in specified zone's root file system 793 * Arguments: r_lzMountPoint - pointer to handle to string - on success, the 794 * full path to the mount point relative to the global zone 795 * root file system is returned here - this is needed to 796 * unmount the directory when it is no longer needed 797 * r_lzRootPath - pointer to handle to string - on success, the 798 * full path to the mount point relative to the specified 799 * zone's root file system is returned here - this is 800 * passed to any command executing in the specified zone to 801 * access the directory mounted 802 * a_zoneName - pointer to string representing the name of the zone 803 * to mount the specified global zone directory in 804 * a_gzPath - pointer to string representing the full absolute path 805 * of the global zone directory to LOFS mount inside of the 806 * specified non-global zone 807 * a_mountPointPrefix - pointer to string representing the prefix 808 * to be used when creating the mount point name in the 809 * specified zone's root directory 810 * Returns: boolean_t 811 * == B_TRUE - global zone directory mounted successfully 812 * == B_FALSE - failed to mount directory in specified zone 813 * NOTE: Any strings returned is placed in new storage for the 814 * calling function. The caller must use 'Free' to dispose 815 * of the storage once the strings are no longer needed. 816 */ 817 818 boolean_t 819 z_mount_in_lz(char **r_lzMountPoint, char **r_lzRootPath, char *a_zoneName, 820 char *a_gzPath, char *a_mountPointPrefix) 821 { 822 char lzRootPath[MAXPATHLEN] = {'\0'}; 823 char uuid[MAXPATHLEN] = {'\0'}; 824 char gzMountPoint[MAXPATHLEN] = {'\0'}; 825 char lzMountPoint[MAXPATHLEN] = {'\0'}; 826 hrtime_t hretime; 827 int err; 828 int slen; 829 struct tm tstruct; 830 time_t thetime; 831 zoneid_t zid; 832 833 /* entry assertions */ 834 835 assert(a_zoneName != (char *)NULL); 836 assert(*a_zoneName != '\0'); 837 assert(a_gzPath != (char *)NULL); 838 assert(*a_gzPath != '\0'); 839 assert(r_lzMountPoint != (char **)NULL); 840 assert(r_lzRootPath != (char **)NULL); 841 842 /* entry debugging info */ 843 844 _z_echoDebug(DBG_ZONES_MOUNT_IN_LZ_ENTRY, a_zoneName, a_gzPath); 845 846 /* reset returned non-global zone mount point path handle */ 847 848 *r_lzMountPoint = (char *)NULL; 849 *r_lzRootPath = (char *)NULL; 850 851 /* if zones are not implemented, return FALSE */ 852 853 if (z_zones_are_implemented() == B_FALSE) { 854 return (B_FALSE); 855 } 856 857 /* error if global zone path is not absolute */ 858 859 if (*a_gzPath != '/') { 860 _z_program_error(ERR_GZPATH_NOT_ABSOLUTE, a_gzPath); 861 return (B_FALSE); 862 } 863 864 /* error if global zone path does not exist */ 865 866 if (_z_is_directory(a_gzPath) != 0) { 867 _z_program_error(ERR_GZPATH_NOT_DIR, a_gzPath, strerror(errno)); 868 return (B_FALSE); 869 } 870 871 /* verify that specified non-global zone exists */ 872 873 err = zone_get_id(a_zoneName, &zid); 874 if (err != Z_OK) { 875 _z_program_error(ERR_GET_ZONEID, a_zoneName, 876 zonecfg_strerror(err)); 877 return (B_FALSE); 878 } 879 880 /* obtain global zone path to non-global zones root file system */ 881 882 err = zone_get_rootpath(a_zoneName, lzRootPath, sizeof (lzRootPath)); 883 if (err != Z_OK) { 884 _z_program_error(ERR_NO_ZONE_ROOTPATH, a_zoneName, 885 zonecfg_strerror(err)); 886 return (B_FALSE); 887 } 888 889 if (lzRootPath[0] == '\0') { 890 _z_program_error(ERR_ROOTPATH_EMPTY, a_zoneName); 891 return (B_FALSE); 892 } 893 894 /* 895 * lofs resolve the non-global zone's root path first in case 896 * its in a path that's been lofs mounted read-only. 897 */ 898 z_resolve_lofs(lzRootPath, sizeof (lzRootPath)); 899 900 /* verify that the root path exists */ 901 902 if (_z_is_directory(lzRootPath) != 0) { 903 _z_program_error(ERR_LZROOT_NOTDIR, lzRootPath, 904 strerror(errno)); 905 return (B_FALSE); 906 } 907 908 /* 909 * generate a unique key - the key is the same length as unique uid 910 * but contains different information that is as unique as can be made; 911 * include current hires time (nanosecond real timer). Such a unique 912 * i.d. will look like: 913 * 0203104092-1145345-0004e94d6af481a0 914 */ 915 916 hretime = gethrtime(); 917 918 thetime = time((time_t *)NULL); 919 (void) localtime_r(&thetime, &tstruct); 920 921 slen = snprintf(uuid, sizeof (uuid), 922 UUID_FORMAT, 923 tstruct.tm_mday, tstruct.tm_mon, tstruct.tm_year, 924 tstruct.tm_yday, tstruct.tm_hour, tstruct.tm_min, 925 tstruct.tm_sec, tstruct.tm_wday, hretime); 926 if (slen > sizeof (uuid)) { 927 _z_program_error(ERR_GZMOUNT_SNPRINTFUUID_FAILED, 928 UUID_FORMAT, sizeof (uuid)); 929 return (B_FALSE); 930 } 931 932 /* create the global zone mount point */ 933 934 slen = snprintf(gzMountPoint, sizeof (gzMountPoint), "%s/.SUNW_%s_%s", 935 lzRootPath, 936 a_mountPointPrefix ? a_mountPointPrefix : "zones", uuid); 937 if (slen > sizeof (gzMountPoint)) { 938 _z_program_error(ERR_GZMOUNT_SNPRINTFGMP_FAILED, 939 "%s/.SUNW_%s_%s", lzRootPath, 940 a_mountPointPrefix ? a_mountPointPrefix : "zones", 941 uuid, sizeof (gzMountPoint)); 942 return (B_FALSE); 943 } 944 945 slen = snprintf(lzMountPoint, sizeof (lzMountPoint), "%s", 946 gzMountPoint+strlen(lzRootPath)); 947 if (slen > sizeof (lzMountPoint)) { 948 _z_program_error(ERR_GZMOUNT_SNPRINTFLMP_FAILED, 949 "%s", gzMountPoint+strlen(lzRootPath), 950 sizeof (lzMountPoint)); 951 return (B_FALSE); 952 } 953 954 _z_echoDebug(DBG_MNTPT_NAMES, a_gzPath, a_zoneName, gzMountPoint, 955 lzMountPoint); 956 957 /* error if the mount point already exists */ 958 959 if (_z_is_directory(gzMountPoint) == 0) { 960 _z_program_error(ERR_ZONEROOT_NOTDIR, gzMountPoint, 961 a_zoneName, strerror(errno)); 962 return (B_FALSE); 963 } 964 965 /* create the temporary mount point */ 966 967 if (mkdir(gzMountPoint, 0600) != 0) { 968 _z_program_error(ERR_MNTPT_MKDIR, gzMountPoint, a_zoneName, 969 strerror(errno)); 970 return (B_FALSE); 971 } 972 973 /* mount the global zone path on the non-global zone root file system */ 974 975 err = mount(a_gzPath, gzMountPoint, MS_RDONLY|MS_DATA, "lofs", 976 (char *)NULL, 0, (char *)NULL, 0); 977 if (err != 0) { 978 _z_program_error(ERR_GZMOUNT_FAILED, a_gzPath, 979 gzMountPoint, a_zoneName, strerror(errno)); 980 return (B_FALSE); 981 } 982 983 /* success - return both mountpoints to caller */ 984 985 *r_lzMountPoint = _z_strdup(gzMountPoint); 986 987 *r_lzRootPath = _z_strdup(lzMountPoint); 988 989 /* return success */ 990 991 return (B_TRUE); 992 } 993 994 /* 995 * Name: z_non_global_zones_exist 996 * Description: Determine if any non-global native zones exist 997 * Arguments: None. 998 * Returns: boolean_t 999 * == B_TRUE - at least one non-global native zone exists 1000 * == B_FALSE - no non-global native zone exists 1001 */ 1002 1003 boolean_t 1004 z_non_global_zones_exist(void) 1005 { 1006 FILE *zoneIndexFP; 1007 boolean_t anyExist = B_FALSE; 1008 struct zoneent *ze; 1009 zone_spec_t *zent; 1010 1011 /* if zones are not implemented, return FALSE */ 1012 1013 if (z_zones_are_implemented() == B_FALSE) { 1014 return (B_FALSE); 1015 } 1016 1017 /* determine if any zones are configured */ 1018 zoneIndexFP = setzoneent(); 1019 if (zoneIndexFP == NULL) { 1020 return (B_FALSE); 1021 } 1022 1023 /* index file open; scan all zones; see if any are at least installed */ 1024 1025 while ((ze = getzoneent_private(zoneIndexFP)) != NULL) { 1026 /* 1027 * If the user specified an explicit zone list, then ignore any 1028 * zones that aren't on that list. 1029 */ 1030 if ((zent = _z_global_data._zone_spec) != NULL) { 1031 while (zent != NULL) { 1032 if (strcmp(zent->zl_name, ze->zone_name) == 0) 1033 break; 1034 zent = zent->zl_next; 1035 } 1036 if (zent == NULL) { 1037 free(ze); 1038 continue; 1039 } 1040 } 1041 1042 /* skip the global zone */ 1043 if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0) { 1044 free(ze); 1045 continue; 1046 } 1047 1048 /* skip any branded zones */ 1049 if (z_is_zone_branded(ze->zone_name)) { 1050 free(ze); 1051 continue; 1052 } 1053 1054 /* is this zone installed? */ 1055 if (ze->zone_state >= ZONE_STATE_INSTALLED) { 1056 free(ze); 1057 anyExist = B_TRUE; 1058 break; 1059 } 1060 free(ze); 1061 } 1062 1063 /* close the index file */ 1064 1065 endzoneent(zoneIndexFP); 1066 1067 /* return results */ 1068 1069 return (anyExist); 1070 } 1071 1072 /* 1073 * Name: z_on_zone_spec 1074 * Description: Determine if named zone is on the zone_spec list. 1075 * Arguments: Pointer to name to test. 1076 * Returns: B_TRUE if named zone is on the list or if the user specified 1077 * no list at all (all zones is the default), B_FALSE otherwise. 1078 */ 1079 1080 boolean_t 1081 z_on_zone_spec(const char *zonename) 1082 { 1083 zone_spec_t *zent; 1084 1085 /* entry assertions */ 1086 1087 assert(zonename != NULL); 1088 assert(*zonename != '\0'); 1089 1090 /* return true if zones not implemented or no zone spec list defined */ 1091 1092 if (!z_zones_are_implemented() || _z_global_data._zone_spec == NULL) { 1093 return (B_TRUE); 1094 } 1095 1096 /* return true if named zone is on the zone spec list */ 1097 1098 for (zent = _z_global_data._zone_spec; 1099 zent != NULL; zent = zent->zl_next) { 1100 if (strcmp(zent->zl_name, zonename) == 0) 1101 return (B_TRUE); 1102 } 1103 1104 /* named zone is not on the zone spec list */ 1105 1106 return (B_FALSE); 1107 } 1108 1109 /* 1110 * Name: z_running_in_global_zone 1111 * Description: Determine if running in the "global" zone 1112 * Arguments: void 1113 * Returns: boolean_t 1114 * == B_TRUE - running in global zone 1115 * == B_FALSE - not running in global zone 1116 */ 1117 1118 boolean_t 1119 z_running_in_global_zone(void) 1120 { 1121 static boolean_t _zoneIdDetermined = B_FALSE; 1122 static boolean_t _zoneIsGlobal = B_FALSE; 1123 1124 /* if ID has not been determined, cache it now */ 1125 1126 if (!_zoneIdDetermined) { 1127 _zoneIdDetermined = B_TRUE; 1128 _zoneIsGlobal = _z_running_in_global_zone(); 1129 } 1130 1131 return (_zoneIsGlobal); 1132 } 1133 1134 /* 1135 * Name: z_set_output_functions 1136 * Description: Link program specific output functions to this library. 1137 * Arguments: a_echo_fcn - (_z_printf_fcn_t) 1138 * Function to call to cause "normal operation" messages 1139 * to be output/displayed 1140 * a_echo_debug_fcn - (_z_printf_fcn_t) 1141 * Function to call to cause "debugging" messages 1142 * to be output/displayed 1143 * a_progerr_fcn - (_z_printf_fcn_t) 1144 * Function to call to cause "program error" messages 1145 * to be output/displayed 1146 * Returns: void 1147 * NOTE: If NULL is specified for any function, then the functionality 1148 * associated with that function is disabled. 1149 * NOTE: The function pointers provided must call a function that 1150 * takes two arguments: 1151 * function(char *format, char *message) 1152 * Any registered function will be called like: 1153 * function("%s", "message") 1154 */ 1155 1156 void 1157 z_set_output_functions(_z_printf_fcn_t a_echo_fcn, 1158 _z_printf_fcn_t a_echo_debug_fcn, 1159 _z_printf_fcn_t a_progerr_fcn) 1160 { 1161 _z_global_data._z_echo = a_echo_fcn; 1162 _z_global_data._z_echo_debug = a_echo_debug_fcn; 1163 _z_global_data._z_progerr = a_progerr_fcn; 1164 } 1165 1166 /* 1167 * Name: z_set_zone_root 1168 * Description: Set root for zones library operations 1169 * Arguments: Path to root of boot environment containing zone; must be 1170 * absolute. 1171 * Returns: None. 1172 * NOTE: Must be called before performing any zone-related operations. 1173 * (Currently called directly by set_inst_root() during -R 1174 * argument handling.) 1175 */ 1176 1177 void 1178 z_set_zone_root(const char *zroot) 1179 { 1180 char *rootdir; 1181 1182 /* if zones are not implemented, just return */ 1183 1184 if (!z_zones_are_implemented()) 1185 return; 1186 1187 /* entry assertions */ 1188 1189 assert(zroot != NULL); 1190 1191 rootdir = _z_strdup((char *)zroot); 1192 z_canoninplace(rootdir); 1193 1194 if (strcmp(rootdir, "/") == 0) { 1195 rootdir[0] = '\0'; 1196 } 1197 1198 /* free any existing cached root path */ 1199 if (*_z_global_data._z_root_dir != '\0') { 1200 free(_z_global_data._z_root_dir); 1201 _z_global_data._z_root_dir = NULL; 1202 } 1203 1204 /* store duplicate of new zone root path */ 1205 1206 if (*rootdir != '\0') { 1207 _z_global_data._z_root_dir = _z_strdup(rootdir); 1208 } else { 1209 _z_global_data._z_root_dir = ""; 1210 } 1211 1212 /* set zone root path */ 1213 1214 zonecfg_set_root(rootdir); 1215 1216 free(rootdir); 1217 } 1218 1219 /* 1220 * Name: z_set_zone_spec 1221 * Description: Set list of zones on which actions will be performed. 1222 * Arguments: Whitespace-separated list of zone names. 1223 * Returns: 0 on success, -1 on error. 1224 * NOTES: Will call _z_program_error if argument can't be parsed or 1225 * memory not available. 1226 */ 1227 1228 int 1229 z_set_zone_spec(const char *zlist) 1230 { 1231 const char *zend; 1232 ptrdiff_t zlen; 1233 zone_spec_t *zent; 1234 zone_spec_t *zhead; 1235 zone_spec_t **znextp = &zhead; 1236 1237 /* entry assertions */ 1238 1239 assert(zlist != NULL); 1240 1241 /* parse list to zone_spec_t list, store in global data */ 1242 1243 for (;;) { 1244 while (isspace(*zlist)) { 1245 zlist++; 1246 } 1247 if (*zlist == '\0') { 1248 break; 1249 } 1250 for (zend = zlist; *zend != '\0'; zend++) { 1251 if (isspace(*zend)) { 1252 break; 1253 } 1254 } 1255 zlen = ((ptrdiff_t)zend) - ((ptrdiff_t)zlist); 1256 if (zlen >= ZONENAME_MAX) { 1257 _z_program_error(ERR_ZONE_NAME_ILLEGAL, zlen, zlist); 1258 return (-1); 1259 } 1260 zent = _z_malloc(sizeof (*zent)); 1261 (void) memcpy(zent->zl_name, zlist, zlen); 1262 zent->zl_name[zlen] = '\0'; 1263 zent->zl_used = B_FALSE; 1264 *znextp = zent; 1265 znextp = &zent->zl_next; 1266 zlist = zend; 1267 } 1268 *znextp = NULL; 1269 1270 if (zhead == NULL) { 1271 _z_program_error(ERR_ZONE_LIST_EMPTY); 1272 return (-1); 1273 } 1274 1275 _z_global_data._zone_spec = zhead; 1276 return (0); 1277 } 1278 1279 /* 1280 * Name: z_umount_lz_mount 1281 * Description: Unmount directory mounted with z_mount_in_lz 1282 * Arguments: a_lzMountPointer - pointer to string returned by z_mount_in_lz 1283 * Returns: boolean_t 1284 * == B_TRUE - successfully unmounted directory 1285 * == B_FALSE - failed to unmount directory 1286 */ 1287 1288 boolean_t 1289 z_umount_lz_mount(char *a_lzMountPoint) 1290 { 1291 int err; 1292 1293 /* entry assertions */ 1294 1295 assert(a_lzMountPoint != (char *)NULL); 1296 assert(*a_lzMountPoint != '\0'); 1297 1298 /* entry debugging info */ 1299 1300 _z_echoDebug(DBG_ZONES_UNMOUNT_FROM_LZ_ENTRY, a_lzMountPoint); 1301 1302 /* if zones are not implemented, return TRUE */ 1303 1304 if (z_zones_are_implemented() == B_FALSE) { 1305 return (B_FALSE); 1306 } 1307 1308 /* error if global zone path is not absolute */ 1309 1310 if (*a_lzMountPoint != '/') { 1311 _z_program_error(ERR_LZMNTPT_NOT_ABSOLUTE, a_lzMountPoint); 1312 return (B_FALSE); 1313 } 1314 1315 /* verify mount point exists */ 1316 1317 if (_z_is_directory(a_lzMountPoint) != 0) { 1318 _z_program_error(ERR_LZMNTPT_NOTDIR, a_lzMountPoint, 1319 strerror(errno)); 1320 return (B_FALSE); 1321 } 1322 1323 /* unmount */ 1324 1325 err = umount2(a_lzMountPoint, 0); 1326 if (err != 0) { 1327 _z_program_error(ERR_GZUMOUNT_FAILED, a_lzMountPoint, 1328 strerror(errno)); 1329 return (B_FALSE); 1330 } 1331 1332 /* remove the mount point */ 1333 1334 (void) remove(a_lzMountPoint); 1335 1336 /* return success */ 1337 1338 return (B_TRUE); 1339 } 1340 1341 /* 1342 * Name: z_unlock_this_zone 1343 * Description: unlock this zone 1344 * Arguments: a_lflags - [RO, *RO] - (ZLOCKS_T) 1345 * Flags indicating which locks to release 1346 * Returns: boolean_t 1347 * == B_TRUE - success specified locks released 1348 * == B_FALSE - failure specified locks may not be released 1349 * NOTE: the lock objects for "this zone" are maintained internally. 1350 */ 1351 1352 boolean_t 1353 z_unlock_this_zone(ZLOCKS_T a_lflags) 1354 { 1355 boolean_t b; 1356 boolean_t errors = B_FALSE; 1357 char *zoneName; 1358 1359 /* entry assertions */ 1360 1361 assert(a_lflags != ZLOCKS_NONE); 1362 1363 /* entry debugging info */ 1364 1365 _z_echoDebug(DBG_ZONES_ULK_THIS, a_lflags); 1366 1367 /* return if no objects locked */ 1368 1369 if ((_z_global_data._z_ObjectLocks == (char *)NULL) || 1370 (*_z_global_data._z_ObjectLocks == '\0')) { 1371 return (B_TRUE); 1372 } 1373 1374 zoneName = z_get_zonename(); 1375 1376 /* unlock package administration */ 1377 1378 if (a_lflags & ZLOCKS_PKG_ADMIN) { 1379 b = _z_unlock_zone_object(&_z_global_data._z_ObjectLocks, 1380 zoneName, LOBJ_PKGADMIN, ERR_ZONES_ULK_THIS_PACKAGE); 1381 if (!b) { 1382 errors = B_TRUE; 1383 } 1384 } 1385 1386 /* unlock zone administration */ 1387 1388 if (a_lflags & ZLOCKS_ZONE_ADMIN) { 1389 b = _z_unlock_zone_object(&_z_global_data._z_ObjectLocks, 1390 zoneName, LOBJ_ZONEADMIN, ERR_ZONES_ULK_THIS_ZONES); 1391 if (!b) { 1392 errors = B_TRUE; 1393 } 1394 } 1395 1396 (void) free(zoneName); 1397 return (!errors); 1398 } 1399 1400 /* 1401 * Name: z_unlock_zones 1402 * Description: unlock specified zones 1403 * Arguments: a_zlst - zoneList_t object describing zones to unlock 1404 * a_lflags - [RO, *RO] - (ZLOCKS_T) 1405 * Flags indicating which locks to release 1406 * Returns: boolean_t 1407 * == B_TRUE - success, zones unlocked 1408 * == B_FALSE - failure, zones not unlocked 1409 */ 1410 1411 boolean_t 1412 z_unlock_zones(zoneList_t a_zlst, ZLOCKS_T a_lflags) 1413 { 1414 boolean_t b; 1415 boolean_t errors = B_FALSE; 1416 int i; 1417 1418 /* entry assertions */ 1419 1420 assert(a_lflags != ZLOCKS_NONE); 1421 1422 /* entry debugging info */ 1423 1424 _z_echoDebug(DBG_ZONES_ULK_ZONES, a_lflags); 1425 1426 /* if zones are not implemented, return TRUE */ 1427 1428 if (z_zones_are_implemented() == B_FALSE) { 1429 _z_echoDebug(DBG_ZONES_ULK_ZONES_UNIMP); 1430 return (B_TRUE); 1431 } 1432 1433 /* ignore empty list */ 1434 1435 if (a_zlst == (zoneList_t)NULL) { 1436 _z_echoDebug(DBG_ZONES_ULK_ZONES_NOZONES); 1437 /* unlock this zone before returning */ 1438 return (z_unlock_this_zone(a_lflags)); 1439 } 1440 1441 /* zones exist */ 1442 1443 _z_echoDebug(DBG_ZONES_ULK_ZONES_EXIST); 1444 1445 /* 1446 * unlock each listed zone that is currently running 1447 */ 1448 1449 for (i = 0; (a_zlst[i]._zlName != (char *)NULL); i++) { 1450 /* ignore zone if not locked */ 1451 if (!(a_zlst[i]._zlStatus & ZST_LOCKED)) { 1452 continue; 1453 } 1454 1455 /* ignore zone if not running */ 1456 if (a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_RUNNING && 1457 a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_MOUNTED) { 1458 continue; 1459 } 1460 1461 /* unlock this zone */ 1462 b = _z_unlock_zone(&a_zlst[i], a_lflags); 1463 1464 if (b != B_TRUE) { 1465 errors = B_TRUE; 1466 } else { 1467 /* mark zone as unlocked */ 1468 a_zlst[i]._zlStatus &= ~ZST_LOCKED; 1469 } 1470 } 1471 1472 /* unlock this zone */ 1473 1474 if (z_unlock_this_zone(a_lflags) != B_TRUE) { 1475 errors = B_TRUE; 1476 } 1477 1478 return (errors); 1479 } 1480 1481 /* 1482 * Name: z_verify_zone_spec 1483 * Description: Verify list of zones on which actions will be performed. 1484 * Arguments: None. 1485 * Returns: 0 on success, -1 on error. 1486 * NOTES: Will call _z_program_error if there are zones on the specified 1487 * list that don't exist on the system. Requires that 1488 * z_set_zone_root is called first (if it is called at all). 1489 */ 1490 1491 int 1492 z_verify_zone_spec(void) 1493 { 1494 FILE *zoneIndexFP; 1495 boolean_t errors; 1496 char zoneIndexPath[MAXPATHLEN]; 1497 struct zoneent *ze; 1498 zone_spec_t *zent; 1499 1500 if (!z_zones_are_implemented()) { 1501 _z_program_error(ERR_ZONES_NOT_IMPLEMENTED); 1502 return (-1); 1503 } 1504 1505 zoneIndexFP = setzoneent(); 1506 if (zoneIndexFP == NULL) { 1507 _z_program_error(ERR_ZONEINDEX_OPEN, zoneIndexPath, 1508 strerror(errno)); 1509 return (-1); 1510 } 1511 1512 while ((ze = getzoneent_private(zoneIndexFP)) != NULL) { 1513 for (zent = _z_global_data._zone_spec; 1514 zent != NULL; zent = zent->zl_next) { 1515 if (strcmp(zent->zl_name, ze->zone_name) == 0) { 1516 zent->zl_used = B_TRUE; 1517 break; 1518 } 1519 } 1520 free(ze); 1521 } 1522 endzoneent(zoneIndexFP); 1523 1524 errors = B_FALSE; 1525 for (zent = _z_global_data._zone_spec; 1526 zent != NULL; zent = zent->zl_next) { 1527 if (!zent->zl_used) { 1528 _z_program_error(ERR_ZONE_NONEXISTENT, zent->zl_name); 1529 errors = B_TRUE; 1530 } 1531 } 1532 return (errors ? -1 : 0); 1533 } 1534 1535 /* 1536 * Name: z_zlist_change_zone_state 1537 * Description: Change the current state of the specified zone 1538 * Arguments: a_zlst - handle to zoneList_t object describing all zones 1539 * a_zoneIndex - index into a_zlst of the zone to return the 1540 * a_newState - the state to put the specified zone in 1541 * Returns: boolean_t 1542 * == B_TRUE - the zone is in the new state 1543 * == B_FALSE - unable to transition the zone to the 1544 * specified state 1545 * NOTE: This changes the "current kernel" state of the specified 1546 * zone. For example, to boot the zone, change the state 1547 * to "ZONE_STATE_RUNNING". To halt the zone, change the 1548 * state to "ZONE_STATE_INSTALLED". 1549 */ 1550 1551 boolean_t 1552 z_zlist_change_zone_state(zoneList_t a_zlst, int a_zoneIndex, 1553 zone_state_t a_newState) 1554 { 1555 int i; 1556 1557 /* entry debugging info */ 1558 1559 _z_echoDebug(DBG_ZONES_CHG_Z_STATE_ENTRY, a_zoneIndex, a_newState); 1560 1561 /* ignore empty list */ 1562 1563 if (a_zlst == (zoneList_t)NULL) { 1564 return (B_FALSE); 1565 } 1566 1567 /* find the specified zone in the list */ 1568 1569 for (i = 0; (i != a_zoneIndex) && 1570 (a_zlst[i]._zlName != (char *)NULL); i++) 1571 ; 1572 1573 /* return error if the specified zone does not exist */ 1574 1575 if (a_zlst[i]._zlName == (char *)NULL) { 1576 return (B_FALSE); 1577 } 1578 1579 /* return success if the zone is already in this state */ 1580 1581 if (a_zlst[i]._zlCurrKernelStatus == a_newState) { 1582 return (B_TRUE); 1583 } 1584 1585 /* take action on new state to set zone to */ 1586 1587 _z_echoDebug(DBG_ZONES_CHG_Z_STATE, a_zlst[i]._zlName, 1588 a_zlst[i]._zlCurrKernelStatus, a_newState); 1589 1590 switch (a_newState) { 1591 case ZONE_STATE_RUNNING: 1592 case ZONE_STATE_MOUNTED: 1593 /* these states mean "boot the zone" */ 1594 return (_z_make_zone_running(&a_zlst[i])); 1595 1596 case ZONE_STATE_DOWN: 1597 case ZONE_STATE_INSTALLED: 1598 /* these states mean "halt the zone" */ 1599 return (_z_make_zone_down(&a_zlst[i])); 1600 1601 case ZONE_STATE_READY: 1602 return (_z_make_zone_ready(&a_zlst[i])); 1603 1604 case ZONE_STATE_CONFIGURED: 1605 case ZONE_STATE_INCOMPLETE: 1606 case ZONE_STATE_SHUTTING_DOWN: 1607 default: 1608 /* do not know how to change zone to this state */ 1609 return (B_FALSE); 1610 } 1611 } 1612 1613 /* 1614 * Name: z_is_zone_branded 1615 * Description: Determine whether zone has a non-native brand 1616 * Arguments: a_zoneName - name of the zone to check for branding 1617 * Returns: boolean_t 1618 * == B_TRUE - zone has a non-native brand 1619 * == B_FALSE - zone is native 1620 */ 1621 boolean_t 1622 z_is_zone_branded(char *zoneName) 1623 { 1624 char brandname[MAXNAMELEN]; 1625 int err; 1626 1627 /* if zones are not implemented, return FALSE */ 1628 if (!z_zones_are_implemented()) { 1629 return (B_FALSE); 1630 } 1631 1632 /* if brands are not implemented, return FALSE */ 1633 if (!z_brands_are_implemented()) { 1634 return (B_FALSE); 1635 } 1636 1637 err = zone_get_brand(zoneName, brandname, sizeof (brandname)); 1638 if (err != Z_OK) { 1639 _z_program_error(ERR_BRAND_GETBRAND, zonecfg_strerror(err)); 1640 return (B_FALSE); 1641 } 1642 1643 /* 1644 * Both "native" and "cluster" are native brands 1645 * that use the standard facilities in the areas 1646 * of packaging/installation/update. 1647 */ 1648 if (streq(brandname, NATIVE_BRAND_NAME) || 1649 streq(brandname, CLUSTER_BRAND_NAME)) { 1650 return (B_FALSE); 1651 } else { 1652 return (B_TRUE); 1653 } 1654 } 1655 1656 /* 1657 * Name: z_is_zone_brand_in_list 1658 * Description: Determine whether zone's brand has a match in the list 1659 * brands passed in. 1660 * Arguments: zoneName - name of the zone to check for branding 1661 * list - list of brands to check the zone against 1662 * Returns: boolean_t 1663 * == B_TRUE - zone has a matching brand 1664 * == B_FALSE - zone brand is not in list 1665 */ 1666 boolean_t 1667 z_is_zone_brand_in_list(char *zoneName, zoneBrandList_t *list) 1668 { 1669 char brandname[MAXNAMELEN]; 1670 int err; 1671 zoneBrandList_t *sp; 1672 1673 if (zoneName == NULL || list == NULL) 1674 return (B_FALSE); 1675 1676 /* if zones are not implemented, return FALSE */ 1677 if (!z_zones_are_implemented()) { 1678 return (B_FALSE); 1679 } 1680 1681 /* if brands are not implemented, return FALSE */ 1682 if (!z_brands_are_implemented()) { 1683 return (B_FALSE); 1684 } 1685 1686 err = zone_get_brand(zoneName, brandname, sizeof (brandname)); 1687 if (err != Z_OK) { 1688 _z_program_error(ERR_BRAND_GETBRAND, zonecfg_strerror(err)); 1689 return (B_FALSE); 1690 } 1691 1692 for (sp = list; sp != NULL; sp = sp->next) { 1693 if (sp->string_ptr != NULL && 1694 strcmp(sp->string_ptr, brandname) == 0) { 1695 return (B_TRUE); 1696 } 1697 } 1698 1699 return (B_FALSE); 1700 } 1701 1702 /* 1703 * Name: z_zlist_get_current_state 1704 * Description: Determine the current kernel state of the specified zone 1705 * Arguments: a_zlst - handle to zoneList_t object describing all zones 1706 * a_zoneIndex - index into a_zlst of the zone to return 1707 * Returns: zone_state_t 1708 * The current state of the specified zone is returned 1709 */ 1710 1711 zone_state_t 1712 z_zlist_get_current_state(zoneList_t a_zlst, int a_zoneIndex) 1713 { 1714 int i; 1715 1716 /* ignore empty list */ 1717 1718 if (a_zlst == (zoneList_t)NULL) { 1719 return (ZONE_STATE_INCOMPLETE); 1720 } 1721 1722 /* find the specified zone in the list */ 1723 1724 for (i = 0; (i != a_zoneIndex) && 1725 (a_zlst[i]._zlName != (char *)NULL); i++) 1726 ; 1727 1728 /* return error if the specified zone does not exist */ 1729 1730 if (a_zlst[i]._zlName == (char *)NULL) { 1731 return (ZONE_STATE_INCOMPLETE); 1732 } 1733 1734 /* return selected zone's current kernel state */ 1735 1736 _z_echoDebug(DBG_ZONES_GET_ZONE_STATE, 1737 a_zlst[i]._zlName ? a_zlst[i]._zlName : "", 1738 a_zlst[i]._zlCurrKernelStatus); 1739 1740 return (a_zlst[i]._zlCurrKernelStatus); 1741 } 1742 1743 /* 1744 * Name: z_zlist_get_original_state 1745 * Description: Return the original kernal state of the specified zone 1746 * Arguments: a_zlst - handle to zoneList_t object describing all zones 1747 * a_zoneIndex - index into a_zlst of the zone to return the 1748 * Returns: zone_state_t 1749 * The original state of the specified zone is returned. 1750 * This is the state of the zone when the zoneList_t 1751 * object was first generated. 1752 */ 1753 1754 zone_state_t 1755 z_zlist_get_original_state(zoneList_t a_zlst, int a_zoneIndex) 1756 { 1757 int i; 1758 1759 /* ignore empty list */ 1760 1761 if (a_zlst == (zoneList_t)NULL) { 1762 return (ZONE_STATE_INCOMPLETE); 1763 } 1764 1765 /* find the specified zone in the list */ 1766 1767 for (i = 0; (i != a_zoneIndex) && 1768 (a_zlst[i]._zlName != (char *)NULL); i++) 1769 ; 1770 1771 /* return error if the specified zone does not exist */ 1772 1773 if (a_zlst[i]._zlName == (char *)NULL) { 1774 return (ZONE_STATE_INCOMPLETE); 1775 } 1776 1777 /* return selected zone's original kernel state */ 1778 1779 return (a_zlst[i]._zlOrigKernelStatus); 1780 } 1781 1782 /* 1783 * Name: z_zlist_get_scratch 1784 * Description: Determine name of scratch zone 1785 * Arguments: a_zlst - handle to zoneList_t object describing all zones 1786 * a_zoneIndex - index into a_zlst of the zone to use 1787 * Return: char * 1788 * == NULL - zone name could not be determined 1789 * != NULL - pointer to string representing scratch zone 1790 * NOTE: Any name returned is placed in static storage that must 1791 * NEVER be free()ed by the caller. 1792 */ 1793 1794 char * 1795 z_zlist_get_scratch(zoneList_t a_zlst, int a_zoneIndex) 1796 { 1797 int i; 1798 1799 /* ignore empty list */ 1800 1801 if (a_zlst == NULL) 1802 return (NULL); 1803 1804 /* find the specified zone in the list */ 1805 1806 for (i = 0; i != a_zoneIndex; i++) { 1807 if (a_zlst[i]._zlName == NULL) 1808 return (NULL); 1809 } 1810 1811 /* return selected zone's scratch name */ 1812 1813 return (a_zlst[i]._zlScratchName == NULL ? a_zlst[i]._zlName : 1814 a_zlst[i]._zlScratchName); 1815 } 1816 1817 /* 1818 * Name: z_zlist_get_zonename 1819 * Description: Determine name of specified zone 1820 * Arguments: a_zlst - handle to zoneList_t object describing all zones 1821 * a_zoneIndex - index into a_zlst of the zone to return the 1822 * Return: char * 1823 * == NULL - zone name could not be determined 1824 * != NULL - pointer to string representing zone name 1825 * NOTE: Any zoneList_t returned is placed in static storage that must 1826 * NEVER be free()ed by the caller. 1827 */ 1828 1829 char * 1830 z_zlist_get_zonename(zoneList_t a_zlst, int a_zoneIndex) 1831 { 1832 int i; 1833 1834 /* ignore empty list */ 1835 1836 if (a_zlst == (zoneList_t)NULL) { 1837 return ((char *)NULL); 1838 } 1839 1840 /* find the specified zone in the list */ 1841 1842 for (i = 0; (i != a_zoneIndex) && 1843 (a_zlst[i]._zlName != (char *)NULL); i++) 1844 ; 1845 1846 /* return error if the specified zone does not exist */ 1847 1848 if (a_zlst[i]._zlName == (char *)NULL) { 1849 return (NULL); 1850 } 1851 1852 /* return selected zone's name */ 1853 1854 return (a_zlst[i]._zlName); 1855 } 1856 1857 /* 1858 * Name: z_zlist_get_zonepath 1859 * Description: Determine zonepath of specified zone 1860 * Arguments: a_zlst - handle to zoneList_t object describing all zones 1861 * a_zoneIndex - index into a_zlst of the zone to return 1862 * Return: char * 1863 * == NULL - zonepath could not be determined 1864 * != NULL - pointer to string representing zonepath 1865 * NOTE: Any zoneList_t returned is placed in static storage that must 1866 * NEVER be free()ed by the caller. 1867 */ 1868 1869 char * 1870 z_zlist_get_zonepath(zoneList_t a_zlst, int a_zoneIndex) 1871 { 1872 int i; 1873 1874 /* ignore empty list */ 1875 1876 if (a_zlst == (zoneList_t)NULL) { 1877 return ((char *)NULL); 1878 } 1879 1880 /* find the specified zone in the list */ 1881 1882 for (i = 0; (i != a_zoneIndex) && 1883 (a_zlst[i]._zlName != (char *)NULL); i++) 1884 ; 1885 1886 /* return error if the specified zone does not exist */ 1887 1888 if (a_zlst[i]._zlName == (char *)NULL) { 1889 return (NULL); 1890 } 1891 1892 /* return selected zone's zonepath */ 1893 1894 return (a_zlst[i]._zlPath); 1895 } 1896 1897 boolean_t 1898 z_zlist_is_zone_runnable(zoneList_t a_zlst, int a_zoneIndex) 1899 { 1900 int i; 1901 1902 /* if zones are not implemented, return error */ 1903 1904 if (z_zones_are_implemented() == B_FALSE) { 1905 return (B_FALSE); 1906 } 1907 1908 /* ignore empty list */ 1909 1910 if (a_zlst == (zoneList_t)NULL) { 1911 return (B_FALSE); 1912 } 1913 1914 /* find the specified zone in the list */ 1915 1916 for (i = 0; (i != a_zoneIndex) && 1917 (a_zlst[i]._zlName != (char *)NULL); i++) 1918 ; 1919 1920 /* return error if the specified zone does not exist */ 1921 1922 if (a_zlst[i]._zlName == (char *)NULL) { 1923 return (B_FALSE); 1924 } 1925 1926 /* choose based on current state */ 1927 1928 switch (a_zlst[i]._zlCurrKernelStatus) { 1929 case ZONE_STATE_RUNNING: 1930 case ZONE_STATE_MOUNTED: 1931 /* already running */ 1932 return (B_TRUE); 1933 1934 case ZONE_STATE_INSTALLED: 1935 case ZONE_STATE_DOWN: 1936 case ZONE_STATE_READY: 1937 case ZONE_STATE_SHUTTING_DOWN: 1938 /* return false if the zone cannot be booted */ 1939 1940 if (a_zlst[i]._zlStatus & ZST_NOT_BOOTABLE) { 1941 return (B_FALSE); 1942 } 1943 1944 return (B_TRUE); 1945 1946 case ZONE_STATE_CONFIGURED: 1947 case ZONE_STATE_INCOMPLETE: 1948 default: 1949 /* cannot transition (boot) these states */ 1950 return (B_FALSE); 1951 } 1952 } 1953 1954 /* 1955 * Name: z_zlist_restore_zone_state 1956 * Description: Return the zone to the state it was originally in 1957 * Arguments: a_zlst - handle to zoneList_t object describing all zones 1958 * a_zoneIndex - index into a_zlst of the zone to return the 1959 * Returns: boolean_t 1960 * == B_TRUE - the zone's state has been restored 1961 * == B_FALSE - unable to transition the zone to its 1962 * original state 1963 */ 1964 1965 boolean_t 1966 z_zlist_restore_zone_state(zoneList_t a_zlst, int a_zoneIndex) 1967 { 1968 int i; 1969 1970 /* ignore empty list */ 1971 1972 if (a_zlst == (zoneList_t)NULL) { 1973 return (B_FALSE); 1974 } 1975 1976 /* find the specified zone in the list */ 1977 1978 for (i = 0; (i != a_zoneIndex) && 1979 (a_zlst[i]._zlName != (char *)NULL); i++) 1980 ; 1981 1982 /* return error if the specified zone does not exist */ 1983 1984 if (a_zlst[i]._zlName == (char *)NULL) { 1985 return (B_FALSE); 1986 } 1987 1988 /* transition the zone back to its original state */ 1989 1990 return (z_zlist_change_zone_state(a_zlst, 1991 a_zoneIndex, a_zlst[i]._zlOrigKernelStatus)); 1992 } 1993 1994 /* 1995 * Name: z_zone_exec 1996 * Description: Execute a Unix command in a specified zone and return results 1997 * Arguments: a_zoneName - pointer to string representing the name of the zone 1998 * to execute the specified command in 1999 * a_path - pointer to string representing the full path *in the 2000 * non-global zone named by a_zoneName* of the Unix command 2001 * to be executed 2002 * a_argv[] - Pointer to array of character strings representing 2003 * the arguments to be passed to the Unix command. The list 2004 * must be termianted with an element that is (char *)NULL 2005 * NOTE: a_argv[0] is the "command name" passed to the command 2006 * a_stdoutPath - Pointer to string representing the path to a file 2007 * into which all output to "stdout" from the Unix command 2008 * is placed. 2009 * == (char *)NULL - leave stdout open and pass through 2010 * == "/dev/null" - discard stdout output 2011 * a_strerrPath - Pointer to string representing the path to a file 2012 * into which all output to "stderr" from the Unix command 2013 * is placed. 2014 * == (char *)NULL - leave stderr open and pass through 2015 * == "/dev/null" - discard stderr output 2016 * a_fds - Pointer to array of integers representing file 2017 * descriptors to remain open during the call - all 2018 * file descriptors above STDERR_FILENO not in this 2019 * list will be closed. 2020 * Returns: int 2021 * The return (exit) code from the specified Unix command 2022 * Special return codes: 2023 * -1 : failure to exec process 2024 * -2 : could not create contract for greenline 2025 * -3 : fork() failed 2026 * -4 : could not open stdout capture file 2027 * -5 : error from 'waitpid' other than EINTR 2028 * -6 : zones are not supported 2029 * NOTE: All file descriptores other than 0, 1 and 2 are closed except 2030 * for those file descriptors listed in the a_fds array. 2031 */ 2032 2033 int 2034 z_zone_exec(const char *a_zoneName, const char *a_path, char *a_argv[], 2035 char *a_stdoutPath, char *a_stderrPath, int *a_fds) 2036 { 2037 int final_status; 2038 int lerrno; 2039 int status; 2040 int tmpl_fd; 2041 pid_t child_pid; 2042 pid_t result_pid; 2043 struct sigaction nact; 2044 struct sigaction oact; 2045 void (*funcSighup)(); 2046 void (*funcSigint)(); 2047 2048 /* if zones are not implemented, return TRUE */ 2049 2050 if (z_zones_are_implemented() == B_FALSE) { 2051 return (-6); /* -6 : zones are not supported */ 2052 } 2053 2054 if ((tmpl_fd = _zexec_init_template()) == -1) { 2055 _z_program_error(ERR_CANNOT_CREATE_CONTRACT, strerror(errno)); 2056 return (-2); /* -2 : could not create greenline contract */ 2057 } 2058 2059 /* 2060 * hold SIGINT/SIGHUP signals and reset signal received counter; 2061 * after the fork1() the parent and child need to setup their respective 2062 * interrupt handling and release the hold on the signals 2063 */ 2064 2065 (void) sighold(SIGINT); 2066 (void) sighold(SIGHUP); 2067 2068 _z_global_data._z_SigReceived = 0; /* no signals received */ 2069 2070 /* 2071 * fork off a new process to execute command in; 2072 * fork1() is used instead of vfork() so the child process can 2073 * perform operations that would modify the parent process if 2074 * vfork() were used 2075 */ 2076 2077 child_pid = fork1(); 2078 2079 if (child_pid < 0) { 2080 /* 2081 * ************************************************************* 2082 * fork failed! 2083 * ************************************************************* 2084 */ 2085 2086 (void) ct_tmpl_clear(tmpl_fd); 2087 (void) close(tmpl_fd); 2088 _z_program_error(ERR_FORK, strerror(errno)); 2089 2090 /* release hold on signals */ 2091 2092 (void) sigrelse(SIGHUP); 2093 (void) sigrelse(SIGINT); 2094 2095 return (-3); /* -3 : fork() failed */ 2096 } 2097 2098 if (child_pid == 0) { 2099 int i; 2100 2101 /* 2102 * ************************************************************* 2103 * This is the forked (child) process 2104 * ************************************************************* 2105 */ 2106 2107 (void) ct_tmpl_clear(tmpl_fd); 2108 (void) close(tmpl_fd); 2109 2110 /* reset any signals to default */ 2111 2112 for (i = 0; i < NSIG; i++) { 2113 (void) sigset(i, SIG_DFL); 2114 } 2115 2116 /* 2117 * close all file descriptors not in the a_fds list 2118 */ 2119 2120 (void) fdwalk(&_z_close_file_descriptors, (void *)a_fds); 2121 2122 /* 2123 * if a file for stdout is present, open the file and use the 2124 * file to capture stdout from the _zexec process 2125 */ 2126 2127 if (a_stdoutPath != (char *)NULL) { 2128 int stdoutfd; 2129 2130 stdoutfd = open(a_stdoutPath, 2131 O_WRONLY|O_CREAT|O_TRUNC, 0600); 2132 if (stdoutfd < 0) { 2133 _z_program_error(ERR_CAPTURE_FILE, a_stdoutPath, 2134 strerror(errno)); 2135 return (-4); 2136 } 2137 2138 (void) dup2(stdoutfd, STDOUT_FILENO); 2139 (void) close(stdoutfd); 2140 } 2141 2142 /* 2143 * if a file for stderr is present, open the file and use the 2144 * file to capture stderr from the _zexec process 2145 */ 2146 2147 if (a_stderrPath != (char *)NULL) { 2148 int stderrfd; 2149 2150 stderrfd = open(a_stderrPath, 2151 O_WRONLY|O_CREAT|O_TRUNC, 0600); 2152 if (stderrfd < 0) { 2153 _z_program_error(ERR_CAPTURE_FILE, a_stderrPath, 2154 strerror(errno)); 2155 return (-4); 2156 } 2157 2158 (void) dup2(stderrfd, STDERR_FILENO); 2159 (void) close(stderrfd); 2160 } 2161 2162 /* release all held signals */ 2163 2164 (void) sigrelse(SIGHUP); 2165 (void) sigrelse(SIGINT); 2166 2167 /* execute command in the specified non-global zone */ 2168 2169 _exit(_zexec(a_zoneName, a_path, a_argv)); 2170 } 2171 2172 /* 2173 * ********************************************************************* 2174 * This is the forking (parent) process 2175 * ********************************************************************* 2176 */ 2177 2178 /* register child process i.d. so signal handlers can pass signal on */ 2179 2180 _z_global_data._z_ChildProcessId = child_pid; 2181 2182 /* 2183 * setup signal handlers for SIGINT and SIGHUP and release hold 2184 */ 2185 2186 /* hook SIGINT to _z_sig_trap() */ 2187 2188 nact.sa_handler = _z_sig_trap; 2189 nact.sa_flags = SA_RESTART; 2190 (void) sigemptyset(&nact.sa_mask); 2191 2192 if (sigaction(SIGINT, &nact, &oact) < 0) { 2193 funcSigint = SIG_DFL; 2194 } else { 2195 funcSigint = oact.sa_handler; 2196 } 2197 2198 /* hook SIGHUP to _z_sig_trap() */ 2199 2200 nact.sa_handler = _z_sig_trap; 2201 nact.sa_flags = SA_RESTART; 2202 (void) sigemptyset(&nact.sa_mask); 2203 2204 if (sigaction(SIGHUP, &nact, &oact) < 0) { 2205 funcSighup = SIG_DFL; 2206 } else { 2207 funcSighup = oact.sa_handler; 2208 } 2209 2210 /* release hold on signals */ 2211 2212 (void) sigrelse(SIGHUP); 2213 (void) sigrelse(SIGINT); 2214 2215 (void) ct_tmpl_clear(tmpl_fd); 2216 (void) close(tmpl_fd); 2217 2218 /* 2219 * wait for the process to exit, reap child exit status 2220 */ 2221 2222 for (;;) { 2223 result_pid = waitpid(child_pid, &status, 0L); 2224 lerrno = (result_pid == -1 ? errno : 0); 2225 2226 /* break loop if child process status reaped */ 2227 2228 if (result_pid != -1) { 2229 break; 2230 } 2231 2232 /* break loop if not interrupted out of waitpid */ 2233 2234 if (errno != EINTR) { 2235 break; 2236 } 2237 } 2238 2239 /* reset child process i.d. so signal handlers do not pass signals on */ 2240 2241 _z_global_data._z_ChildProcessId = -1; 2242 2243 /* 2244 * If the child process terminated due to a call to exit(), then 2245 * set results equal to the 8-bit exit status of the child process; 2246 * otherwise, set the exit status to "-1" indicating that the child 2247 * exited via a signal. 2248 */ 2249 2250 if (WIFEXITED(status)) { 2251 final_status = WEXITSTATUS(status); 2252 if ((_z_global_data._z_SigReceived != 0) && 2253 (final_status == 0)) { 2254 final_status = 1; 2255 } 2256 } else { 2257 final_status = -1; /* -1 : failure to exec process */ 2258 } 2259 2260 /* determine proper exit code */ 2261 2262 if (result_pid == -1) { 2263 final_status = -5; /* -5 : error from waitpid not EINTR */ 2264 } else if (_z_global_data._z_SigReceived != 0) { 2265 final_status = -7; /* -7 : interrupt received */ 2266 } 2267 2268 /* 2269 * reset signal handlers 2270 */ 2271 2272 /* reset SIGINT */ 2273 2274 nact.sa_handler = funcSigint; 2275 nact.sa_flags = SA_RESTART; 2276 (void) sigemptyset(&nact.sa_mask); 2277 2278 (void) sigaction(SIGINT, &nact, (struct sigaction *)NULL); 2279 2280 /* reset SIGHUP */ 2281 2282 nact.sa_handler = funcSighup; 2283 nact.sa_flags = SA_RESTART; 2284 (void) sigemptyset(&nact.sa_mask); 2285 2286 (void) sigaction(SIGHUP, &nact, (struct sigaction *)NULL); 2287 2288 /* 2289 * if signal received during command execution, interrupt 2290 * this process now. 2291 */ 2292 2293 if (_z_global_data._z_SigReceived != 0) { 2294 (void) kill(getpid(), SIGINT); 2295 } 2296 2297 /* set errno and return */ 2298 2299 errno = lerrno; 2300 2301 return (final_status); 2302 } 2303 2304 /* 2305 * Name: z_zones_are_implemented 2306 * Description: Determine if any zone operations can be performed 2307 * Arguments: void 2308 * Returns: boolean_t 2309 * == B_TRUE - zone operations are available 2310 * == B_FALSE - no zone operations can be done 2311 */ 2312 2313 boolean_t 2314 z_zones_are_implemented(void) 2315 { 2316 static boolean_t _zonesImplementedDetermined = B_FALSE; 2317 static boolean_t _zonesAreImplemented = B_FALSE; 2318 2319 /* if availability has not been determined, cache it now */ 2320 2321 if (!_zonesImplementedDetermined) { 2322 _zonesImplementedDetermined = B_TRUE; 2323 _zonesAreImplemented = _z_zones_are_implemented(); 2324 if (!_zonesAreImplemented) { 2325 _z_echoDebug(DBG_ZONES_NOT_IMPLEMENTED); 2326 } else { 2327 _z_echoDebug(DBG_ZONES_ARE_IMPLEMENTED); 2328 } 2329 } 2330 2331 return (_zonesAreImplemented); 2332 } 2333