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]
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
30 * Description: Provide "zones" interface for install consolidation code
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
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
64 * z_zlist_get_original_state - Return the original kernal state of the
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
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
89 #include <sys/types.h>
90 #include <sys/param.h>
91 #include <sys/sysmacros.h>
103 #include <sys/brand.h>
106 #include <libzonecfg.h>
107 #include <libcontract.h>
108 #include <sys/contract/process.h>
109 #include <sys/ctfs.h>
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.
125 #define _INSTZONES_LIB_Z_DEFINE_GLOBAL_DATA
126 #include "instzones_lib.h"
127 #include "zones_strings.h"
133 #define CLUSTER_BRAND_NAME "cluster"
135 /* maximum number of arguments to exec() call */
137 #define UUID_FORMAT "%02d%02d%02d%03d-%02d%02d%02d%d-%016llx"
140 * Library Function Prototypes
143 #define streq(a, b) (strcmp((a), (b)) == 0)
146 * Local Function Prototypes
150 * global internal (private) declarations
154 * *****************************************************************************
155 * global external (public) functions
156 * *****************************************************************************
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
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
175 * == B_TRUE - admin file created
176 * == B_FALSE - failed to create admin file
180 z_create_zone_admin_file(char *a_zoneAdminFilename
, char *a_userAdminFilename
)
183 FILE *uFp
= (FILE *)NULL
;
185 /* entry assertions */
187 assert(a_zoneAdminFilename
!= NULL
);
188 assert(*a_zoneAdminFilename
!= '\0');
190 /* create temporary zone admin file */
192 zFp
= fopen(a_zoneAdminFilename
, "w");
193 if (zFp
== (FILE *)NULL
) {
197 /* open user admin file if specified */
199 if (a_userAdminFilename
!= (char *)NULL
) {
200 uFp
= fopen(a_userAdminFilename
, "r");
203 /* create default admin file for zone pkg ops if no user admin file */
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"
213 /* copy user admin file substitute/change appropriate entries */
214 char buf
[LINE_MAX
+1];
217 /* read next line of user admin file */
219 p
= fgets(buf
, sizeof (buf
), uFp
);
220 if (p
== (char *)NULL
) {
225 /* modify / replace / accept as appropriate */
227 if (strncmp(buf
, "instance=quit", 13) == 0) {
228 (void) fprintf(zFp
, "%s", "instance=unique\n");
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");
252 (void) fprintf(zFp
, "%s", buf
);
256 /* close admin file and return success */
263 * Name: z_brands_are_implemented
264 * Description: Determine if any branded zones may be present
267 * == B_TRUE - branded zones are supported
268 * == B_FALSE - branded zones are not supported
272 z_brands_are_implemented(void)
274 static boolean_t _brandsImplementedDetermined
= B_FALSE
;
275 static boolean_t _brandsAreImplemented
= B_FALSE
;
277 /* if availability has not been determined, cache it now */
279 if (!_brandsImplementedDetermined
) {
280 _brandsImplementedDetermined
= B_TRUE
;
281 _brandsAreImplemented
= _z_brands_are_implemented();
282 if (_brandsAreImplemented
) {
283 _z_echoDebug(DBG_BRANDS_ARE_IMPLEMENTED
);
285 _z_echoDebug(DBG_BRANDS_NOT_IMPLEMENTED
);
289 /* return cached answer */
291 return (_brandsAreImplemented
);
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
302 z_free_zone_list(zoneList_t a_zlst
)
306 /* ignore empty list */
308 if (a_zlst
== (zoneList_t
)NULL
) {
312 /* free each entry in the zone list */
314 for (numzones
= 0; a_zlst
[numzones
]._zlName
!= (char *)NULL
;
316 zoneListElement_t
*zelm
= &a_zlst
[numzones
];
318 /* free zone name string */
322 /* free zonepath string */
324 if (zelm
->_zlPath
!= (char *)NULL
) {
330 /* free handle to the list */
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
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.
349 z_get_nonglobal_zone_list(void)
352 zoneBrandList_t
*brands
= NULL
;
354 if ((brands
= z_make_brand_list("native cluster", " ")) == NULL
)
357 zones
= z_get_nonglobal_zone_list_by_brand(brands
);
359 z_free_brand_list(brands
);
365 * Name: z_free_brand_list
366 * Description: Free contents of zoneBrandList_t object
367 * Arguments: brands - pointer to zoneBrandList_t object to free
371 z_free_brand_list(zoneBrandList_t
*brands
)
373 while (brands
!= NULL
) {
374 zoneBrandList_t
*temp
= brands
;
375 free(brands
->string_ptr
);
376 brands
= brands
->next
;
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.
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.
398 z_make_brand_list(const char *brands
, const char *delim
)
400 zoneBrandList_t
*brand
= NULL
, *head
= NULL
;
404 if ((blist
= strdup(brands
)) == NULL
)
407 if ((str
= strtok(blist
, delim
)) != NULL
) {
408 if ((brand
= (zoneBrandList_t
*)
409 malloc(sizeof (struct _zoneBrandList
))) == NULL
) {
414 brand
->string_ptr
= strdup(str
);
417 while ((str
= strtok(NULL
, delim
)) != NULL
) {
418 if ((brand
->next
= (zoneBrandList_t
*)
419 malloc(sizeof (struct _zoneBrandList
))) == NULL
) {
424 brand
->string_ptr
= strdup(str
);
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.
446 z_get_nonglobal_zone_list_by_brand(zoneBrandList_t
*brands
)
451 zoneList_t zlst
= NULL
;
453 char zonename
[ZONENAME_MAX
];
456 /* if zones are not implemented, return empty list */
458 if (!z_zones_are_implemented()) {
459 return ((zoneList_t
)NULL
);
463 * Open the zone index file. Note that getzoneent_private() handles
466 zoneIndexFP
= setzoneent();
468 mapFP
= zonecfg_open_scratch("", B_FALSE
);
470 /* index file open; scan all zones; see if any are at least installed */
472 while ((ze
= getzoneent_private(zoneIndexFP
)) != NULL
) {
475 /* skip the global zone */
477 if (strcmp(ze
->zone_name
, GLOBAL_ZONENAME
) == 0) {
483 * skip any zones with brands not on the brand list
485 if (!z_is_zone_brand_in_list(ze
->zone_name
, brands
)) {
491 * If the user specified an explicit zone list, then ignore any
492 * zones that aren't on that list.
494 if ((zent
= _z_global_data
._zone_spec
) != NULL
) {
495 while (zent
!= NULL
) {
496 if (strcmp(zent
->zl_name
, ze
->zone_name
) == 0)
498 zent
= zent
->zl_next
;
506 /* non-global zone: create entry for this zone */
509 zlst
= (zoneList_t
)_z_calloc(
510 sizeof (zoneListElement_t
)*2);
512 zlst
= (zoneList_t
)_z_realloc(zlst
,
513 sizeof (zoneListElement_t
)*(numzones
+2));
514 (void) memset(&zlst
[numzones
], 0L,
515 sizeof (zoneListElement_t
)*2);
519 * remember the zone name, zonepath and the current
520 * zone state of the zone.
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
;
527 /* get the zone kernel status */
529 if (zone_get_state(ze
->zone_name
, &st
) != Z_OK
) {
530 st
= ZONE_STATE_INCOMPLETE
;
533 _z_echoDebug(DBG_ZONES_NGZ_LIST_STATES
,
534 ze
->zone_name
, ze
->zone_state
, st
);
537 * For a scratch zone, we need to know the kernel zone name.
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
);
547 * remember the current kernel status of the zone.
550 zlst
[numzones
]._zlOrigKernelStatus
= st
;
551 zlst
[numzones
]._zlCurrKernelStatus
= st
;
557 /* close the index file */
558 endzoneent(zoneIndexFP
);
561 zonecfg_close_scratch(mapFP
);
563 /* return generated list */
569 * Name: z_get_zonename
570 * Description: return the name of the current zone
573 * - pointer to string representing the name of the current
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.
584 char zonename
[ZONENAME_MAX
];
585 zoneid_t zoneid
= (zoneid_t
)-1;
587 /* if zones are not implemented, return "" */
589 if (!z_zones_are_implemented()) {
590 return (_z_strdup(""));
593 /* get the zone i.d. of the current zone */
595 zoneid
= getzoneid();
597 /* get the name of the current zone */
599 zonenameLen
= getzonenamebyid(zoneid
, zonename
, sizeof (zonename
));
601 /* return "" if could not get zonename */
603 if (zonenameLen
< 1) {
604 return (_z_strdup(""));
607 return (_z_strdup(zonename
));
611 * Name: z_global_only
612 * Description: Determine if the global zone is only zone on the spec list.
614 * Returns: B_TRUE if global zone is the only zone on the list,
621 /* return true if zones are not implemented - treate as global zone */
623 if (!z_zones_are_implemented()) {
627 /* return true if this is the global zone */
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) {
635 /* return false - not the global zone */
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
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.
652 z_lock_this_zone(ZLOCKS_T a_lflags
)
656 pid_t pid
= (pid_t
)0;
658 /* entry assertions */
660 assert(a_lflags
!= ZLOCKS_NONE
);
662 /* entry debugging info */
664 _z_echoDebug(DBG_ZONES_LCK_THIS
, a_lflags
);
666 zoneName
= z_get_zonename();
669 /* lock zone administration */
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
);
677 (void) free(zoneName
);
682 /* lock package administration always */
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
);
690 (void) z_unlock_this_zone(a_lflags
);
691 (void) free(zoneName
);
696 (void) free(zoneName
);
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
708 * == B_TRUE - success, zones locked
709 * == B_FALSE - failure, zones not locked
713 z_lock_zones(zoneList_t a_zlst
, ZLOCKS_T a_lflags
)
718 /* entry assertions */
720 assert(a_lflags
!= ZLOCKS_NONE
);
722 /* entry debugging info */
724 _z_echoDebug(DBG_ZONES_LCK_ZONES
, a_lflags
);
726 /* if zones are not implemented, return TRUE */
728 if (z_zones_are_implemented() == B_FALSE
) {
729 _z_echoDebug(DBG_ZONES_LCK_ZONES_UNIMP
);
733 /* lock this zone first before locking other zones */
735 b
= z_lock_this_zone(a_lflags
);
740 /* ignore empty list */
742 if (a_zlst
== (zoneList_t
)NULL
) {
743 _z_echoDebug(DBG_ZONES_LCK_ZONES_NOZONES
);
749 _z_echoDebug(DBG_ZONES_LCK_ZONES_EXIST
);
752 * lock each listed zone that is currently running
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
) {
761 /* ignore zone if not running */
762 if (a_zlst
[i
]._zlCurrKernelStatus
!= ZONE_STATE_RUNNING
&&
763 a_zlst
[i
]._zlCurrKernelStatus
!= ZONE_STATE_MOUNTED
) {
768 * mark zone locked - if interrupted out during lock, an attempt
769 * will be made to release the lock
771 a_zlst
[i
]._zlStatus
|= ZST_LOCKED
;
774 b
= _z_lock_zone(&a_zlst
[i
], a_lflags
);
776 /* on failure unlock all zones and return error */
778 _z_program_error(ERR_ZONES_LCK_ZONES_FAILED
,
780 (void) z_unlock_zones(a_zlst
, a_lflags
);
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
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.
819 z_mount_in_lz(char **r_lzMountPoint
, char **r_lzRootPath
, char *a_zoneName
,
820 char *a_gzPath
, char *a_mountPointPrefix
)
822 char lzRootPath
[MAXPATHLEN
] = {'\0'};
823 char uuid
[MAXPATHLEN
] = {'\0'};
824 char gzMountPoint
[MAXPATHLEN
] = {'\0'};
825 char lzMountPoint
[MAXPATHLEN
] = {'\0'};
833 /* entry assertions */
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
);
842 /* entry debugging info */
844 _z_echoDebug(DBG_ZONES_MOUNT_IN_LZ_ENTRY
, a_zoneName
, a_gzPath
);
846 /* reset returned non-global zone mount point path handle */
848 *r_lzMountPoint
= (char *)NULL
;
849 *r_lzRootPath
= (char *)NULL
;
851 /* if zones are not implemented, return FALSE */
853 if (z_zones_are_implemented() == B_FALSE
) {
857 /* error if global zone path is not absolute */
859 if (*a_gzPath
!= '/') {
860 _z_program_error(ERR_GZPATH_NOT_ABSOLUTE
, a_gzPath
);
864 /* error if global zone path does not exist */
866 if (_z_is_directory(a_gzPath
) != 0) {
867 _z_program_error(ERR_GZPATH_NOT_DIR
, a_gzPath
, strerror(errno
));
871 /* verify that specified non-global zone exists */
873 err
= zone_get_id(a_zoneName
, &zid
);
875 _z_program_error(ERR_GET_ZONEID
, a_zoneName
,
876 zonecfg_strerror(err
));
880 /* obtain global zone path to non-global zones root file system */
882 err
= zone_get_rootpath(a_zoneName
, lzRootPath
, sizeof (lzRootPath
));
884 _z_program_error(ERR_NO_ZONE_ROOTPATH
, a_zoneName
,
885 zonecfg_strerror(err
));
889 if (lzRootPath
[0] == '\0') {
890 _z_program_error(ERR_ROOTPATH_EMPTY
, a_zoneName
);
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.
898 z_resolve_lofs(lzRootPath
, sizeof (lzRootPath
));
900 /* verify that the root path exists */
902 if (_z_is_directory(lzRootPath
) != 0) {
903 _z_program_error(ERR_LZROOT_NOTDIR
, lzRootPath
,
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
916 hretime
= gethrtime();
918 thetime
= time((time_t *)NULL
);
919 (void) localtime_r(&thetime
, &tstruct
);
921 slen
= snprintf(uuid
, sizeof (uuid
),
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
));
932 /* create the global zone mount point */
934 slen
= snprintf(gzMountPoint
, sizeof (gzMountPoint
), "%s/.SUNW_%s_%s",
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
));
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
));
954 _z_echoDebug(DBG_MNTPT_NAMES
, a_gzPath
, a_zoneName
, gzMountPoint
,
957 /* error if the mount point already exists */
959 if (_z_is_directory(gzMountPoint
) == 0) {
960 _z_program_error(ERR_ZONEROOT_NOTDIR
, gzMountPoint
,
961 a_zoneName
, strerror(errno
));
965 /* create the temporary mount point */
967 if (mkdir(gzMountPoint
, 0600) != 0) {
968 _z_program_error(ERR_MNTPT_MKDIR
, gzMountPoint
, a_zoneName
,
973 /* mount the global zone path on the non-global zone root file system */
975 err
= mount(a_gzPath
, gzMountPoint
, MS_RDONLY
|MS_DATA
, "lofs",
976 (char *)NULL
, 0, (char *)NULL
, 0);
978 _z_program_error(ERR_GZMOUNT_FAILED
, a_gzPath
,
979 gzMountPoint
, a_zoneName
, strerror(errno
));
983 /* success - return both mountpoints to caller */
985 *r_lzMountPoint
= _z_strdup(gzMountPoint
);
987 *r_lzRootPath
= _z_strdup(lzMountPoint
);
995 * Name: z_non_global_zones_exist
996 * Description: Determine if any non-global native zones exist
999 * == B_TRUE - at least one non-global native zone exists
1000 * == B_FALSE - no non-global native zone exists
1004 z_non_global_zones_exist(void)
1007 boolean_t anyExist
= B_FALSE
;
1011 /* if zones are not implemented, return FALSE */
1013 if (z_zones_are_implemented() == B_FALSE
) {
1017 /* determine if any zones are configured */
1018 zoneIndexFP
= setzoneent();
1019 if (zoneIndexFP
== NULL
) {
1023 /* index file open; scan all zones; see if any are at least installed */
1025 while ((ze
= getzoneent_private(zoneIndexFP
)) != NULL
) {
1027 * If the user specified an explicit zone list, then ignore any
1028 * zones that aren't on that list.
1030 if ((zent
= _z_global_data
._zone_spec
) != NULL
) {
1031 while (zent
!= NULL
) {
1032 if (strcmp(zent
->zl_name
, ze
->zone_name
) == 0)
1034 zent
= zent
->zl_next
;
1042 /* skip the global zone */
1043 if (strcmp(ze
->zone_name
, GLOBAL_ZONENAME
) == 0) {
1048 /* skip any branded zones */
1049 if (z_is_zone_branded(ze
->zone_name
)) {
1054 /* is this zone installed? */
1055 if (ze
->zone_state
>= ZONE_STATE_INSTALLED
) {
1063 /* close the index file */
1065 endzoneent(zoneIndexFP
);
1067 /* return results */
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.
1081 z_on_zone_spec(const char *zonename
)
1085 /* entry assertions */
1087 assert(zonename
!= NULL
);
1088 assert(*zonename
!= '\0');
1090 /* return true if zones not implemented or no zone spec list defined */
1092 if (!z_zones_are_implemented() || _z_global_data
._zone_spec
== NULL
) {
1096 /* return true if named zone is on the zone spec list */
1098 for (zent
= _z_global_data
._zone_spec
;
1099 zent
!= NULL
; zent
= zent
->zl_next
) {
1100 if (strcmp(zent
->zl_name
, zonename
) == 0)
1104 /* named zone is not on the zone spec list */
1110 * Name: z_running_in_global_zone
1111 * Description: Determine if running in the "global" zone
1113 * Returns: boolean_t
1114 * == B_TRUE - running in global zone
1115 * == B_FALSE - not running in global zone
1119 z_running_in_global_zone(void)
1121 static boolean_t _zoneIdDetermined
= B_FALSE
;
1122 static boolean_t _zoneIsGlobal
= B_FALSE
;
1124 /* if ID has not been determined, cache it now */
1126 if (!_zoneIdDetermined
) {
1127 _zoneIdDetermined
= B_TRUE
;
1128 _zoneIsGlobal
= _z_running_in_global_zone();
1131 return (_zoneIsGlobal
);
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
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")
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
)
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
;
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
1172 * NOTE: Must be called before performing any zone-related operations.
1173 * (Currently called directly by set_inst_root() during -R
1174 * argument handling.)
1178 z_set_zone_root(const char *zroot
)
1182 /* if zones are not implemented, just return */
1184 if (!z_zones_are_implemented())
1187 /* entry assertions */
1189 assert(zroot
!= NULL
);
1191 rootdir
= _z_strdup((char *)zroot
);
1192 z_canoninplace(rootdir
);
1194 if (strcmp(rootdir
, "/") == 0) {
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
;
1204 /* store duplicate of new zone root path */
1206 if (*rootdir
!= '\0') {
1207 _z_global_data
._z_root_dir
= _z_strdup(rootdir
);
1209 _z_global_data
._z_root_dir
= "";
1212 /* set zone root path */
1214 zonecfg_set_root(rootdir
);
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.
1229 z_set_zone_spec(const char *zlist
)
1235 zone_spec_t
**znextp
= &zhead
;
1237 /* entry assertions */
1239 assert(zlist
!= NULL
);
1241 /* parse list to zone_spec_t list, store in global data */
1244 while (isspace(*zlist
)) {
1247 if (*zlist
== '\0') {
1250 for (zend
= zlist
; *zend
!= '\0'; zend
++) {
1251 if (isspace(*zend
)) {
1255 zlen
= ((ptrdiff_t)zend
) - ((ptrdiff_t)zlist
);
1256 if (zlen
>= ZONENAME_MAX
) {
1257 _z_program_error(ERR_ZONE_NAME_ILLEGAL
, zlen
, zlist
);
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
;
1265 znextp
= &zent
->zl_next
;
1270 if (zhead
== NULL
) {
1271 _z_program_error(ERR_ZONE_LIST_EMPTY
);
1275 _z_global_data
._zone_spec
= zhead
;
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
1289 z_umount_lz_mount(char *a_lzMountPoint
)
1293 /* entry assertions */
1295 assert(a_lzMountPoint
!= (char *)NULL
);
1296 assert(*a_lzMountPoint
!= '\0');
1298 /* entry debugging info */
1300 _z_echoDebug(DBG_ZONES_UNMOUNT_FROM_LZ_ENTRY
, a_lzMountPoint
);
1302 /* if zones are not implemented, return TRUE */
1304 if (z_zones_are_implemented() == B_FALSE
) {
1308 /* error if global zone path is not absolute */
1310 if (*a_lzMountPoint
!= '/') {
1311 _z_program_error(ERR_LZMNTPT_NOT_ABSOLUTE
, a_lzMountPoint
);
1315 /* verify mount point exists */
1317 if (_z_is_directory(a_lzMountPoint
) != 0) {
1318 _z_program_error(ERR_LZMNTPT_NOTDIR
, a_lzMountPoint
,
1325 err
= umount2(a_lzMountPoint
, 0);
1327 _z_program_error(ERR_GZUMOUNT_FAILED
, a_lzMountPoint
,
1332 /* remove the mount point */
1334 (void) remove(a_lzMountPoint
);
1336 /* return success */
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.
1353 z_unlock_this_zone(ZLOCKS_T a_lflags
)
1356 boolean_t errors
= B_FALSE
;
1359 /* entry assertions */
1361 assert(a_lflags
!= ZLOCKS_NONE
);
1363 /* entry debugging info */
1365 _z_echoDebug(DBG_ZONES_ULK_THIS
, a_lflags
);
1367 /* return if no objects locked */
1369 if ((_z_global_data
._z_ObjectLocks
== (char *)NULL
) ||
1370 (*_z_global_data
._z_ObjectLocks
== '\0')) {
1374 zoneName
= z_get_zonename();
1376 /* unlock package administration */
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
);
1386 /* unlock zone administration */
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
);
1396 (void) free(zoneName
);
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
1412 z_unlock_zones(zoneList_t a_zlst
, ZLOCKS_T a_lflags
)
1415 boolean_t errors
= B_FALSE
;
1418 /* entry assertions */
1420 assert(a_lflags
!= ZLOCKS_NONE
);
1422 /* entry debugging info */
1424 _z_echoDebug(DBG_ZONES_ULK_ZONES
, a_lflags
);
1426 /* if zones are not implemented, return TRUE */
1428 if (z_zones_are_implemented() == B_FALSE
) {
1429 _z_echoDebug(DBG_ZONES_ULK_ZONES_UNIMP
);
1433 /* ignore empty list */
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
));
1443 _z_echoDebug(DBG_ZONES_ULK_ZONES_EXIST
);
1446 * unlock each listed zone that is currently running
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
)) {
1455 /* ignore zone if not running */
1456 if (a_zlst
[i
]._zlCurrKernelStatus
!= ZONE_STATE_RUNNING
&&
1457 a_zlst
[i
]._zlCurrKernelStatus
!= ZONE_STATE_MOUNTED
) {
1461 /* unlock this zone */
1462 b
= _z_unlock_zone(&a_zlst
[i
], a_lflags
);
1467 /* mark zone as unlocked */
1468 a_zlst
[i
]._zlStatus
&= ~ZST_LOCKED
;
1472 /* unlock this zone */
1474 if (z_unlock_this_zone(a_lflags
) != B_TRUE
) {
1482 * Name: z_verify_zone_spec
1483 * Description: Verify list of zones on which actions will be performed.
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).
1492 z_verify_zone_spec(void)
1496 char zoneIndexPath
[MAXPATHLEN
];
1500 if (!z_zones_are_implemented()) {
1501 _z_program_error(ERR_ZONES_NOT_IMPLEMENTED
);
1505 zoneIndexFP
= setzoneent();
1506 if (zoneIndexFP
== NULL
) {
1507 _z_program_error(ERR_ZONEINDEX_OPEN
, zoneIndexPath
,
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
;
1522 endzoneent(zoneIndexFP
);
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
);
1532 return (errors
? -1 : 0);
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
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".
1552 z_zlist_change_zone_state(zoneList_t a_zlst
, int a_zoneIndex
,
1553 zone_state_t a_newState
)
1557 /* entry debugging info */
1559 _z_echoDebug(DBG_ZONES_CHG_Z_STATE_ENTRY
, a_zoneIndex
, a_newState
);
1561 /* ignore empty list */
1563 if (a_zlst
== (zoneList_t
)NULL
) {
1567 /* find the specified zone in the list */
1569 for (i
= 0; (i
!= a_zoneIndex
) &&
1570 (a_zlst
[i
]._zlName
!= (char *)NULL
); i
++)
1573 /* return error if the specified zone does not exist */
1575 if (a_zlst
[i
]._zlName
== (char *)NULL
) {
1579 /* return success if the zone is already in this state */
1581 if (a_zlst
[i
]._zlCurrKernelStatus
== a_newState
) {
1585 /* take action on new state to set zone to */
1587 _z_echoDebug(DBG_ZONES_CHG_Z_STATE
, a_zlst
[i
]._zlName
,
1588 a_zlst
[i
]._zlCurrKernelStatus
, a_newState
);
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
]));
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
]));
1601 case ZONE_STATE_READY
:
1602 return (_z_make_zone_ready(&a_zlst
[i
]));
1604 case ZONE_STATE_CONFIGURED
:
1605 case ZONE_STATE_INCOMPLETE
:
1606 case ZONE_STATE_SHUTTING_DOWN
:
1608 /* do not know how to change zone to this state */
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
1622 z_is_zone_branded(char *zoneName
)
1624 char brandname
[MAXNAMELEN
];
1627 /* if zones are not implemented, return FALSE */
1628 if (!z_zones_are_implemented()) {
1632 /* if brands are not implemented, return FALSE */
1633 if (!z_brands_are_implemented()) {
1637 err
= zone_get_brand(zoneName
, brandname
, sizeof (brandname
));
1639 _z_program_error(ERR_BRAND_GETBRAND
, zonecfg_strerror(err
));
1644 * Both "native" and "cluster" are native brands
1645 * that use the standard facilities in the areas
1646 * of packaging/installation/update.
1648 if (streq(brandname
, NATIVE_BRAND_NAME
) ||
1649 streq(brandname
, CLUSTER_BRAND_NAME
)) {
1657 * Name: z_is_zone_brand_in_list
1658 * Description: Determine whether zone's brand has a match in the list
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
1667 z_is_zone_brand_in_list(char *zoneName
, zoneBrandList_t
*list
)
1669 char brandname
[MAXNAMELEN
];
1671 zoneBrandList_t
*sp
;
1673 if (zoneName
== NULL
|| list
== NULL
)
1676 /* if zones are not implemented, return FALSE */
1677 if (!z_zones_are_implemented()) {
1681 /* if brands are not implemented, return FALSE */
1682 if (!z_brands_are_implemented()) {
1686 err
= zone_get_brand(zoneName
, brandname
, sizeof (brandname
));
1688 _z_program_error(ERR_BRAND_GETBRAND
, zonecfg_strerror(err
));
1692 for (sp
= list
; sp
!= NULL
; sp
= sp
->next
) {
1693 if (sp
->string_ptr
!= NULL
&&
1694 strcmp(sp
->string_ptr
, brandname
) == 0) {
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
1712 z_zlist_get_current_state(zoneList_t a_zlst
, int a_zoneIndex
)
1716 /* ignore empty list */
1718 if (a_zlst
== (zoneList_t
)NULL
) {
1719 return (ZONE_STATE_INCOMPLETE
);
1722 /* find the specified zone in the list */
1724 for (i
= 0; (i
!= a_zoneIndex
) &&
1725 (a_zlst
[i
]._zlName
!= (char *)NULL
); i
++)
1728 /* return error if the specified zone does not exist */
1730 if (a_zlst
[i
]._zlName
== (char *)NULL
) {
1731 return (ZONE_STATE_INCOMPLETE
);
1734 /* return selected zone's current kernel state */
1736 _z_echoDebug(DBG_ZONES_GET_ZONE_STATE
,
1737 a_zlst
[i
]._zlName
? a_zlst
[i
]._zlName
: "",
1738 a_zlst
[i
]._zlCurrKernelStatus
);
1740 return (a_zlst
[i
]._zlCurrKernelStatus
);
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.
1755 z_zlist_get_original_state(zoneList_t a_zlst
, int a_zoneIndex
)
1759 /* ignore empty list */
1761 if (a_zlst
== (zoneList_t
)NULL
) {
1762 return (ZONE_STATE_INCOMPLETE
);
1765 /* find the specified zone in the list */
1767 for (i
= 0; (i
!= a_zoneIndex
) &&
1768 (a_zlst
[i
]._zlName
!= (char *)NULL
); i
++)
1771 /* return error if the specified zone does not exist */
1773 if (a_zlst
[i
]._zlName
== (char *)NULL
) {
1774 return (ZONE_STATE_INCOMPLETE
);
1777 /* return selected zone's original kernel state */
1779 return (a_zlst
[i
]._zlOrigKernelStatus
);
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
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.
1795 z_zlist_get_scratch(zoneList_t a_zlst
, int a_zoneIndex
)
1799 /* ignore empty list */
1804 /* find the specified zone in the list */
1806 for (i
= 0; i
!= a_zoneIndex
; i
++) {
1807 if (a_zlst
[i
]._zlName
== NULL
)
1811 /* return selected zone's scratch name */
1813 return (a_zlst
[i
]._zlScratchName
== NULL
? a_zlst
[i
]._zlName
:
1814 a_zlst
[i
]._zlScratchName
);
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
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.
1830 z_zlist_get_zonename(zoneList_t a_zlst
, int a_zoneIndex
)
1834 /* ignore empty list */
1836 if (a_zlst
== (zoneList_t
)NULL
) {
1837 return ((char *)NULL
);
1840 /* find the specified zone in the list */
1842 for (i
= 0; (i
!= a_zoneIndex
) &&
1843 (a_zlst
[i
]._zlName
!= (char *)NULL
); i
++)
1846 /* return error if the specified zone does not exist */
1848 if (a_zlst
[i
]._zlName
== (char *)NULL
) {
1852 /* return selected zone's name */
1854 return (a_zlst
[i
]._zlName
);
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
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.
1870 z_zlist_get_zonepath(zoneList_t a_zlst
, int a_zoneIndex
)
1874 /* ignore empty list */
1876 if (a_zlst
== (zoneList_t
)NULL
) {
1877 return ((char *)NULL
);
1880 /* find the specified zone in the list */
1882 for (i
= 0; (i
!= a_zoneIndex
) &&
1883 (a_zlst
[i
]._zlName
!= (char *)NULL
); i
++)
1886 /* return error if the specified zone does not exist */
1888 if (a_zlst
[i
]._zlName
== (char *)NULL
) {
1892 /* return selected zone's zonepath */
1894 return (a_zlst
[i
]._zlPath
);
1898 z_zlist_is_zone_runnable(zoneList_t a_zlst
, int a_zoneIndex
)
1902 /* if zones are not implemented, return error */
1904 if (z_zones_are_implemented() == B_FALSE
) {
1908 /* ignore empty list */
1910 if (a_zlst
== (zoneList_t
)NULL
) {
1914 /* find the specified zone in the list */
1916 for (i
= 0; (i
!= a_zoneIndex
) &&
1917 (a_zlst
[i
]._zlName
!= (char *)NULL
); i
++)
1920 /* return error if the specified zone does not exist */
1922 if (a_zlst
[i
]._zlName
== (char *)NULL
) {
1926 /* choose based on current state */
1928 switch (a_zlst
[i
]._zlCurrKernelStatus
) {
1929 case ZONE_STATE_RUNNING
:
1930 case ZONE_STATE_MOUNTED
:
1931 /* already running */
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 */
1940 if (a_zlst
[i
]._zlStatus
& ZST_NOT_BOOTABLE
) {
1946 case ZONE_STATE_CONFIGURED
:
1947 case ZONE_STATE_INCOMPLETE
:
1949 /* cannot transition (boot) these states */
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
1966 z_zlist_restore_zone_state(zoneList_t a_zlst
, int a_zoneIndex
)
1970 /* ignore empty list */
1972 if (a_zlst
== (zoneList_t
)NULL
) {
1976 /* find the specified zone in the list */
1978 for (i
= 0; (i
!= a_zoneIndex
) &&
1979 (a_zlst
[i
]._zlName
!= (char *)NULL
); i
++)
1982 /* return error if the specified zone does not exist */
1984 if (a_zlst
[i
]._zlName
== (char *)NULL
) {
1988 /* transition the zone back to its original state */
1990 return (z_zlist_change_zone_state(a_zlst
,
1991 a_zoneIndex
, a_zlst
[i
]._zlOrigKernelStatus
));
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
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
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
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.
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.
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
)
2043 struct sigaction nact
;
2044 struct sigaction oact
;
2045 void (*funcSighup
)();
2046 void (*funcSigint
)();
2048 /* if zones are not implemented, return TRUE */
2050 if (z_zones_are_implemented() == B_FALSE
) {
2051 return (-6); /* -6 : zones are not supported */
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 */
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
2065 (void) sighold(SIGINT
);
2066 (void) sighold(SIGHUP
);
2068 _z_global_data
._z_SigReceived
= 0; /* no signals received */
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
2077 child_pid
= fork1();
2079 if (child_pid
< 0) {
2081 * *************************************************************
2083 * *************************************************************
2086 (void) ct_tmpl_clear(tmpl_fd
);
2087 (void) close(tmpl_fd
);
2088 _z_program_error(ERR_FORK
, strerror(errno
));
2090 /* release hold on signals */
2092 (void) sigrelse(SIGHUP
);
2093 (void) sigrelse(SIGINT
);
2095 return (-3); /* -3 : fork() failed */
2098 if (child_pid
== 0) {
2102 * *************************************************************
2103 * This is the forked (child) process
2104 * *************************************************************
2107 (void) ct_tmpl_clear(tmpl_fd
);
2108 (void) close(tmpl_fd
);
2110 /* reset any signals to default */
2112 for (i
= 0; i
< NSIG
; i
++) {
2113 (void) sigset(i
, SIG_DFL
);
2117 * close all file descriptors not in the a_fds list
2120 (void) fdwalk(&_z_close_file_descriptors
, (void *)a_fds
);
2123 * if a file for stdout is present, open the file and use the
2124 * file to capture stdout from the _zexec process
2127 if (a_stdoutPath
!= (char *)NULL
) {
2130 stdoutfd
= open(a_stdoutPath
,
2131 O_WRONLY
|O_CREAT
|O_TRUNC
, 0600);
2133 _z_program_error(ERR_CAPTURE_FILE
, a_stdoutPath
,
2138 (void) dup2(stdoutfd
, STDOUT_FILENO
);
2139 (void) close(stdoutfd
);
2143 * if a file for stderr is present, open the file and use the
2144 * file to capture stderr from the _zexec process
2147 if (a_stderrPath
!= (char *)NULL
) {
2150 stderrfd
= open(a_stderrPath
,
2151 O_WRONLY
|O_CREAT
|O_TRUNC
, 0600);
2153 _z_program_error(ERR_CAPTURE_FILE
, a_stderrPath
,
2158 (void) dup2(stderrfd
, STDERR_FILENO
);
2159 (void) close(stderrfd
);
2162 /* release all held signals */
2164 (void) sigrelse(SIGHUP
);
2165 (void) sigrelse(SIGINT
);
2167 /* execute command in the specified non-global zone */
2169 _exit(_zexec(a_zoneName
, a_path
, a_argv
));
2173 * *********************************************************************
2174 * This is the forking (parent) process
2175 * *********************************************************************
2178 /* register child process i.d. so signal handlers can pass signal on */
2180 _z_global_data
._z_ChildProcessId
= child_pid
;
2183 * setup signal handlers for SIGINT and SIGHUP and release hold
2186 /* hook SIGINT to _z_sig_trap() */
2188 nact
.sa_handler
= _z_sig_trap
;
2189 nact
.sa_flags
= SA_RESTART
;
2190 (void) sigemptyset(&nact
.sa_mask
);
2192 if (sigaction(SIGINT
, &nact
, &oact
) < 0) {
2193 funcSigint
= SIG_DFL
;
2195 funcSigint
= oact
.sa_handler
;
2198 /* hook SIGHUP to _z_sig_trap() */
2200 nact
.sa_handler
= _z_sig_trap
;
2201 nact
.sa_flags
= SA_RESTART
;
2202 (void) sigemptyset(&nact
.sa_mask
);
2204 if (sigaction(SIGHUP
, &nact
, &oact
) < 0) {
2205 funcSighup
= SIG_DFL
;
2207 funcSighup
= oact
.sa_handler
;
2210 /* release hold on signals */
2212 (void) sigrelse(SIGHUP
);
2213 (void) sigrelse(SIGINT
);
2215 (void) ct_tmpl_clear(tmpl_fd
);
2216 (void) close(tmpl_fd
);
2219 * wait for the process to exit, reap child exit status
2223 result_pid
= waitpid(child_pid
, &status
, 0L);
2224 lerrno
= (result_pid
== -1 ? errno
: 0);
2226 /* break loop if child process status reaped */
2228 if (result_pid
!= -1) {
2232 /* break loop if not interrupted out of waitpid */
2234 if (errno
!= EINTR
) {
2239 /* reset child process i.d. so signal handlers do not pass signals on */
2241 _z_global_data
._z_ChildProcessId
= -1;
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.
2250 if (WIFEXITED(status
)) {
2251 final_status
= WEXITSTATUS(status
);
2252 if ((_z_global_data
._z_SigReceived
!= 0) &&
2253 (final_status
== 0)) {
2257 final_status
= -1; /* -1 : failure to exec process */
2260 /* determine proper exit code */
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 */
2269 * reset signal handlers
2274 nact
.sa_handler
= funcSigint
;
2275 nact
.sa_flags
= SA_RESTART
;
2276 (void) sigemptyset(&nact
.sa_mask
);
2278 (void) sigaction(SIGINT
, &nact
, (struct sigaction
*)NULL
);
2282 nact
.sa_handler
= funcSighup
;
2283 nact
.sa_flags
= SA_RESTART
;
2284 (void) sigemptyset(&nact
.sa_mask
);
2286 (void) sigaction(SIGHUP
, &nact
, (struct sigaction
*)NULL
);
2289 * if signal received during command execution, interrupt
2293 if (_z_global_data
._z_SigReceived
!= 0) {
2294 (void) kill(getpid(), SIGINT
);
2297 /* set errno and return */
2301 return (final_status
);
2305 * Name: z_zones_are_implemented
2306 * Description: Determine if any zone operations can be performed
2308 * Returns: boolean_t
2309 * == B_TRUE - zone operations are available
2310 * == B_FALSE - no zone operations can be done
2314 z_zones_are_implemented(void)
2316 static boolean_t _zonesImplementedDetermined
= B_FALSE
;
2317 static boolean_t _zonesAreImplemented
= B_FALSE
;
2319 /* if availability has not been determined, cache it now */
2321 if (!_zonesImplementedDetermined
) {
2322 _zonesImplementedDetermined
= B_TRUE
;
2323 _zonesAreImplemented
= _z_zones_are_implemented();
2324 if (!_zonesAreImplemented
) {
2325 _z_echoDebug(DBG_ZONES_NOT_IMPLEMENTED
);
2327 _z_echoDebug(DBG_ZONES_ARE_IMPLEMENTED
);
2331 return (_zonesAreImplemented
);