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