Print this page
2594 implement graceful shutdown for local zones in zoneadm
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libbrand/common/libbrand.c
+++ new/usr/src/lib/libbrand/common/libbrand.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) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24 + * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
24 25 */
25 26
26 27 #include <assert.h>
27 28 #include <dirent.h>
28 29 #include <errno.h>
29 30 #include <fnmatch.h>
30 31 #include <signal.h>
31 32 #include <stdlib.h>
32 33 #include <unistd.h>
33 34 #include <strings.h>
34 35 #include <synch.h>
35 36 #include <sys/brand.h>
36 37 #include <sys/fcntl.h>
37 38 #include <sys/param.h>
38 39 #include <sys/stat.h>
39 40 #include <sys/systeminfo.h>
40 41 #include <sys/types.h>
41 42 #include <thread.h>
42 43 #include <zone.h>
43 44
44 45 #include <libbrand_impl.h>
45 46 #include <libbrand.h>
46 47
47 48 #define DTD_ELEM_ATTACH ((const xmlChar *) "attach")
48 49 #define DTD_ELEM_BOOT ((const xmlChar *) "boot")
49 50 #define DTD_ELEM_BRAND ((const xmlChar *) "brand")
50 51 #define DTD_ELEM_CLONE ((const xmlChar *) "clone")
51 52 #define DTD_ELEM_COMMENT ((const xmlChar *) "comment")
52 53 #define DTD_ELEM_DETACH ((const xmlChar *) "detach")
53 54 #define DTD_ELEM_DEVICE ((const xmlChar *) "device")
54 55 #define DTD_ELEM_GLOBAL_MOUNT ((const xmlChar *) "global_mount")
55 56 #define DTD_ELEM_HALT ((const xmlChar *) "halt")
56 57 #define DTD_ELEM_INITNAME ((const xmlChar *) "initname")
57 58 #define DTD_ELEM_INSTALL ((const xmlChar *) "install")
58 59 #define DTD_ELEM_INSTALLOPTS ((const xmlChar *) "installopts")
59 60 #define DTD_ELEM_LOGIN_CMD ((const xmlChar *) "login_cmd")
60 61 #define DTD_ELEM_FORCELOGIN_CMD ((const xmlChar *) "forcedlogin_cmd")
61 62 #define DTD_ELEM_MODNAME ((const xmlChar *) "modname")
62 63 #define DTD_ELEM_MOUNT ((const xmlChar *) "mount")
63 64 #define DTD_ELEM_POSTATTACH ((const xmlChar *) "postattach")
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
64 65 #define DTD_ELEM_POSTCLONE ((const xmlChar *) "postclone")
65 66 #define DTD_ELEM_POSTINSTALL ((const xmlChar *) "postinstall")
66 67 #define DTD_ELEM_POSTSNAP ((const xmlChar *) "postsnap")
67 68 #define DTD_ELEM_POSTSTATECHG ((const xmlChar *) "poststatechange")
68 69 #define DTD_ELEM_PREDETACH ((const xmlChar *) "predetach")
69 70 #define DTD_ELEM_PRESNAP ((const xmlChar *) "presnap")
70 71 #define DTD_ELEM_PRESTATECHG ((const xmlChar *) "prestatechange")
71 72 #define DTD_ELEM_PREUNINSTALL ((const xmlChar *) "preuninstall")
72 73 #define DTD_ELEM_PRIVILEGE ((const xmlChar *) "privilege")
73 74 #define DTD_ELEM_QUERY ((const xmlChar *) "query")
75 +#define DTD_ELEM_SHUTDOWN ((const xmlChar *) "shutdown")
74 76 #define DTD_ELEM_SYMLINK ((const xmlChar *) "symlink")
75 77 #define DTD_ELEM_SYSBOOT ((const xmlChar *) "sysboot")
76 78 #define DTD_ELEM_UNINSTALL ((const xmlChar *) "uninstall")
77 79 #define DTD_ELEM_USER_CMD ((const xmlChar *) "user_cmd")
78 80 #define DTD_ELEM_VALIDSNAP ((const xmlChar *) "validatesnap")
79 81 #define DTD_ELEM_VERIFY_CFG ((const xmlChar *) "verify_cfg")
80 82 #define DTD_ELEM_VERIFY_ADM ((const xmlChar *) "verify_adm")
81 83
82 84 #define DTD_ATTR_ALLOWEXCL ((const xmlChar *) "allow-exclusive-ip")
83 85 #define DTD_ATTR_ARCH ((const xmlChar *) "arch")
84 86 #define DTD_ATTR_DIRECTORY ((const xmlChar *) "directory")
85 87 #define DTD_ATTR_IPTYPE ((const xmlChar *) "ip-type")
86 88 #define DTD_ATTR_MATCH ((const xmlChar *) "match")
87 89 #define DTD_ATTR_MODE ((const xmlChar *) "mode")
88 90 #define DTD_ATTR_NAME ((const xmlChar *) "name")
89 91 #define DTD_ATTR_OPT ((const xmlChar *) "opt")
90 92 #define DTD_ATTR_PATH ((const xmlChar *) "path")
91 93 #define DTD_ATTR_SET ((const xmlChar *) "set")
92 94 #define DTD_ATTR_SOURCE ((const xmlChar *) "source")
93 95 #define DTD_ATTR_SPECIAL ((const xmlChar *) "special")
94 96 #define DTD_ATTR_TARGET ((const xmlChar *) "target")
95 97 #define DTD_ATTR_TYPE ((const xmlChar *) "type")
96 98
97 99 #define DTD_ENTITY_TRUE "true"
98 100
99 101 static volatile boolean_t libbrand_initialized = B_FALSE;
100 102 static char i_curr_arch[MAXNAMELEN];
101 103 static char i_curr_zone[ZONENAME_MAX];
102 104
103 105 /*ARGSUSED*/
104 106 static void
105 107 brand_error_func(void *ctx, const char *msg, ...)
106 108 {
107 109 /*
108 110 * Ignore error messages from libxml
109 111 */
110 112 }
111 113
112 114 static boolean_t
113 115 libbrand_initialize()
114 116 {
115 117 static mutex_t initialize_lock = DEFAULTMUTEX;
116 118
117 119 (void) mutex_lock(&initialize_lock);
118 120
119 121 if (libbrand_initialized) {
120 122 (void) mutex_unlock(&initialize_lock);
121 123 return (B_TRUE);
122 124 }
123 125
124 126 if (sysinfo(SI_ARCHITECTURE, i_curr_arch, sizeof (i_curr_arch)) < 0) {
125 127 (void) mutex_unlock(&initialize_lock);
126 128 return (B_FALSE);
127 129 }
128 130
129 131 if (getzonenamebyid(getzoneid(), i_curr_zone,
130 132 sizeof (i_curr_zone)) < 0) {
131 133 (void) mutex_unlock(&initialize_lock);
132 134 return (B_FALSE);
133 135 }
134 136
135 137 /*
136 138 * Note that here we're initializing per-process libxml2
137 139 * state. By doing so we're implicitly assuming that
138 140 * no other code in this process is also trying to
139 141 * use libxml2. But in most case we know this not to
140 142 * be true since we're almost always used in conjunction
141 143 * with libzonecfg, which also uses libxml2. Lucky for
142 144 * us, libzonecfg initializes libxml2 to essentially
143 145 * the same defaults as we're using below.
144 146 */
145 147 (void) xmlLineNumbersDefault(1);
146 148 xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
147 149 xmlDoValidityCheckingDefaultValue = 1;
148 150 (void) xmlKeepBlanksDefault(0);
149 151 xmlGetWarningsDefaultValue = 0;
150 152 xmlSetGenericErrorFunc(NULL, brand_error_func);
151 153
152 154 libbrand_initialized = B_TRUE;
153 155 (void) mutex_unlock(&initialize_lock);
154 156 return (B_TRUE);
155 157 }
156 158
157 159 static const char *
158 160 get_curr_arch(void)
159 161 {
160 162 if (!libbrand_initialize())
161 163 return (NULL);
162 164
163 165 return (i_curr_arch);
164 166 }
165 167
166 168 static const char *
167 169 get_curr_zone(void)
168 170 {
169 171 if (!libbrand_initialize())
170 172 return (NULL);
171 173
172 174 return (i_curr_zone);
173 175 }
174 176
175 177 /*
176 178 * Internal function to open an XML file
177 179 *
178 180 * Returns the XML doc pointer, or NULL on failure. It will validate the
179 181 * document, as well as removing any comments from the document structure.
180 182 */
181 183 static xmlDocPtr
182 184 open_xml_file(const char *file)
183 185 {
184 186 xmlDocPtr doc;
185 187 xmlValidCtxtPtr cvp;
186 188 int valid;
187 189
188 190 if (!libbrand_initialize())
189 191 return (NULL);
190 192
191 193 /*
192 194 * Parse the file
193 195 */
194 196 if ((doc = xmlParseFile(file)) == NULL)
195 197 return (NULL);
196 198
197 199 /*
198 200 * Validate the file
199 201 */
200 202 if ((cvp = xmlNewValidCtxt()) == NULL) {
201 203 xmlFreeDoc(doc);
202 204 return (NULL);
203 205 }
204 206 cvp->error = brand_error_func;
205 207 cvp->warning = brand_error_func;
206 208 valid = xmlValidateDocument(cvp, doc);
207 209 xmlFreeValidCtxt(cvp);
208 210 if (valid == 0) {
209 211 xmlFreeDoc(doc);
210 212 return (NULL);
211 213 }
212 214
213 215 return (doc);
214 216 }
215 217 /*
216 218 * Open a handle to the named brand.
217 219 *
218 220 * Returns a handle to the named brand, which is used for all subsequent brand
219 221 * interaction, or NULL if unable to open or initialize the brand.
220 222 */
221 223 brand_handle_t
222 224 brand_open(const char *name)
223 225 {
224 226 struct brand_handle *bhp;
225 227 char path[MAXPATHLEN];
226 228 xmlNodePtr node;
227 229 xmlChar *property;
228 230 struct stat statbuf;
229 231
230 232 /*
231 233 * Make sure brand name isn't too long
232 234 */
233 235 if (strlen(name) >= MAXNAMELEN)
234 236 return (NULL);
235 237
236 238 /*
237 239 * Check that the brand exists
238 240 */
239 241 (void) snprintf(path, sizeof (path), "%s/%s", BRAND_DIR, name);
240 242
241 243 if (stat(path, &statbuf) != 0)
242 244 return (NULL);
243 245
244 246 /*
245 247 * Allocate brand handle
246 248 */
247 249 if ((bhp = malloc(sizeof (struct brand_handle))) == NULL)
248 250 return (NULL);
249 251 bzero(bhp, sizeof (struct brand_handle));
250 252
251 253 (void) strcpy(bhp->bh_name, name);
252 254
253 255 /*
254 256 * Open the configuration file
255 257 */
256 258 (void) snprintf(path, sizeof (path), "%s/%s/%s", BRAND_DIR, name,
257 259 BRAND_CONFIG);
258 260 if ((bhp->bh_config = open_xml_file(path)) == NULL) {
259 261 brand_close((brand_handle_t)bhp);
260 262 return (NULL);
261 263 }
262 264
263 265 /*
264 266 * Verify that the name of the brand matches the directory in which it
265 267 * is installed.
266 268 */
267 269 if ((node = xmlDocGetRootElement(bhp->bh_config)) == NULL) {
268 270 brand_close((brand_handle_t)bhp);
269 271 return (NULL);
270 272 }
271 273
272 274 if (xmlStrcmp(node->name, DTD_ELEM_BRAND) != 0) {
273 275 brand_close((brand_handle_t)bhp);
274 276 return (NULL);
275 277 }
276 278
277 279 if ((property = xmlGetProp(node, DTD_ATTR_NAME)) == NULL) {
278 280 brand_close((brand_handle_t)bhp);
279 281 return (NULL);
280 282 }
281 283
282 284 if (strcmp((char *)property, name) != 0) {
283 285 xmlFree(property);
284 286 brand_close((brand_handle_t)bhp);
285 287 return (NULL);
286 288 }
287 289 xmlFree(property);
288 290
289 291 /*
290 292 * Open handle to platform configuration file.
291 293 */
292 294 (void) snprintf(path, sizeof (path), "%s/%s/%s", BRAND_DIR, name,
293 295 BRAND_PLATFORM);
294 296 if ((bhp->bh_platform = open_xml_file(path)) == NULL) {
295 297 brand_close((brand_handle_t)bhp);
296 298 return (NULL);
297 299 }
298 300
299 301 return ((brand_handle_t)bhp);
300 302 }
301 303
302 304 /*
303 305 * Closes the given brand handle
304 306 */
305 307 void
306 308 brand_close(brand_handle_t bh)
307 309 {
308 310 struct brand_handle *bhp = (struct brand_handle *)bh;
309 311 if (bhp->bh_platform != NULL)
310 312 xmlFreeDoc(bhp->bh_platform);
311 313 if (bhp->bh_config != NULL)
312 314 xmlFreeDoc(bhp->bh_config);
313 315 free(bhp);
314 316 }
315 317
316 318 static int
317 319 i_substitute_tokens(const char *sbuf, char *dbuf, int dbuf_size,
318 320 const char *zonename, const char *zonepath, const char *username,
319 321 const char *curr_zone)
320 322 {
321 323 int dst, src;
322 324
323 325 /*
324 326 * Walk through the characters, substituting values as needed.
325 327 */
326 328 dbuf[0] = '\0';
327 329 dst = 0;
328 330 for (src = 0; src < strlen((char *)sbuf) && dst < dbuf_size; src++) {
329 331 if (sbuf[src] != '%') {
330 332 dbuf[dst++] = sbuf[src];
331 333 continue;
332 334 }
333 335
334 336 switch (sbuf[++src]) {
335 337 case '%':
336 338 dst += strlcpy(dbuf + dst, "%", dbuf_size - dst);
337 339 break;
338 340 case 'R':
339 341 if (zonepath == NULL)
340 342 break;
341 343 dst += strlcpy(dbuf + dst, zonepath, dbuf_size - dst);
342 344 break;
343 345 case 'u':
344 346 if (username == NULL)
345 347 break;
346 348 dst += strlcpy(dbuf + dst, username, dbuf_size - dst);
347 349 break;
348 350 case 'Z':
349 351 if (curr_zone == NULL)
350 352 break;
351 353 /* name of the zone we're running in */
352 354 dst += strlcpy(dbuf + dst, curr_zone, dbuf_size - dst);
353 355 break;
354 356 case 'z':
355 357 /* name of the zone we're operating on */
356 358 if (zonename == NULL)
357 359 break;
358 360 dst += strlcpy(dbuf + dst, zonename, dbuf_size - dst);
359 361 break;
360 362 }
361 363 }
362 364
363 365 if (dst >= dbuf_size)
364 366 return (-1);
365 367
366 368 dbuf[dst] = '\0';
367 369 return (0);
368 370 }
369 371
370 372 /*
371 373 * Retrieve the given tag from the brand.
372 374 * Perform the following substitutions as necessary:
373 375 *
374 376 * %% %
375 377 * %u Username
376 378 * %z Name of target zone
377 379 * %Z Name of current zone
378 380 * %R Zonepath of zone
379 381 *
380 382 * Returns 0 on success, -1 on failure.
381 383 */
382 384 static int
383 385 brand_get_value(struct brand_handle *bhp, const char *zonename,
384 386 const char *zonepath, const char *username, const char *curr_zone,
385 387 char *buf, size_t len, const xmlChar *tagname,
386 388 boolean_t substitute, boolean_t optional)
387 389 {
388 390 xmlNodePtr node;
389 391 xmlChar *content;
390 392 int err = 0;
391 393
392 394 /*
393 395 * Retrieve the specified value from the XML doc
394 396 */
395 397 if ((node = xmlDocGetRootElement(bhp->bh_config)) == NULL)
396 398 return (-1);
397 399
398 400 if (xmlStrcmp(node->name, DTD_ELEM_BRAND) != 0)
399 401 return (-1);
400 402
401 403 for (node = node->xmlChildrenNode; node != NULL;
402 404 node = node->next) {
403 405 if (xmlStrcmp(node->name, tagname) == 0)
404 406 break;
405 407 }
406 408
407 409 if (node == NULL) {
408 410 if (optional) {
409 411 buf[0] = '\0';
410 412 return (0);
411 413 } else {
412 414 return (-1);
413 415 }
414 416 }
415 417
416 418 if ((content = xmlNodeGetContent(node)) == NULL)
417 419 return (-1);
418 420
419 421 if (strlen((char *)content) == 0) {
420 422 /*
421 423 * If the entry in the config file is empty, check to see
422 424 * whether this is an optional field. If so, we return the
423 425 * empty buffer. If not, we return an error.
424 426 */
425 427 if (optional) {
426 428 buf[0] = '\0';
427 429 } else {
428 430 err = -1;
429 431 }
430 432 } else {
431 433 /* Substitute token values as needed. */
432 434 if (substitute) {
433 435 if (i_substitute_tokens((char *)content, buf, len,
434 436 zonename, zonepath, username, curr_zone) != 0)
435 437 err = -1;
436 438 } else {
437 439 if (strlcpy(buf, (char *)content, len) >= len)
438 440 err = -1;
439 441 }
440 442 }
441 443
442 444 xmlFree(content);
443 445
444 446 return (err);
445 447 }
446 448
447 449 int
448 450 brand_get_attach(brand_handle_t bh, const char *zonename,
449 451 const char *zonepath, char *buf, size_t len)
450 452 {
451 453 struct brand_handle *bhp = (struct brand_handle *)bh;
452 454 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
453 455 buf, len, DTD_ELEM_ATTACH, B_TRUE, B_TRUE));
454 456 }
455 457
456 458 int
457 459 brand_get_boot(brand_handle_t bh, const char *zonename,
458 460 const char *zonepath, char *buf, size_t len)
459 461 {
460 462 struct brand_handle *bhp = (struct brand_handle *)bh;
461 463 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
462 464 buf, len, DTD_ELEM_BOOT, B_TRUE, B_TRUE));
463 465 }
464 466
465 467 int
466 468 brand_get_brandname(brand_handle_t bh, char *buf, size_t len)
467 469 {
468 470 struct brand_handle *bhp = (struct brand_handle *)bh;
469 471 if (len <= strlen(bhp->bh_name))
470 472 return (-1);
471 473
472 474 (void) strcpy(buf, bhp->bh_name);
473 475
474 476 return (0);
475 477 }
476 478
477 479 int
478 480 brand_get_clone(brand_handle_t bh, const char *zonename,
479 481 const char *zonepath, char *buf, size_t len)
480 482 {
481 483 struct brand_handle *bhp = (struct brand_handle *)bh;
482 484 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
483 485 buf, len, DTD_ELEM_CLONE, B_TRUE, B_TRUE));
484 486 }
485 487
486 488 int
487 489 brand_get_detach(brand_handle_t bh, const char *zonename,
488 490 const char *zonepath, char *buf, size_t len)
489 491 {
490 492 struct brand_handle *bhp = (struct brand_handle *)bh;
491 493 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
492 494 buf, len, DTD_ELEM_DETACH, B_TRUE, B_TRUE));
493 495 }
↓ open down ↓ |
410 lines elided |
↑ open up ↑ |
494 496
495 497 int
496 498 brand_get_halt(brand_handle_t bh, const char *zonename,
497 499 const char *zonepath, char *buf, size_t len)
498 500 {
499 501 struct brand_handle *bhp = (struct brand_handle *)bh;
500 502 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
501 503 buf, len, DTD_ELEM_HALT, B_TRUE, B_TRUE));
502 504 }
503 505
506 +int
507 +brand_get_shutdown(brand_handle_t bh, const char *zonename,
508 + const char *zonepath, char *buf, size_t len)
509 +{
510 + struct brand_handle *bhp = (struct brand_handle *)bh;
511 + return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
512 + buf, len, DTD_ELEM_SHUTDOWN, B_TRUE, B_TRUE));
513 +}
514 +
504 515 int
505 516 brand_get_initname(brand_handle_t bh, char *buf, size_t len)
506 517 {
507 518 struct brand_handle *bhp = (struct brand_handle *)bh;
508 519 return (brand_get_value(bhp, NULL, NULL, NULL, NULL,
509 520 buf, len, DTD_ELEM_INITNAME, B_FALSE, B_FALSE));
510 521 }
511 522
512 523 int
513 524 brand_get_login_cmd(brand_handle_t bh, const char *username,
514 525 char *buf, size_t len)
515 526 {
516 527 struct brand_handle *bhp = (struct brand_handle *)bh;
517 528 const char *curr_zone = get_curr_zone();
518 529 return (brand_get_value(bhp, NULL, NULL, username, curr_zone,
519 530 buf, len, DTD_ELEM_LOGIN_CMD, B_TRUE, B_FALSE));
520 531 }
521 532
522 533 int
523 534 brand_get_forcedlogin_cmd(brand_handle_t bh, const char *username,
524 535 char *buf, size_t len)
525 536 {
526 537 struct brand_handle *bhp = (struct brand_handle *)bh;
527 538 const char *curr_zone = get_curr_zone();
528 539 return (brand_get_value(bhp, NULL, NULL, username, curr_zone,
529 540 buf, len, DTD_ELEM_FORCELOGIN_CMD, B_TRUE, B_FALSE));
530 541 }
531 542
532 543 int
533 544 brand_get_user_cmd(brand_handle_t bh, const char *username,
534 545 char *buf, size_t len)
535 546 {
536 547 struct brand_handle *bhp = (struct brand_handle *)bh;
537 548
538 549 return (brand_get_value(bhp, NULL, NULL, username, NULL,
539 550 buf, len, DTD_ELEM_USER_CMD, B_TRUE, B_FALSE));
540 551 }
541 552
542 553 int
543 554 brand_get_install(brand_handle_t bh, const char *zonename,
544 555 const char *zonepath, char *buf, size_t len)
545 556 {
546 557 struct brand_handle *bhp = (struct brand_handle *)bh;
547 558 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
548 559 buf, len, DTD_ELEM_INSTALL, B_TRUE, B_FALSE));
549 560 }
550 561
551 562 int
552 563 brand_get_installopts(brand_handle_t bh, char *buf, size_t len)
553 564 {
554 565 struct brand_handle *bhp = (struct brand_handle *)bh;
555 566 return (brand_get_value(bhp, NULL, NULL, NULL, NULL,
556 567 buf, len, DTD_ELEM_INSTALLOPTS, B_FALSE, B_TRUE));
557 568 }
558 569
559 570 int
560 571 brand_get_modname(brand_handle_t bh, char *buf, size_t len)
561 572 {
562 573 struct brand_handle *bhp = (struct brand_handle *)bh;
563 574 return (brand_get_value(bhp, NULL, NULL, NULL, NULL,
564 575 buf, len, DTD_ELEM_MODNAME, B_FALSE, B_TRUE));
565 576 }
566 577
567 578 int
568 579 brand_get_postattach(brand_handle_t bh, const char *zonename,
569 580 const char *zonepath, char *buf, size_t len)
570 581 {
571 582 struct brand_handle *bhp = (struct brand_handle *)bh;
572 583 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
573 584 buf, len, DTD_ELEM_POSTATTACH, B_TRUE, B_TRUE));
574 585 }
575 586
576 587 int
577 588 brand_get_postclone(brand_handle_t bh, const char *zonename,
578 589 const char *zonepath, char *buf, size_t len)
579 590 {
580 591 struct brand_handle *bhp = (struct brand_handle *)bh;
581 592 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
582 593 buf, len, DTD_ELEM_POSTCLONE, B_TRUE, B_TRUE));
583 594 }
584 595
585 596 int
586 597 brand_get_postinstall(brand_handle_t bh, const char *zonename,
587 598 const char *zonepath, char *buf, size_t len)
588 599 {
589 600 struct brand_handle *bhp = (struct brand_handle *)bh;
590 601 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
591 602 buf, len, DTD_ELEM_POSTINSTALL, B_TRUE, B_TRUE));
592 603 }
593 604
594 605 int
595 606 brand_get_postsnap(brand_handle_t bh, const char *zonename,
596 607 const char *zonepath, char *buf, size_t len)
597 608 {
598 609 struct brand_handle *bhp = (struct brand_handle *)bh;
599 610 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
600 611 buf, len, DTD_ELEM_POSTSNAP, B_TRUE, B_TRUE));
601 612 }
602 613
603 614 int
604 615 brand_get_poststatechange(brand_handle_t bh, const char *zonename,
605 616 const char *zonepath, char *buf, size_t len)
606 617 {
607 618 struct brand_handle *bhp = (struct brand_handle *)bh;
608 619 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
609 620 buf, len, DTD_ELEM_POSTSTATECHG, B_TRUE, B_TRUE));
610 621 }
611 622
612 623 int
613 624 brand_get_predetach(brand_handle_t bh, const char *zonename,
614 625 const char *zonepath, char *buf, size_t len)
615 626 {
616 627 struct brand_handle *bhp = (struct brand_handle *)bh;
617 628 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
618 629 buf, len, DTD_ELEM_PREDETACH, B_TRUE, B_TRUE));
619 630 }
620 631
621 632 int
622 633 brand_get_presnap(brand_handle_t bh, const char *zonename,
623 634 const char *zonepath, char *buf, size_t len)
624 635 {
625 636 struct brand_handle *bhp = (struct brand_handle *)bh;
626 637 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
627 638 buf, len, DTD_ELEM_PRESNAP, B_TRUE, B_TRUE));
628 639 }
629 640
630 641 int
631 642 brand_get_prestatechange(brand_handle_t bh, const char *zonename,
632 643 const char *zonepath, char *buf, size_t len)
633 644 {
634 645 struct brand_handle *bhp = (struct brand_handle *)bh;
635 646 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
636 647 buf, len, DTD_ELEM_PRESTATECHG, B_TRUE, B_TRUE));
637 648 }
638 649
639 650 int
640 651 brand_get_preuninstall(brand_handle_t bh, const char *zonename,
641 652 const char *zonepath, char *buf, size_t len)
642 653 {
643 654 struct brand_handle *bhp = (struct brand_handle *)bh;
644 655 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
645 656 buf, len, DTD_ELEM_PREUNINSTALL, B_TRUE, B_TRUE));
646 657 }
647 658
648 659 int
649 660 brand_get_query(brand_handle_t bh, const char *zonename,
650 661 const char *zonepath, char *buf, size_t len)
651 662 {
652 663 struct brand_handle *bhp = (struct brand_handle *)bh;
653 664 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
654 665 buf, len, DTD_ELEM_QUERY, B_TRUE, B_TRUE));
655 666 }
656 667
657 668 int
658 669 brand_get_uninstall(brand_handle_t bh, const char *zonename,
659 670 const char *zonepath, char *buf, size_t len)
660 671 {
661 672 struct brand_handle *bhp = (struct brand_handle *)bh;
662 673 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
663 674 buf, len, DTD_ELEM_UNINSTALL, B_TRUE, B_TRUE));
664 675 }
665 676
666 677 int
667 678 brand_get_validatesnap(brand_handle_t bh, const char *zonename,
668 679 const char *zonepath, char *buf, size_t len)
669 680 {
670 681 struct brand_handle *bhp = (struct brand_handle *)bh;
671 682 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
672 683 buf, len, DTD_ELEM_VALIDSNAP, B_TRUE, B_TRUE));
673 684 }
674 685
675 686 int
676 687 brand_get_verify_cfg(brand_handle_t bh, char *buf, size_t len)
677 688 {
678 689 struct brand_handle *bhp = (struct brand_handle *)bh;
679 690 return (brand_get_value(bhp, NULL, NULL, NULL, NULL,
680 691 buf, len, DTD_ELEM_VERIFY_CFG, B_FALSE, B_TRUE));
681 692 }
682 693
683 694 int
684 695 brand_get_verify_adm(brand_handle_t bh, const char *zonename,
685 696 const char *zonepath, char *buf, size_t len)
686 697 {
687 698 struct brand_handle *bhp = (struct brand_handle *)bh;
688 699 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
689 700 buf, len, DTD_ELEM_VERIFY_ADM, B_TRUE, B_TRUE));
690 701 }
691 702
692 703 int
693 704 brand_get_sysboot(brand_handle_t bh, const char *zonename,
694 705 const char *zonepath, char *buf, size_t len)
695 706 {
696 707 struct brand_handle *bhp = (struct brand_handle *)bh;
697 708 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
698 709 buf, len, DTD_ELEM_SYSBOOT, B_TRUE, B_TRUE));
699 710 }
700 711
701 712 boolean_t
702 713 brand_allow_exclusive_ip(brand_handle_t bh)
703 714 {
704 715 struct brand_handle *bhp = (struct brand_handle *)bh;
705 716 xmlNodePtr node;
706 717 xmlChar *allow_excl;
707 718 boolean_t ret;
708 719
709 720 assert(bhp != NULL);
710 721
711 722 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL)
712 723 return (B_FALSE);
713 724
714 725 allow_excl = xmlGetProp(node, DTD_ATTR_ALLOWEXCL);
715 726 if (allow_excl == NULL)
716 727 return (B_FALSE);
717 728
718 729 /* Note: only return B_TRUE if it's "true" */
719 730 if (strcmp((char *)allow_excl, DTD_ENTITY_TRUE) == 0)
720 731 ret = B_TRUE;
721 732 else
722 733 ret = B_FALSE;
723 734
724 735 xmlFree(allow_excl);
725 736
726 737 return (ret);
727 738 }
728 739
729 740 /*
730 741 * Iterate over brand privileges
731 742 *
732 743 * Walks the brand config, searching for <privilege> elements, calling the
733 744 * specified callback for each. Returns 0 on success, or -1 on failure.
734 745 */
735 746 int
736 747 brand_config_iter_privilege(brand_handle_t bh,
737 748 int (*func)(void *, priv_iter_t *), void *data)
738 749 {
739 750 struct brand_handle *bhp = (struct brand_handle *)bh;
740 751 xmlNodePtr node;
741 752 xmlChar *name, *set, *iptype;
742 753 priv_iter_t priv_iter;
743 754 int ret;
744 755
745 756 if ((node = xmlDocGetRootElement(bhp->bh_config)) == NULL)
746 757 return (-1);
747 758
748 759 for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
749 760
750 761 if (xmlStrcmp(node->name, DTD_ELEM_PRIVILEGE) != 0)
751 762 continue;
752 763
753 764 name = xmlGetProp(node, DTD_ATTR_NAME);
754 765 set = xmlGetProp(node, DTD_ATTR_SET);
755 766 iptype = xmlGetProp(node, DTD_ATTR_IPTYPE);
756 767
757 768 if (name == NULL || set == NULL || iptype == NULL) {
758 769 if (name != NULL)
759 770 xmlFree(name);
760 771 if (set != NULL)
761 772 xmlFree(set);
762 773 if (iptype != NULL)
763 774 xmlFree(iptype);
764 775 return (-1);
765 776 }
766 777
767 778 priv_iter.pi_name = (char *)name;
768 779 priv_iter.pi_set = (char *)set;
769 780 priv_iter.pi_iptype = (char *)iptype;
770 781
771 782 ret = func(data, &priv_iter);
772 783
773 784 xmlFree(name);
774 785 xmlFree(set);
775 786 xmlFree(iptype);
776 787
777 788 if (ret != 0)
778 789 return (-1);
779 790 }
780 791
781 792 return (0);
782 793 }
783 794
784 795 static int
785 796 i_brand_platform_iter_mounts(struct brand_handle *bhp, const char *zonepath,
786 797 int (*func)(void *, const char *, const char *, const char *,
787 798 const char *), void *data, const xmlChar *mount_type)
788 799 {
789 800 xmlNodePtr node;
790 801 xmlChar *special, *dir, *type, *opt;
791 802 char special_exp[MAXPATHLEN];
792 803 char opt_exp[MAXPATHLEN];
793 804 int ret;
794 805
795 806 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL)
796 807 return (-1);
797 808
798 809 for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
799 810
800 811 if (xmlStrcmp(node->name, mount_type) != 0)
801 812 continue;
802 813
803 814 special = xmlGetProp(node, DTD_ATTR_SPECIAL);
804 815 dir = xmlGetProp(node, DTD_ATTR_DIRECTORY);
805 816 type = xmlGetProp(node, DTD_ATTR_TYPE);
806 817 opt = xmlGetProp(node, DTD_ATTR_OPT);
807 818 if ((special == NULL) || (dir == NULL) || (type == NULL) ||
808 819 (opt == NULL)) {
809 820 ret = -1;
810 821 goto next;
811 822 }
812 823
813 824 /* Substitute token values as needed. */
814 825 if ((ret = i_substitute_tokens((char *)special,
815 826 special_exp, sizeof (special_exp),
816 827 NULL, zonepath, NULL, NULL)) != 0)
817 828 goto next;
818 829
819 830 /* opt might not be defined */
820 831 if (strlen((const char *)opt) == 0) {
821 832 xmlFree(opt);
822 833 opt = NULL;
823 834 } else {
824 835 if ((ret = i_substitute_tokens((char *)opt,
825 836 opt_exp, sizeof (opt_exp),
826 837 NULL, zonepath, NULL, NULL)) != 0)
827 838 goto next;
828 839 }
829 840
830 841 ret = func(data, (char *)special_exp, (char *)dir,
831 842 (char *)type, ((opt != NULL) ? opt_exp : NULL));
832 843
833 844 next:
834 845 if (special != NULL)
835 846 xmlFree(special);
836 847 if (dir != NULL)
837 848 xmlFree(dir);
838 849 if (type != NULL)
839 850 xmlFree(type);
840 851 if (opt != NULL)
841 852 xmlFree(opt);
842 853 if (ret != 0)
843 854 return (-1);
844 855 }
845 856 return (0);
846 857 }
847 858
848 859
849 860 /*
850 861 * Iterate over global platform filesystems
851 862 *
852 863 * Walks the platform, searching for <global_mount> elements, calling the
853 864 * specified callback for each. Returns 0 on success, or -1 on failure.
854 865 *
855 866 * Perform the following substitutions as necessary:
856 867 *
857 868 * %R Zonepath of zone
858 869 */
859 870 int
860 871 brand_platform_iter_gmounts(brand_handle_t bh, const char *zonepath,
861 872 int (*func)(void *, const char *, const char *, const char *,
862 873 const char *), void *data)
863 874 {
864 875 struct brand_handle *bhp = (struct brand_handle *)bh;
865 876 return (i_brand_platform_iter_mounts(bhp, zonepath, func, data,
866 877 DTD_ELEM_GLOBAL_MOUNT));
867 878 }
868 879
869 880 /*
870 881 * Iterate over non-global zone platform filesystems
871 882 *
872 883 * Walks the platform, searching for <mount> elements, calling the
873 884 * specified callback for each. Returns 0 on success, or -1 on failure.
874 885 */
875 886 int
876 887 brand_platform_iter_mounts(brand_handle_t bh, int (*func)(void *,
877 888 const char *, const char *, const char *, const char *), void *data)
878 889 {
879 890 struct brand_handle *bhp = (struct brand_handle *)bh;
880 891 return (i_brand_platform_iter_mounts(bhp, NULL, func, data,
881 892 DTD_ELEM_MOUNT));
882 893 }
883 894
884 895 /*
885 896 * Iterate over platform symlinks
886 897 *
887 898 * Walks the platform, searching for <symlink> elements, calling the
888 899 * specified callback for each. Returns 0 on success, or -1 on failure.
889 900 */
890 901 int
891 902 brand_platform_iter_link(brand_handle_t bh,
892 903 int (*func)(void *, const char *, const char *), void *data)
893 904 {
894 905 struct brand_handle *bhp = (struct brand_handle *)bh;
895 906 xmlNodePtr node;
896 907 xmlChar *source, *target;
897 908 int ret;
898 909
899 910 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL)
900 911 return (-1);
901 912
902 913 for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
903 914
904 915 if (xmlStrcmp(node->name, DTD_ELEM_SYMLINK) != 0)
905 916 continue;
906 917
907 918 source = xmlGetProp(node, DTD_ATTR_SOURCE);
908 919 target = xmlGetProp(node, DTD_ATTR_TARGET);
909 920
910 921 if (source == NULL || target == NULL) {
911 922 if (source != NULL)
912 923 xmlFree(source);
913 924 if (target != NULL)
914 925 xmlFree(target);
915 926 return (-1);
916 927 }
917 928
918 929 ret = func(data, (char *)source, (char *)target);
919 930
920 931 xmlFree(source);
921 932 xmlFree(target);
922 933
923 934 if (ret != 0)
924 935 return (-1);
925 936 }
926 937
927 938 return (0);
928 939 }
929 940
930 941 /*
931 942 * Iterate over platform devices
932 943 *
933 944 * Walks the platform, searching for <device> elements, calling the
934 945 * specified callback for each. Returns 0 on success, or -1 on failure.
935 946 */
936 947 int
937 948 brand_platform_iter_devices(brand_handle_t bh, const char *zonename,
938 949 int (*func)(void *, const char *, const char *), void *data,
939 950 const char *curr_iptype)
940 951 {
941 952 struct brand_handle *bhp = (struct brand_handle *)bh;
942 953 const char *curr_arch = get_curr_arch();
943 954 xmlNodePtr node;
944 955 xmlChar *match, *name, *arch, *iptype;
945 956 char match_exp[MAXPATHLEN];
946 957 boolean_t err = B_FALSE;
947 958 int ret = 0;
948 959
949 960
950 961 assert(bhp != NULL);
951 962 assert(zonename != NULL);
952 963 assert(func != NULL);
953 964 assert(curr_iptype != NULL);
954 965
955 966 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL)
956 967 return (-1);
957 968
958 969 for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
959 970
960 971 if (xmlStrcmp(node->name, DTD_ELEM_DEVICE) != 0)
961 972 continue;
962 973
963 974 match = xmlGetProp(node, DTD_ATTR_MATCH);
964 975 name = xmlGetProp(node, DTD_ATTR_NAME);
965 976 arch = xmlGetProp(node, DTD_ATTR_ARCH);
966 977 iptype = xmlGetProp(node, DTD_ATTR_IPTYPE);
967 978 if ((match == NULL) || (name == NULL) || (arch == NULL) ||
968 979 (iptype == NULL)) {
969 980 err = B_TRUE;
970 981 goto next;
971 982 }
972 983
973 984 /* check if the arch matches */
974 985 if ((strcmp((char *)arch, "all") != 0) &&
975 986 (strcmp((char *)arch, curr_arch) != 0))
976 987 goto next;
977 988
978 989 /* check if the iptype matches */
979 990 if ((strcmp((char *)iptype, "all") != 0) &&
980 991 (strcmp((char *)iptype, curr_iptype) != 0))
981 992 goto next;
982 993
983 994 /* Substitute token values as needed. */
984 995 if ((ret = i_substitute_tokens((char *)match,
985 996 match_exp, sizeof (match_exp),
986 997 zonename, NULL, NULL, NULL)) != 0) {
987 998 err = B_TRUE;
988 999 goto next;
989 1000 }
990 1001
991 1002 /* name might not be defined */
992 1003 if (strlen((const char *)name) == 0) {
993 1004 xmlFree(name);
994 1005 name = NULL;
995 1006 }
996 1007
997 1008 /* invoke the callback */
998 1009 ret = func(data, (const char *)match_exp, (const char *)name);
999 1010
1000 1011 next:
1001 1012 if (match != NULL)
1002 1013 xmlFree(match);
1003 1014 if (name != NULL)
1004 1015 xmlFree(name);
1005 1016 if (arch != NULL)
1006 1017 xmlFree(arch);
1007 1018 if (iptype != NULL)
1008 1019 xmlFree(iptype);
1009 1020 if (err)
1010 1021 return (-1);
1011 1022 if (ret != 0)
1012 1023 return (-1);
1013 1024 }
1014 1025
1015 1026 return (0);
1016 1027 }
↓ open down ↓ |
503 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX