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