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