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 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 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 * 34 * _z_close_file_descriptors - close a file descriptor "a_fd" not in the 35 * list "a_fds" 36 * _z_echo - Output an interactive message if interaction is enabled 37 * _z_echoDebug - Output a debugging message if debugging is enabled 38 * _z_is_directory - determine if specified path exists and is a directory 39 * _z_program_error - Output an error message to the appropriate destinations 40 * _z_pluginCatchSigint - SIGINT/SIGHUP interrupt handler 41 * _z_running_in_global_zone - Determine if this process is running in the 42 * global zone 43 * _z_zones_are_implemented - Determine if zones are supported by the 44 * current system 45 * _z_brands_are_implemented - determine if branded zones are implemented on 46 * this system 47 */ 48 49 /* 50 * System includes 51 */ 52 53 #include <stdio.h> 54 #include <stdlib.h> 55 #include <unistd.h> 56 #include <fcntl.h> 57 #include <ctype.h> 58 #include <sys/types.h> 59 #include <sys/param.h> 60 #include <string.h> 61 #include <strings.h> 62 #include <sys/stat.h> 63 #include <stdarg.h> 64 #include <limits.h> 65 #include <errno.h> 66 #include <signal.h> 67 #include <stropts.h> 68 #include <libintl.h> 69 #include <locale.h> 70 #include <assert.h> 71 #include <dlfcn.h> 72 73 /* 74 * local includes 75 */ 76 77 #include "instzones_lib.h" 78 #include "zones_strings.h" 79 80 /* 81 * Private structures 82 */ 83 84 /* 85 * these dynamic libraries are required in order to use the branded zones 86 * functionality. If these libraries are not available at runtime, 87 * then the zones we find are assumed to be native zones. 88 */ 89 90 #define BRAND1_LIBRARY "libbrand.so.1" 91 #define BRAND_LIBRARY "libbrand.so" 92 93 /* 94 * Library Function Prototypes 95 */ 96 97 /* 98 * Local Function Prototypes 99 */ 100 101 static void error_and_exit(int error_num); 102 103 static void (*fatal_err_func)() = &error_and_exit; 104 105 /* ----------------------- private functions -------------------------- */ 106 /* 107 * error_and_exit() 108 * Abort routine. An exit code of '2' is used by all applications 109 * to indicate a non-recoverable fatal error. 110 * Parameters: 111 * error_num - error index number: 112 * ERR_MALLOC_FAIL 113 * Return: 114 * none 115 * Status: 116 * private 117 */ 118 static void 119 error_and_exit(int error_num) 120 { 121 if (error_num == ERR_MALLOC_FAIL) 122 (void) fprintf(stderr, "Allocation of memory failed\n"); 123 else 124 (void) fprintf(stderr, "ERROR: code %d\n", error_num); 125 exit(2); 126 } 127 128 /* 129 * ***************************************************************************** 130 * global external (public) functions 131 * ***************************************************************************** 132 */ 133 134 /* 135 * Name: _z_close_file_descriptors 136 * Description: close a file descriptor "a_fd" not in the list "a_fds" 137 * This function is called from the fdwalk() library function. 138 * If the file descriptor passed in is NOT in the list passed in, 139 * the file is closed. 140 * Arguments: a_fds - [RO, *RO] - (void *) 141 * Pointer to list of file descriptors to keep open 142 * a_fd - [RO, *RO] - (int) 143 * File descriptor to check 144 * Returns: int 145 * 0 - success 146 */ 147 148 int 149 _z_close_file_descriptors(void *a_fds, int a_fd) 150 { 151 int *fds; 152 int i; 153 154 /* do not close standard input, output, or error file descriptors */ 155 156 if (a_fd == STDIN_FILENO || a_fd == STDOUT_FILENO || 157 a_fd == STDERR_FILENO) { 158 return (0); 159 } 160 161 /* if no file descriptor retention list, close this file */ 162 163 if (a_fds == (void *)NULL) { 164 (void) close(a_fd); 165 return (0); 166 } 167 168 /* 169 * retention list provided, skip this descriptor if its in the list 170 */ 171 172 fds = (int *)a_fds; 173 174 for (i = 0; fds[i] != -1; i++) { 175 if (fds[i] == a_fd) { 176 return (0); 177 } 178 } 179 180 /* this descriptor not in retention list - close this file */ 181 182 (void) close(a_fd); 183 184 return (0); 185 } 186 187 /* 188 * Name: _z_echo 189 * Synopsis: Output an interactive message if interaction is enabled 190 * Description: Main method for outputting an interactive message; call to 191 * output interactive message if interation has not been disabled 192 * by a previous call to echoSetFlag(0). 193 * Arguments: format - [RO, RO*] (char *) 194 * printf-style format for debugging message to be output 195 * VARG_LIST - [RO] (?) 196 * arguments as appropriate to 'format' specified 197 * Returns: void 198 */ 199 200 /*PRINTFLIKE1*/ 201 void 202 _z_echo(char *a_format, ...) 203 { 204 va_list ap; 205 char message[MAX_MESSAGE_SIZE]; 206 207 /* entry assertions */ 208 209 assert(a_format != NULL); 210 211 /* return if no progerr function registered */ 212 213 if (_z_global_data._z_echo == NULL) { 214 return; 215 } 216 217 /* capture message */ 218 219 va_start(ap, a_format); 220 (void) vsnprintf(message, sizeof (message), a_format, ap); 221 va_end(ap); 222 223 /* pass message to registered function */ 224 225 (_z_global_data._z_echo)("%s", message); 226 } 227 228 /* 229 * Name: _z_echoDebug 230 * Synopsis: Output a debugging message if debugging is enabled 231 * Description: Main method for outputting a debugging message; call to 232 * output debugging message if debugging has been enabled 233 * by a previous call to _z_echoDebugSetFlag(1). 234 * Arguments: format - [RO, RO*] (char *) 235 * printf-style format for debugging message to be output 236 * VARG_LIST - [RO] (?) 237 * arguments as appropriate to 'format' specified 238 * Returns: void 239 * NOTE: format of message will be: 240 * # [ aaa bbb ccc ] message 241 * where: aaa - process i.d. 242 * bbb - zone i.d. 243 * ccc - name of program 244 * for example: 245 * # [ 25685 0 pkgadd ] unable to get package list 246 */ 247 248 /*PRINTFLIKE1*/ 249 void 250 _z_echoDebug(char *a_format, ...) 251 { 252 va_list ap; 253 char message[MAX_MESSAGE_SIZE]; 254 255 /* entry assertions */ 256 257 assert(a_format != NULL); 258 259 /* return if no progerr function registered */ 260 261 if (_z_global_data._z_echo_debug == NULL) { 262 return; 263 } 264 265 /* capture message */ 266 267 va_start(ap, a_format); 268 (void) vsnprintf(message, sizeof (message), a_format, ap); 269 va_end(ap); 270 271 /* pass message to registered function */ 272 273 (_z_global_data._z_echo_debug)("%s", message); 274 } 275 276 /* 277 * Name: _z_is_directory 278 * Description: determine if specified path exists and is a directory 279 * Arguments: path - pointer to string representing the path to verify 280 * returns: 0 - directory exists 281 * 1 - directory does not exist or is not a directory 282 * NOTE: errno is set appropriately 283 */ 284 285 int 286 _z_is_directory(char *path) 287 { 288 struct stat statbuf; 289 290 /* entry assertions */ 291 292 assert(path != NULL); 293 assert(*path != '\0'); 294 295 /* return error if path does not exist */ 296 297 if (stat(path, &statbuf) != 0) { 298 return (1); 299 } 300 301 /* return error if path is not a directory */ 302 303 if ((statbuf.st_mode & S_IFMT) != S_IFDIR) { 304 errno = ENOTDIR; 305 return (1); 306 } 307 308 /* path exists and is a directory */ 309 310 return (0); 311 } 312 313 /* 314 * Name: _z_pluginCatchSigint 315 * Synopsis: SIGINT/SIGHUP interrupt handler 316 * Description: Catch the "SIGINT" and "SIGHUP" signals: 317 * -> increment _z_SigReceived global variable 318 * -> propagate signal to "_z_ChildProcessId" if registered (!= -1) 319 * Arguments: signo - [RO, *RO] - (int) 320 * Signal number that was caught 321 * Returns: void 322 */ 323 324 void 325 _z_sig_trap(int a_signo) 326 { 327 /* bump signals received count */ 328 329 _z_global_data._z_SigReceived++; 330 331 /* if child process registered, propagate signal to child */ 332 333 if (_z_global_data._z_ChildProcessId > 0) { 334 (void) kill(_z_global_data._z_ChildProcessId, a_signo); 335 } 336 } 337 338 /* 339 * Name: _z_program_error 340 * Description: Output an error message to the appropriate destinations 341 * Arguments: format - [RO, RO*] (char *) 342 * printf-style format for debugging message to be output 343 * VARG_LIST - [RO] (?) 344 * arguments as appropriate to 'format' specified 345 * Returns: void 346 * NOTE: format of message will be: 347 * [aaa: ] ERROR: message 348 * where: aaa - program name (if set) 349 * message - results of format and arguments 350 * for example: 351 * ERROR: unable to get package list 352 */ 353 354 /*PRINTFLIKE1*/ 355 void 356 _z_program_error(char *a_format, ...) 357 { 358 va_list ap; 359 char message[MAX_MESSAGE_SIZE]; 360 361 /* entry assertions */ 362 363 assert(a_format != NULL); 364 365 /* return if no progerr function registered */ 366 367 if (_z_global_data._z_progerr == NULL) { 368 return; 369 } 370 371 /* capture message */ 372 373 va_start(ap, a_format); 374 (void) vsnprintf(message, sizeof (message), a_format, ap); 375 va_end(ap); 376 377 /* pass message to registered function */ 378 379 (_z_global_data._z_progerr)(MSG_PROG_ERR, message); 380 } 381 382 /* 383 * Name: _z_running_in_global_zone 384 * Synopsis: Determine if this process is running in the global zone 385 * Arguments: void 386 * Returns: boolean_t 387 * == B_TRUE - this process is running in the global zone 388 * == B_FALSE - this process is running in a nonglobal zone 389 */ 390 391 boolean_t 392 _z_running_in_global_zone(void) 393 { 394 zoneid_t zoneid = (zoneid_t)-1; 395 396 /* 397 * if zones are not implemented, there is no way to tell if zones 398 * are supported or not - in this case, we can only be running in the 399 * global zone (since non-global zones cannot exist) so return TRUE 400 */ 401 402 if (z_zones_are_implemented() == B_FALSE) { 403 return (B_TRUE); 404 } 405 406 /* get the zone i.d. of the current zone */ 407 408 zoneid = getzoneid(); 409 410 /* return TRUE if this is the global zone i.d. */ 411 412 if (zoneid == GLOBAL_ZONEID) { 413 return (B_TRUE); 414 } 415 416 /* return FALSE - not in the global zone */ 417 418 return (B_FALSE); 419 } 420 421 /* 422 * Name: _z_zones_are_implemented 423 * Synopsis: Determine if zones are supported by the current system 424 * Arguments: void 425 * Returns: boolean_t 426 * == B_TRUE - zones are supported 427 * == B_FALSE - zones are not supported 428 */ 429 430 boolean_t 431 _z_zones_are_implemented(void) 432 { 433 void *libptr = NULL; 434 435 /* locate zone cfg library */ 436 437 libptr = dlopen(ZONECFG_LIBRARY, RTLD_NOW|RTLD_GLOBAL); 438 if (libptr == (void *)NULL) { 439 _z_echoDebug(DBG_LIBRARY_NOT_FOUND, ZONECFG_LIBRARY, dlerror()); 440 libptr = dlopen(ZONECFG1_LIBRARY, RTLD_NOW|RTLD_GLOBAL); 441 } 442 443 /* return false if library not available */ 444 445 if (libptr == (void *)NULL) { 446 _z_echoDebug(DBG_LIBRARY_NOT_FOUND, ZONECFG1_LIBRARY, 447 dlerror()); 448 return (B_FALSE); 449 } 450 451 /* library available - close handle */ 452 453 (void) dlclose(libptr); 454 455 /* locate contract filesystem library */ 456 457 libptr = dlopen(CONTRACT_LIBRARY, RTLD_NOW|RTLD_GLOBAL); 458 if (libptr == (void *)NULL) { 459 _z_echoDebug(DBG_LIBRARY_NOT_FOUND, CONTRACT_LIBRARY, 460 dlerror()); 461 libptr = dlopen(CONTRACT1_LIBRARY, RTLD_NOW|RTLD_GLOBAL); 462 } 463 464 /* return false if library not available */ 465 466 if (libptr == (void *)NULL) { 467 _z_echoDebug(DBG_LIBRARY_NOT_FOUND, CONTRACT1_LIBRARY, 468 dlerror()); 469 return (B_FALSE); 470 } 471 472 /* library available - close handle */ 473 474 (void) dlclose(libptr); 475 476 /* return success */ 477 478 return (B_TRUE); 479 } 480 481 boolean_t 482 _z_brands_are_implemented(void) 483 { 484 void *libptr; 485 486 /* locate brand library */ 487 488 libptr = dlopen(BRAND_LIBRARY, RTLD_NOW|RTLD_GLOBAL); 489 if (libptr == NULL) { 490 _z_echoDebug(DBG_LIBRARY_NOT_FOUND, BRAND_LIBRARY, dlerror()); 491 libptr = dlopen(BRAND1_LIBRARY, RTLD_NOW|RTLD_GLOBAL); 492 } 493 494 /* return false if library not available */ 495 496 if (libptr == NULL) { 497 _z_echoDebug(DBG_LIBRARY_NOT_FOUND, BRAND1_LIBRARY, dlerror()); 498 return (B_FALSE); 499 } 500 501 /* library available - close handle */ 502 503 (void) dlclose(libptr); 504 505 /* return success */ 506 507 return (B_TRUE); 508 } 509 510 /* 511 * z_calloc() 512 * Allocate 'size' bytes from the heap using calloc() 513 * Parameters: 514 * size - number of bytes to allocate 515 * Return: 516 * NULL - calloc() failure 517 * void * - pointer to allocated structure 518 * Status: 519 * public 520 */ 521 void * 522 _z_calloc(size_t size) 523 { 524 void * tmp; 525 526 if ((tmp = (void *) malloc(size)) == NULL) { 527 fatal_err_func(ERR_MALLOC_FAIL); 528 return (NULL); 529 } 530 531 (void) memset(tmp, 0, size); 532 return (tmp); 533 } 534 535 /* 536 * z_malloc() 537 * Alloc 'size' bytes from heap using malloc() 538 * Parameters: 539 * size - number of bytes to malloc 540 * Return: 541 * NULL - malloc() failure 542 * void * - pointer to allocated structure 543 * Status: 544 * public 545 */ 546 void * 547 _z_malloc(size_t size) 548 { 549 void *tmp; 550 551 if ((tmp = (void *) malloc(size)) == NULL) { 552 fatal_err_func(ERR_MALLOC_FAIL); 553 return (NULL); 554 } else 555 return (tmp); 556 } 557 558 /* 559 * _z_realloc() 560 * Calls realloc() with the specfied parameters. _z_realloc() 561 * checks for realloc failures and adjusts the return value 562 * automatically. 563 * Parameters: 564 * ptr - pointer to existing data block 565 * size - number of bytes additional 566 * Return: 567 * NULL - realloc() failed 568 * void * - pointer to realloc'd structured 569 * Status: 570 * public 571 */ 572 void * 573 _z_realloc(void *ptr, size_t size) 574 { 575 void *tmp; 576 577 if ((tmp = (void *)realloc(ptr, size)) == (void *)NULL) { 578 fatal_err_func(ERR_MALLOC_FAIL); 579 return ((void *)NULL); 580 } else 581 return (tmp); 582 } 583 584 /* 585 * z_strdup() 586 * Allocate space for the string from the heap, copy 'str' into it, 587 * and return a pointer to it. 588 * Parameters: 589 * str - string to duplicate 590 * Return: 591 * NULL - duplication failed or 'str' was NULL 592 * char * - pointer to newly allocated/initialized structure 593 * Status: 594 * public 595 */ 596 void * 597 _z_strdup(char *str) 598 { 599 char *tmp; 600 601 if (str == NULL) 602 return ((char *)NULL); 603 604 if ((tmp = strdup(str)) == NULL) { 605 fatal_err_func(ERR_MALLOC_FAIL); 606 return ((char *)NULL); 607 } else 608 return (tmp); 609 } 610