4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2015, Joyent, Inc.
25 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
37 #include <sys/brand.h>
38 #include <sys/fcntl.h>
39 #include <sys/param.h>
41 #include <sys/systeminfo.h>
42 #include <sys/types.h>
46 #include <libbrand_impl.h>
49 #define DTD_ELEM_ATTACH ((const xmlChar *) "attach")
50 #define DTD_ELEM_BOOT ((const xmlChar *) "boot")
51 #define DTD_ELEM_BRAND ((const xmlChar *) "brand")
52 #define DTD_ELEM_CLONE ((const xmlChar *) "clone")
53 #define DTD_ELEM_COMMENT ((const xmlChar *) "comment")
54 #define DTD_ELEM_DETACH ((const xmlChar *) "detach")
55 #define DTD_ELEM_DEVICE ((const xmlChar *) "device")
56 #define DTD_ELEM_GLOBAL_MOUNT ((const xmlChar *) "global_mount")
57 #define DTD_ELEM_HALT ((const xmlChar *) "halt")
58 #define DTD_ELEM_INITNAME ((const xmlChar *) "initname")
59 #define DTD_ELEM_INSTALL ((const xmlChar *) "install")
60 #define DTD_ELEM_INSTALLOPTS ((const xmlChar *) "installopts")
61 #define DTD_ELEM_LOGIN_CMD ((const xmlChar *) "login_cmd")
62 #define DTD_ELEM_FORCELOGIN_CMD ((const xmlChar *) "forcedlogin_cmd")
63 #define DTD_ELEM_MODNAME ((const xmlChar *) "modname")
64 #define DTD_ELEM_MOUNT ((const xmlChar *) "mount")
65 #define DTD_ELEM_RESTARTINIT ((const xmlChar *) "restartinit")
66 #define DTD_ELEM_POSTATTACH ((const xmlChar *) "postattach")
67 #define DTD_ELEM_POSTCLONE ((const xmlChar *) "postclone")
68 #define DTD_ELEM_POSTINSTALL ((const xmlChar *) "postinstall")
69 #define DTD_ELEM_POSTSNAP ((const xmlChar *) "postsnap")
70 #define DTD_ELEM_POSTSTATECHG ((const xmlChar *) "poststatechange")
71 #define DTD_ELEM_PREDETACH ((const xmlChar *) "predetach")
72 #define DTD_ELEM_PRESNAP ((const xmlChar *) "presnap")
73 #define DTD_ELEM_PRESTATECHG ((const xmlChar *) "prestatechange")
74 #define DTD_ELEM_PREUNINSTALL ((const xmlChar *) "preuninstall")
75 #define DTD_ELEM_PRIVILEGE ((const xmlChar *) "privilege")
76 #define DTD_ELEM_QUERY ((const xmlChar *) "query")
77 #define DTD_ELEM_SHUTDOWN ((const xmlChar *) "shutdown")
78 #define DTD_ELEM_SYMLINK ((const xmlChar *) "symlink")
79 #define DTD_ELEM_SYSBOOT ((const xmlChar *) "sysboot")
80 #define DTD_ELEM_UNINSTALL ((const xmlChar *) "uninstall")
81 #define DTD_ELEM_USER_CMD ((const xmlChar *) "user_cmd")
82 #define DTD_ELEM_VALIDSNAP ((const xmlChar *) "validatesnap")
83 #define DTD_ELEM_VERIFY_CFG ((const xmlChar *) "verify_cfg")
84 #define DTD_ELEM_VERIFY_ADM ((const xmlChar *) "verify_adm")
86 #define DTD_ATTR_ALLOWEXCL ((const xmlChar *) "allow-exclusive-ip")
87 #define DTD_ATTR_ARCH ((const xmlChar *) "arch")
88 #define DTD_ATTR_DIRECTORY ((const xmlChar *) "directory")
89 #define DTD_ATTR_IPTYPE ((const xmlChar *) "ip-type")
90 #define DTD_ATTR_MATCH ((const xmlChar *) "match")
91 #define DTD_ATTR_MODE ((const xmlChar *) "mode")
92 #define DTD_ATTR_NAME ((const xmlChar *) "name")
93 #define DTD_ATTR_OPT ((const xmlChar *) "opt")
94 #define DTD_ATTR_PATH ((const xmlChar *) "path")
95 #define DTD_ATTR_SET ((const xmlChar *) "set")
96 #define DTD_ATTR_SOURCE ((const xmlChar *) "source")
97 #define DTD_ATTR_SPECIAL ((const xmlChar *) "special")
98 #define DTD_ATTR_TARGET ((const xmlChar *) "target")
99 #define DTD_ATTR_TYPE ((const xmlChar *) "type")
101 #define DTD_ENTITY_TRUE "true"
103 static volatile boolean_t libbrand_initialized
= B_FALSE
;
104 static char i_curr_arch
[MAXNAMELEN
];
105 static char i_curr_zone
[ZONENAME_MAX
];
109 brand_error_func(void *ctx
, const char *msg
, ...)
112 * Ignore error messages from libxml
117 libbrand_initialize()
119 static mutex_t initialize_lock
= DEFAULTMUTEX
;
121 (void) mutex_lock(&initialize_lock
);
123 if (libbrand_initialized
) {
124 (void) mutex_unlock(&initialize_lock
);
128 if (sysinfo(SI_ARCHITECTURE
, i_curr_arch
, sizeof (i_curr_arch
)) < 0) {
129 (void) mutex_unlock(&initialize_lock
);
133 if (getzonenamebyid(getzoneid(), i_curr_zone
,
134 sizeof (i_curr_zone
)) < 0) {
135 (void) mutex_unlock(&initialize_lock
);
140 * Note that here we're initializing per-process libxml2
141 * state. By doing so we're implicitly assuming that
142 * no other code in this process is also trying to
143 * use libxml2. But in most case we know this not to
144 * be true since we're almost always used in conjunction
145 * with libzonecfg, which also uses libxml2. Lucky for
146 * us, libzonecfg initializes libxml2 to essentially
147 * the same defaults as we're using below.
149 (void) xmlLineNumbersDefault(1);
150 xmlLoadExtDtdDefaultValue
|= XML_DETECT_IDS
;
151 xmlDoValidityCheckingDefaultValue
= 1;
152 (void) xmlKeepBlanksDefault(0);
153 xmlGetWarningsDefaultValue
= 0;
154 xmlSetGenericErrorFunc(NULL
, brand_error_func
);
156 libbrand_initialized
= B_TRUE
;
157 (void) mutex_unlock(&initialize_lock
);
164 if (!libbrand_initialize())
167 return (i_curr_arch
);
173 if (!libbrand_initialize())
176 return (i_curr_zone
);
180 * Internal function to open an XML file
182 * Returns the XML doc pointer, or NULL on failure. It will validate the
183 * document, as well as removing any comments from the document structure.
186 open_xml_file(const char *file
)
192 if (!libbrand_initialize())
198 if ((doc
= xmlParseFile(file
)) == NULL
)
204 if ((cvp
= xmlNewValidCtxt()) == NULL
) {
208 cvp
->error
= brand_error_func
;
209 cvp
->warning
= brand_error_func
;
210 valid
= xmlValidateDocument(cvp
, doc
);
211 xmlFreeValidCtxt(cvp
);
220 * Open a handle to the named brand.
222 * Returns a handle to the named brand, which is used for all subsequent brand
223 * interaction, or NULL if unable to open or initialize the brand.
226 brand_open(const char *name
)
228 struct brand_handle
*bhp
;
229 char path
[MAXPATHLEN
];
235 * Make sure brand name isn't too long
237 if (strlen(name
) >= MAXNAMELEN
)
241 * Check that the brand exists
243 (void) snprintf(path
, sizeof (path
), "%s/%s", BRAND_DIR
, name
);
245 if (stat(path
, &statbuf
) != 0)
249 * Allocate brand handle
251 if ((bhp
= malloc(sizeof (struct brand_handle
))) == NULL
)
253 bzero(bhp
, sizeof (struct brand_handle
));
255 (void) strcpy(bhp
->bh_name
, name
);
258 * Open the configuration file
260 (void) snprintf(path
, sizeof (path
), "%s/%s/%s", BRAND_DIR
, name
,
262 if ((bhp
->bh_config
= open_xml_file(path
)) == NULL
) {
263 brand_close((brand_handle_t
)bhp
);
268 * Verify that the name of the brand matches the directory in which it
271 if ((node
= xmlDocGetRootElement(bhp
->bh_config
)) == NULL
) {
272 brand_close((brand_handle_t
)bhp
);
276 if (xmlStrcmp(node
->name
, DTD_ELEM_BRAND
) != 0) {
277 brand_close((brand_handle_t
)bhp
);
281 if ((property
= xmlGetProp(node
, DTD_ATTR_NAME
)) == NULL
) {
282 brand_close((brand_handle_t
)bhp
);
286 if (strcmp((char *)property
, name
) != 0) {
288 brand_close((brand_handle_t
)bhp
);
294 * Open handle to platform configuration file.
296 (void) snprintf(path
, sizeof (path
), "%s/%s/%s", BRAND_DIR
, name
,
298 if ((bhp
->bh_platform
= open_xml_file(path
)) == NULL
) {
299 brand_close((brand_handle_t
)bhp
);
303 return ((brand_handle_t
)bhp
);
307 * Closes the given brand handle
310 brand_close(brand_handle_t bh
)
312 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
313 if (bhp
->bh_platform
!= NULL
)
314 xmlFreeDoc(bhp
->bh_platform
);
315 if (bhp
->bh_config
!= NULL
)
316 xmlFreeDoc(bhp
->bh_config
);
321 i_substitute_tokens(const char *sbuf
, char *dbuf
, int dbuf_size
,
322 const char *zonename
, const char *zonepath
, const char *username
,
323 const char *curr_zone
)
328 * Walk through the characters, substituting values as needed.
332 for (src
= 0; src
< strlen((char *)sbuf
) && dst
< dbuf_size
; src
++) {
333 if (sbuf
[src
] != '%') {
334 dbuf
[dst
++] = sbuf
[src
];
338 switch (sbuf
[++src
]) {
340 dst
+= strlcpy(dbuf
+ dst
, "%", dbuf_size
- dst
);
343 if (zonepath
== NULL
)
345 dst
+= strlcpy(dbuf
+ dst
, zonepath
, dbuf_size
- dst
);
348 if (username
== NULL
)
350 dst
+= strlcpy(dbuf
+ dst
, username
, dbuf_size
- dst
);
353 if (curr_zone
== NULL
)
355 /* name of the zone we're running in */
356 dst
+= strlcpy(dbuf
+ dst
, curr_zone
, dbuf_size
- dst
);
359 /* name of the zone we're operating on */
360 if (zonename
== NULL
)
362 dst
+= strlcpy(dbuf
+ dst
, zonename
, dbuf_size
- dst
);
367 if (dst
>= dbuf_size
)
375 * Retrieve the given tag from the brand.
376 * Perform the following substitutions as necessary:
380 * %z Name of target zone
381 * %Z Name of current zone
382 * %R Zonepath of zone
384 * Returns 0 on success, -1 on failure.
387 brand_get_value(struct brand_handle
*bhp
, const char *zonename
,
388 const char *zonepath
, const char *username
, const char *curr_zone
,
389 char *buf
, size_t len
, const xmlChar
*tagname
,
390 boolean_t substitute
, boolean_t optional
)
397 * Retrieve the specified value from the XML doc
399 if ((node
= xmlDocGetRootElement(bhp
->bh_config
)) == NULL
)
402 if (xmlStrcmp(node
->name
, DTD_ELEM_BRAND
) != 0)
405 for (node
= node
->xmlChildrenNode
; node
!= NULL
;
407 if (xmlStrcmp(node
->name
, tagname
) == 0)
420 if ((content
= xmlNodeGetContent(node
)) == NULL
)
423 if (strlen((char *)content
) == 0) {
425 * If the entry in the config file is empty, check to see
426 * whether this is an optional field. If so, we return the
427 * empty buffer. If not, we return an error.
435 /* Substitute token values as needed. */
437 if (i_substitute_tokens((char *)content
, buf
, len
,
438 zonename
, zonepath
, username
, curr_zone
) != 0)
441 if (strlcpy(buf
, (char *)content
, len
) >= len
)
452 brand_get_attach(brand_handle_t bh
, const char *zonename
,
453 const char *zonepath
, char *buf
, size_t len
)
455 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
456 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
457 buf
, len
, DTD_ELEM_ATTACH
, B_TRUE
, B_TRUE
));
461 brand_get_boot(brand_handle_t bh
, const char *zonename
,
462 const char *zonepath
, char *buf
, size_t len
)
464 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
465 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
466 buf
, len
, DTD_ELEM_BOOT
, B_TRUE
, B_TRUE
));
470 brand_get_brandname(brand_handle_t bh
, char *buf
, size_t len
)
472 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
473 if (len
<= strlen(bhp
->bh_name
))
476 (void) strcpy(buf
, bhp
->bh_name
);
482 brand_get_clone(brand_handle_t bh
, const char *zonename
,
483 const char *zonepath
, char *buf
, size_t len
)
485 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
486 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
487 buf
, len
, DTD_ELEM_CLONE
, B_TRUE
, B_TRUE
));
491 brand_get_detach(brand_handle_t bh
, const char *zonename
,
492 const char *zonepath
, char *buf
, size_t len
)
494 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
495 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
496 buf
, len
, DTD_ELEM_DETACH
, B_TRUE
, B_TRUE
));
500 brand_get_halt(brand_handle_t bh
, const char *zonename
,
501 const char *zonepath
, char *buf
, size_t len
)
503 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
504 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
505 buf
, len
, DTD_ELEM_HALT
, B_TRUE
, B_TRUE
));
509 brand_get_shutdown(brand_handle_t bh
, const char *zonename
,
510 const char *zonepath
, char *buf
, size_t len
)
512 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
513 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
514 buf
, len
, DTD_ELEM_SHUTDOWN
, B_TRUE
, B_TRUE
));
518 brand_get_initname(brand_handle_t bh
, char *buf
, size_t len
)
520 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
521 return (brand_get_value(bhp
, NULL
, NULL
, NULL
, NULL
,
522 buf
, len
, DTD_ELEM_INITNAME
, B_FALSE
, B_FALSE
));
526 brand_restartinit(brand_handle_t bh
)
528 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
531 if (brand_get_value(bhp
, NULL
, NULL
, NULL
, NULL
,
532 val
, sizeof (val
), DTD_ELEM_RESTARTINIT
, B_FALSE
, B_FALSE
) != 0)
535 if (strcmp(val
, "false") == 0)
541 brand_get_login_cmd(brand_handle_t bh
, const char *username
,
542 char *buf
, size_t len
)
544 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
545 const char *curr_zone
= get_curr_zone();
546 return (brand_get_value(bhp
, NULL
, NULL
, username
, curr_zone
,
547 buf
, len
, DTD_ELEM_LOGIN_CMD
, B_TRUE
, B_FALSE
));
551 brand_get_forcedlogin_cmd(brand_handle_t bh
, const char *username
,
552 char *buf
, size_t len
)
554 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
555 const char *curr_zone
= get_curr_zone();
556 return (brand_get_value(bhp
, NULL
, NULL
, username
, curr_zone
,
557 buf
, len
, DTD_ELEM_FORCELOGIN_CMD
, B_TRUE
, B_FALSE
));
561 brand_get_user_cmd(brand_handle_t bh
, const char *username
,
562 char *buf
, size_t len
)
564 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
566 return (brand_get_value(bhp
, NULL
, NULL
, username
, NULL
,
567 buf
, len
, DTD_ELEM_USER_CMD
, B_TRUE
, B_FALSE
));
571 brand_get_install(brand_handle_t bh
, const char *zonename
,
572 const char *zonepath
, char *buf
, size_t len
)
574 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
575 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
576 buf
, len
, DTD_ELEM_INSTALL
, B_TRUE
, B_FALSE
));
580 brand_get_installopts(brand_handle_t bh
, char *buf
, size_t len
)
582 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
583 return (brand_get_value(bhp
, NULL
, NULL
, NULL
, NULL
,
584 buf
, len
, DTD_ELEM_INSTALLOPTS
, B_FALSE
, B_TRUE
));
588 brand_get_modname(brand_handle_t bh
, char *buf
, size_t len
)
590 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
591 return (brand_get_value(bhp
, NULL
, NULL
, NULL
, NULL
,
592 buf
, len
, DTD_ELEM_MODNAME
, B_FALSE
, B_TRUE
));
596 brand_get_postattach(brand_handle_t bh
, const char *zonename
,
597 const char *zonepath
, char *buf
, size_t len
)
599 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
600 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
601 buf
, len
, DTD_ELEM_POSTATTACH
, B_TRUE
, B_TRUE
));
605 brand_get_postclone(brand_handle_t bh
, const char *zonename
,
606 const char *zonepath
, char *buf
, size_t len
)
608 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
609 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
610 buf
, len
, DTD_ELEM_POSTCLONE
, B_TRUE
, B_TRUE
));
614 brand_get_postinstall(brand_handle_t bh
, const char *zonename
,
615 const char *zonepath
, char *buf
, size_t len
)
617 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
618 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
619 buf
, len
, DTD_ELEM_POSTINSTALL
, B_TRUE
, B_TRUE
));
623 brand_get_postsnap(brand_handle_t bh
, const char *zonename
,
624 const char *zonepath
, char *buf
, size_t len
)
626 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
627 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
628 buf
, len
, DTD_ELEM_POSTSNAP
, B_TRUE
, B_TRUE
));
632 brand_get_poststatechange(brand_handle_t bh
, const char *zonename
,
633 const char *zonepath
, char *buf
, size_t len
)
635 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
636 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
637 buf
, len
, DTD_ELEM_POSTSTATECHG
, B_TRUE
, B_TRUE
));
641 brand_get_predetach(brand_handle_t bh
, const char *zonename
,
642 const char *zonepath
, char *buf
, size_t len
)
644 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
645 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
646 buf
, len
, DTD_ELEM_PREDETACH
, B_TRUE
, B_TRUE
));
650 brand_get_presnap(brand_handle_t bh
, const char *zonename
,
651 const char *zonepath
, char *buf
, size_t len
)
653 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
654 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
655 buf
, len
, DTD_ELEM_PRESNAP
, B_TRUE
, B_TRUE
));
659 brand_get_prestatechange(brand_handle_t bh
, const char *zonename
,
660 const char *zonepath
, char *buf
, size_t len
)
662 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
663 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
664 buf
, len
, DTD_ELEM_PRESTATECHG
, B_TRUE
, B_TRUE
));
668 brand_get_preuninstall(brand_handle_t bh
, const char *zonename
,
669 const char *zonepath
, char *buf
, size_t len
)
671 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
672 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
673 buf
, len
, DTD_ELEM_PREUNINSTALL
, B_TRUE
, B_TRUE
));
677 brand_get_query(brand_handle_t bh
, const char *zonename
,
678 const char *zonepath
, char *buf
, size_t len
)
680 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
681 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
682 buf
, len
, DTD_ELEM_QUERY
, B_TRUE
, B_TRUE
));
686 brand_get_uninstall(brand_handle_t bh
, const char *zonename
,
687 const char *zonepath
, char *buf
, size_t len
)
689 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
690 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
691 buf
, len
, DTD_ELEM_UNINSTALL
, B_TRUE
, B_TRUE
));
695 brand_get_validatesnap(brand_handle_t bh
, const char *zonename
,
696 const char *zonepath
, char *buf
, size_t len
)
698 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
699 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
700 buf
, len
, DTD_ELEM_VALIDSNAP
, B_TRUE
, B_TRUE
));
704 brand_get_verify_cfg(brand_handle_t bh
, char *buf
, size_t len
)
706 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
707 return (brand_get_value(bhp
, NULL
, NULL
, NULL
, NULL
,
708 buf
, len
, DTD_ELEM_VERIFY_CFG
, B_FALSE
, B_TRUE
));
712 brand_get_verify_adm(brand_handle_t bh
, const char *zonename
,
713 const char *zonepath
, char *buf
, size_t len
)
715 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
716 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
717 buf
, len
, DTD_ELEM_VERIFY_ADM
, B_TRUE
, B_TRUE
));
721 brand_get_sysboot(brand_handle_t bh
, const char *zonename
,
722 const char *zonepath
, char *buf
, size_t len
)
724 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
725 return (brand_get_value(bhp
, zonename
, zonepath
, NULL
, NULL
,
726 buf
, len
, DTD_ELEM_SYSBOOT
, B_TRUE
, B_TRUE
));
730 brand_allow_exclusive_ip(brand_handle_t bh
)
732 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
739 if ((node
= xmlDocGetRootElement(bhp
->bh_platform
)) == NULL
)
742 allow_excl
= xmlGetProp(node
, DTD_ATTR_ALLOWEXCL
);
743 if (allow_excl
== NULL
)
746 /* Note: only return B_TRUE if it's "true" */
747 if (strcmp((char *)allow_excl
, DTD_ENTITY_TRUE
) == 0)
758 * Iterate over brand privileges
760 * Walks the brand config, searching for <privilege> elements, calling the
761 * specified callback for each. Returns 0 on success, or -1 on failure.
764 brand_config_iter_privilege(brand_handle_t bh
,
765 int (*func
)(void *, priv_iter_t
*), void *data
)
767 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
769 xmlChar
*name
, *set
, *iptype
;
770 priv_iter_t priv_iter
;
773 if ((node
= xmlDocGetRootElement(bhp
->bh_config
)) == NULL
)
776 for (node
= node
->xmlChildrenNode
; node
!= NULL
; node
= node
->next
) {
778 if (xmlStrcmp(node
->name
, DTD_ELEM_PRIVILEGE
) != 0)
781 name
= xmlGetProp(node
, DTD_ATTR_NAME
);
782 set
= xmlGetProp(node
, DTD_ATTR_SET
);
783 iptype
= xmlGetProp(node
, DTD_ATTR_IPTYPE
);
785 if (name
== NULL
|| set
== NULL
|| iptype
== NULL
) {
795 priv_iter
.pi_name
= (char *)name
;
796 priv_iter
.pi_set
= (char *)set
;
797 priv_iter
.pi_iptype
= (char *)iptype
;
799 ret
= func(data
, &priv_iter
);
813 i_brand_platform_iter_mounts(struct brand_handle
*bhp
, const char *zonename
,
814 const char *zonepath
, int (*func
)(void *, const char *, const char *,
815 const char *, const char *), void *data
, const xmlChar
*mount_type
)
818 xmlChar
*special
, *dir
, *type
, *opt
;
819 char special_exp
[MAXPATHLEN
];
820 char opt_exp
[MAXPATHLEN
];
823 if ((node
= xmlDocGetRootElement(bhp
->bh_platform
)) == NULL
)
826 for (node
= node
->xmlChildrenNode
; node
!= NULL
; node
= node
->next
) {
828 if (xmlStrcmp(node
->name
, mount_type
) != 0)
831 special
= xmlGetProp(node
, DTD_ATTR_SPECIAL
);
832 dir
= xmlGetProp(node
, DTD_ATTR_DIRECTORY
);
833 type
= xmlGetProp(node
, DTD_ATTR_TYPE
);
834 opt
= xmlGetProp(node
, DTD_ATTR_OPT
);
835 if ((special
== NULL
) || (dir
== NULL
) || (type
== NULL
) ||
841 /* Substitute token values as needed. */
842 if ((ret
= i_substitute_tokens((char *)special
,
843 special_exp
, sizeof (special_exp
),
844 zonename
, zonepath
, NULL
, NULL
)) != 0)
847 /* opt might not be defined */
848 if (strlen((const char *)opt
) == 0) {
852 if ((ret
= i_substitute_tokens((char *)opt
,
853 opt_exp
, sizeof (opt_exp
),
854 zonename
, zonepath
, NULL
, NULL
)) != 0)
858 ret
= func(data
, (char *)special_exp
, (char *)dir
,
859 (char *)type
, ((opt
!= NULL
) ? opt_exp
: NULL
));
878 * Iterate over global platform filesystems
880 * Walks the platform, searching for <global_mount> elements, calling the
881 * specified callback for each. Returns 0 on success, or -1 on failure.
883 * Perform the following substitutions as necessary:
885 * %R Zonepath of zone
888 brand_platform_iter_gmounts(brand_handle_t bh
, const char *zonename
,
889 const char *zonepath
, int (*func
)(void *, const char *, const char *,
890 const char *, const char *), void *data
)
892 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
893 return (i_brand_platform_iter_mounts(bhp
, zonename
, zonepath
, func
,
894 data
, DTD_ELEM_GLOBAL_MOUNT
));
898 * Iterate over non-global zone platform filesystems
900 * Walks the platform, searching for <mount> elements, calling the
901 * specified callback for each. Returns 0 on success, or -1 on failure.
904 brand_platform_iter_mounts(brand_handle_t bh
, int (*func
)(void *,
905 const char *, const char *, const char *, const char *), void *data
)
907 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
908 return (i_brand_platform_iter_mounts(bhp
, NULL
, NULL
, func
, data
,
913 * Iterate over platform symlinks
915 * Walks the platform, searching for <symlink> elements, calling the
916 * specified callback for each. Returns 0 on success, or -1 on failure.
919 brand_platform_iter_link(brand_handle_t bh
,
920 int (*func
)(void *, const char *, const char *), void *data
)
922 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
924 xmlChar
*source
, *target
;
927 if ((node
= xmlDocGetRootElement(bhp
->bh_platform
)) == NULL
)
930 for (node
= node
->xmlChildrenNode
; node
!= NULL
; node
= node
->next
) {
932 if (xmlStrcmp(node
->name
, DTD_ELEM_SYMLINK
) != 0)
935 source
= xmlGetProp(node
, DTD_ATTR_SOURCE
);
936 target
= xmlGetProp(node
, DTD_ATTR_TARGET
);
938 if (source
== NULL
|| target
== NULL
) {
946 ret
= func(data
, (char *)source
, (char *)target
);
959 * Iterate over platform devices
961 * Walks the platform, searching for <device> elements, calling the
962 * specified callback for each. Returns 0 on success, or -1 on failure.
965 brand_platform_iter_devices(brand_handle_t bh
, const char *zonename
,
966 int (*func
)(void *, const char *, const char *), void *data
,
967 const char *curr_iptype
)
969 struct brand_handle
*bhp
= (struct brand_handle
*)bh
;
970 const char *curr_arch
= get_curr_arch();
972 xmlChar
*match
, *name
, *arch
, *iptype
;
973 char match_exp
[MAXPATHLEN
];
974 boolean_t err
= B_FALSE
;
979 assert(zonename
!= NULL
);
980 assert(func
!= NULL
);
981 assert(curr_iptype
!= NULL
);
983 if ((node
= xmlDocGetRootElement(bhp
->bh_platform
)) == NULL
)
986 for (node
= node
->xmlChildrenNode
; node
!= NULL
; node
= node
->next
) {
988 if (xmlStrcmp(node
->name
, DTD_ELEM_DEVICE
) != 0)
991 match
= xmlGetProp(node
, DTD_ATTR_MATCH
);
992 name
= xmlGetProp(node
, DTD_ATTR_NAME
);
993 arch
= xmlGetProp(node
, DTD_ATTR_ARCH
);
994 iptype
= xmlGetProp(node
, DTD_ATTR_IPTYPE
);
995 if ((match
== NULL
) || (name
== NULL
) || (arch
== NULL
) ||
1001 /* check if the arch matches */
1002 if ((strcmp((char *)arch
, "all") != 0) &&
1003 (strcmp((char *)arch
, curr_arch
) != 0))
1006 /* check if the iptype matches */
1007 if ((strcmp((char *)iptype
, "all") != 0) &&
1008 (strcmp((char *)iptype
, curr_iptype
) != 0))
1011 /* Substitute token values as needed. */
1012 if ((ret
= i_substitute_tokens((char *)match
,
1013 match_exp
, sizeof (match_exp
),
1014 zonename
, NULL
, NULL
, NULL
)) != 0) {
1019 /* name might not be defined */
1020 if (strlen((const char *)name
) == 0) {
1025 /* invoke the callback */
1026 ret
= func(data
, (const char *)match_exp
, (const char *)name
);