summaryrefslogtreecommitdiff
path: root/usr/src/lib/libc/sparc/sys/uadmin.c
diff options
context:
space:
mode:
authorJan Setje-Eilers <Jan.Setje-Eilers@Sun.COM>2009-07-07 22:27:57 -0700
committerJan Setje-Eilers <Jan.Setje-Eilers@Sun.COM>2009-07-07 22:27:57 -0700
commit4ed6ceb3446c24afa0c760ea49cd78dbc7692329 (patch)
tree085dad8a771aaa423d0a47f2cdb6e993bfd5a35a /usr/src/lib/libc/sparc/sys/uadmin.c
parent09b1eac246a4e627fcbd1ce5bf8005746cbe45ea (diff)
downloadillumos-gate-4ed6ceb3446c24afa0c760ea49cd78dbc7692329.tar.gz
6858169 libc should not publish libscf's interfaces
Diffstat (limited to 'usr/src/lib/libc/sparc/sys/uadmin.c')
-rw-r--r--usr/src/lib/libc/sparc/sys/uadmin.c119
1 files changed, 103 insertions, 16 deletions
diff --git a/usr/src/lib/libc/sparc/sys/uadmin.c b/usr/src/lib/libc/sparc/sys/uadmin.c
index b5d034a2ea..8358586304 100644
--- a/usr/src/lib/libc/sparc/sys/uadmin.c
+++ b/usr/src/lib/libc/sparc/sys/uadmin.c
@@ -23,36 +23,123 @@
* Use is subject to license terms.
*/
+#include "mtlib.h"
#include <sys/types.h>
#include <libscf.h>
#include <sys/uadmin.h>
#include <unistd.h>
#include <stdlib.h>
#include <zone.h>
+#include <thread.h>
+#include <dlfcn.h>
+#include <atomic.h>
-int
-uadmin(int cmd, int fcn, uintptr_t mdep)
+/*
+ * Pull in the following three interfaces from libscf without introducing
+ * a dependency on it, which since libscf depends on libc would be circular:
+ *
+ * scf_simple_prop_get
+ * scf_simple_prop_next_boolean
+ * scf_simple_prop_free
+ */
+typedef scf_simple_prop_t *(*scf_simple_prop_get_t)(scf_handle_t *,
+ const char *, const char *, const char *);
+static scf_simple_prop_get_t real_scf_simple_prop_get = NULL;
+typedef uint8_t *(*scf_simple_prop_next_boolean_t)(scf_simple_prop_t *);
+static scf_simple_prop_next_boolean_t real_scf_simple_prop_next_boolean = NULL;
+typedef void (*scf_simple_prop_free_t)(scf_simple_prop_t *);
+static scf_simple_prop_free_t real_scf_simple_prop_free = NULL;
+static mutex_t scf_lock = DEFAULTMUTEX;
+
+static void
+load_scf(void)
+{
+ void *scf_handle = dlopen("libscf.so.1", RTLD_LAZY);
+ scf_simple_prop_get_t scf_simple_prop_get = (scf_handle == NULL)? NULL :
+ (scf_simple_prop_get_t)dlsym(scf_handle, "scf_simple_prop_get");
+ scf_simple_prop_next_boolean_t scf_simple_prop_next_boolean =
+ (scf_handle == NULL)? NULL :
+ (scf_simple_prop_next_boolean_t)dlsym(scf_handle,
+ "scf_simple_prop_next_boolean");
+ scf_simple_prop_free_t scf_simple_prop_free =
+ (scf_handle == NULL)? NULL :
+ (scf_simple_prop_free_t)dlsym(scf_handle, "scf_simple_prop_free");
+
+ lmutex_lock(&scf_lock);
+ if (real_scf_simple_prop_get == NULL ||
+ real_scf_simple_prop_next_boolean == NULL ||
+ real_scf_simple_prop_free == NULL) {
+ if (scf_simple_prop_get == NULL)
+ real_scf_simple_prop_get = (scf_simple_prop_get_t)(-1);
+ else {
+ real_scf_simple_prop_get = scf_simple_prop_get;
+ scf_handle = NULL; /* don't dlclose it */
+ }
+ if (scf_simple_prop_next_boolean == NULL)
+ real_scf_simple_prop_next_boolean =
+ (scf_simple_prop_next_boolean_t)(-1);
+ else {
+ real_scf_simple_prop_next_boolean =
+ scf_simple_prop_next_boolean;
+ scf_handle = NULL; /* don't dlclose it */
+ }
+ if (scf_simple_prop_free == NULL)
+ real_scf_simple_prop_free =
+ (scf_simple_prop_free_t)(-1);
+ else {
+ real_scf_simple_prop_free = scf_simple_prop_free;
+ scf_handle = NULL; /* don't dlclose it */
+ }
+ membar_producer();
+ }
+ lmutex_unlock(&scf_lock);
+
+ if (scf_handle)
+ (void) dlclose(scf_handle);
+}
+
+static void
+check_archive_update(void)
{
- extern int __uadmin(int cmd, int fcn, uintptr_t mdep);
scf_simple_prop_t *prop = NULL;
- uint8_t *ret_val = NULL;
boolean_t update_flag = B_FALSE;
char *fmri = "svc:/system/boot-config:default";
+ uint8_t *ret_val = NULL;
+
+ if (real_scf_simple_prop_get == NULL ||
+ real_scf_simple_prop_next_boolean == NULL ||
+ real_scf_simple_prop_free == NULL) {
+ load_scf();
+ }
+ if (real_scf_simple_prop_get == (scf_simple_prop_get_t)(-1) ||
+ real_scf_simple_prop_next_boolean ==
+ (scf_simple_prop_next_boolean_t)(-1) ||
+ real_scf_simple_prop_free == (scf_simple_prop_free_t)(-1)) {
+ return;
+ }
+
+ prop = real_scf_simple_prop_get(NULL, fmri, "config",
+ "uadmin_boot_archive_sync");
+ if (prop) {
+ if ((ret_val = real_scf_simple_prop_next_boolean(prop)) !=
+ NULL)
+ update_flag = (*ret_val == 0) ? B_FALSE :
+ B_TRUE;
+ real_scf_simple_prop_free(prop);
+ }
+
+ if (update_flag == B_TRUE)
+ (void) system("/sbin/bootadm update-archive");
+}
+
+int
+uadmin(int cmd, int fcn, uintptr_t mdep)
+{
+ extern int __uadmin(int cmd, int fcn, uintptr_t mdep);
if (geteuid() == 0 && getzoneid() == GLOBAL_ZONEID &&
(cmd == A_SHUTDOWN || cmd == A_REBOOT)) {
- prop = scf_simple_prop_get(NULL, fmri, "config",
- "uadmin_boot_archive_sync");
- if (prop) {
- if ((ret_val = scf_simple_prop_next_boolean(prop)) !=
- NULL)
- update_flag = (*ret_val == 0) ? B_FALSE :
- B_TRUE;
- scf_simple_prop_free(prop);
- }
-
- if (update_flag == B_TRUE)
- (void) system("/sbin/bootadm update-archive");
+ check_archive_update();
}
return (__uadmin(cmd, fcn, mdep));