8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libinstzones / common / zones_utils.c
blob3b51d145d18c5c11fadc8ad74c0c7016efcbc466
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Module: zones.c
29 * Group: libinstzones
30 * Description: Provide "zones" interface for install consolidation code
32 * Public Methods:
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
50 * System includes
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>
74 * local includes
77 #include "instzones_lib.h"
78 #include "zones_strings.h"
81 * Private structures
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.
90 #define BRAND1_LIBRARY "libbrand.so.1"
91 #define BRAND_LIBRARY "libbrand.so"
94 * Library Function Prototypes
98 * Local Function Prototypes
101 static void error_and_exit(int error_num);
103 static void (*fatal_err_func)() = &error_and_exit;
105 /* ----------------------- private functions -------------------------- */
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
118 static void
119 error_and_exit(int error_num)
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);
129 * *****************************************************************************
130 * global external (public) functions
131 * *****************************************************************************
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
149 _z_close_file_descriptors(void *a_fds, int a_fd)
151 int *fds;
152 int i;
154 /* do not close standard input, output, or error file descriptors */
156 if (a_fd == STDIN_FILENO || a_fd == STDOUT_FILENO ||
157 a_fd == STDERR_FILENO) {
158 return (0);
161 /* if no file descriptor retention list, close this file */
163 if (a_fds == (void *)NULL) {
164 (void) close(a_fd);
165 return (0);
169 * retention list provided, skip this descriptor if its in the list
172 fds = (int *)a_fds;
174 for (i = 0; fds[i] != -1; i++) {
175 if (fds[i] == a_fd) {
176 return (0);
180 /* this descriptor not in retention list - close this file */
182 (void) close(a_fd);
184 return (0);
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
200 /*PRINTFLIKE1*/
201 void
202 _z_echo(char *a_format, ...)
204 va_list ap;
205 char message[MAX_MESSAGE_SIZE];
207 /* entry assertions */
209 assert(a_format != NULL);
211 /* return if no progerr function registered */
213 if (_z_global_data._z_echo == NULL) {
214 return;
217 /* capture message */
219 va_start(ap, a_format);
220 (void) vsnprintf(message, sizeof (message), a_format, ap);
221 va_end(ap);
223 /* pass message to registered function */
225 (_z_global_data._z_echo)("%s", message);
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
248 /*PRINTFLIKE1*/
249 void
250 _z_echoDebug(char *a_format, ...)
252 va_list ap;
253 char message[MAX_MESSAGE_SIZE];
255 /* entry assertions */
257 assert(a_format != NULL);
259 /* return if no progerr function registered */
261 if (_z_global_data._z_echo_debug == NULL) {
262 return;
265 /* capture message */
267 va_start(ap, a_format);
268 (void) vsnprintf(message, sizeof (message), a_format, ap);
269 va_end(ap);
271 /* pass message to registered function */
273 (_z_global_data._z_echo_debug)("%s", message);
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
286 _z_is_directory(char *path)
288 struct stat statbuf;
290 /* entry assertions */
292 assert(path != NULL);
293 assert(*path != '\0');
295 /* return error if path does not exist */
297 if (stat(path, &statbuf) != 0) {
298 return (1);
301 /* return error if path is not a directory */
303 if ((statbuf.st_mode & S_IFMT) != S_IFDIR) {
304 errno = ENOTDIR;
305 return (1);
308 /* path exists and is a directory */
310 return (0);
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
324 void
325 _z_sig_trap(int a_signo)
327 /* bump signals received count */
329 _z_global_data._z_SigReceived++;
331 /* if child process registered, propagate signal to child */
333 if (_z_global_data._z_ChildProcessId > 0) {
334 (void) kill(_z_global_data._z_ChildProcessId, a_signo);
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
354 /*PRINTFLIKE1*/
355 void
356 _z_program_error(char *a_format, ...)
358 va_list ap;
359 char message[MAX_MESSAGE_SIZE];
361 /* entry assertions */
363 assert(a_format != NULL);
365 /* return if no progerr function registered */
367 if (_z_global_data._z_progerr == NULL) {
368 return;
371 /* capture message */
373 va_start(ap, a_format);
374 (void) vsnprintf(message, sizeof (message), a_format, ap);
375 va_end(ap);
377 /* pass message to registered function */
379 (_z_global_data._z_progerr)(MSG_PROG_ERR, message);
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
391 boolean_t
392 _z_running_in_global_zone(void)
394 zoneid_t zoneid = (zoneid_t)-1;
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
402 if (z_zones_are_implemented() == B_FALSE) {
403 return (B_TRUE);
406 /* get the zone i.d. of the current zone */
408 zoneid = getzoneid();
410 /* return TRUE if this is the global zone i.d. */
412 if (zoneid == GLOBAL_ZONEID) {
413 return (B_TRUE);
416 /* return FALSE - not in the global zone */
418 return (B_FALSE);
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
430 boolean_t
431 _z_zones_are_implemented(void)
433 void *libptr = NULL;
435 /* locate zone cfg library */
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);
443 /* return false if library not available */
445 if (libptr == (void *)NULL) {
446 _z_echoDebug(DBG_LIBRARY_NOT_FOUND, ZONECFG1_LIBRARY,
447 dlerror());
448 return (B_FALSE);
451 /* library available - close handle */
453 (void) dlclose(libptr);
455 /* locate contract filesystem library */
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);
464 /* return false if library not available */
466 if (libptr == (void *)NULL) {
467 _z_echoDebug(DBG_LIBRARY_NOT_FOUND, CONTRACT1_LIBRARY,
468 dlerror());
469 return (B_FALSE);
472 /* library available - close handle */
474 (void) dlclose(libptr);
476 /* return success */
478 return (B_TRUE);
481 boolean_t
482 _z_brands_are_implemented(void)
484 void *libptr;
486 /* locate brand library */
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);
494 /* return false if library not available */
496 if (libptr == NULL) {
497 _z_echoDebug(DBG_LIBRARY_NOT_FOUND, BRAND1_LIBRARY, dlerror());
498 return (B_FALSE);
501 /* library available - close handle */
503 (void) dlclose(libptr);
505 /* return success */
507 return (B_TRUE);
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
521 void *
522 _z_calloc(size_t size)
524 void * tmp;
526 if ((tmp = (void *) malloc(size)) == NULL) {
527 fatal_err_func(ERR_MALLOC_FAIL);
528 return (NULL);
531 (void) memset(tmp, 0, size);
532 return (tmp);
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
546 void *
547 _z_malloc(size_t size)
549 void *tmp;
551 if ((tmp = (void *) malloc(size)) == NULL) {
552 fatal_err_func(ERR_MALLOC_FAIL);
553 return (NULL);
554 } else
555 return (tmp);
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
572 void *
573 _z_realloc(void *ptr, size_t size)
575 void *tmp;
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);
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
596 void *
597 _z_strdup(char *str)
599 char *tmp;
601 if (str == NULL)
602 return ((char *)NULL);
604 if ((tmp = strdup(str)) == NULL) {
605 fatal_err_func(ERR_MALLOC_FAIL);
606 return ((char *)NULL);
607 } else
608 return (tmp);