summaryrefslogtreecommitdiff
path: root/usr/src/lib/libc/port/sys/zone.c
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libc/port/sys/zone.c
downloadillumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libc/port/sys/zone.c')
-rw-r--r--usr/src/lib/libc/port/sys/zone.c201
1 files changed, 201 insertions, 0 deletions
diff --git a/usr/src/lib/libc/port/sys/zone.c b/usr/src/lib/libc/port/sys/zone.c
new file mode 100644
index 0000000000..416313941f
--- /dev/null
+++ b/usr/src/lib/libc/port/sys/zone.c
@@ -0,0 +1,201 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#pragma weak getzoneid = _getzoneid
+#pragma weak getzoneidbyname = _getzoneidbyname
+#pragma weak getzonenamebyid = _getzonenamebyid
+
+#include "synonyms.h"
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <sys/zone.h>
+#include <sys/priv.h>
+#include <zone.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <errno.h>
+
+zoneid_t
+zone_create(const char *name, const char *root, const priv_set_t *privs,
+ const char *rctls, size_t rctlsz, int *extended_error)
+{
+ zone_def zd;
+
+ zd.zone_name = name;
+ zd.zone_root = root;
+ zd.zone_privs = privs;
+ zd.rctlbuf = rctls;
+ zd.rctlbufsz = rctlsz;
+ zd.extended_error = extended_error;
+
+ return ((zoneid_t)syscall(SYS_zone,
+ ZONE_CREATE, &zd));
+}
+
+int
+zone_boot(zoneid_t zoneid, const char *bootargs)
+{
+ return (syscall(SYS_zone, ZONE_BOOT, zoneid, bootargs));
+}
+
+int
+zone_shutdown(zoneid_t zoneid)
+{
+ return (syscall(SYS_zone, ZONE_SHUTDOWN, zoneid));
+}
+
+int
+zone_destroy(zoneid_t zoneid)
+{
+ return (syscall(SYS_zone, ZONE_DESTROY, zoneid));
+}
+
+ssize_t
+zone_getattr(zoneid_t zoneid, int attr, void *valp, size_t size)
+{
+ sysret_t rval;
+ int error;
+
+ error = __systemcall(&rval, SYS_zone, ZONE_GETATTR, zoneid,
+ attr, valp, size);
+ if (error)
+ (void) __set_errno(error);
+ return ((ssize_t)rval.sys_rval1);
+}
+
+int
+zone_enter(zoneid_t zoneid)
+{
+ return (syscall(SYS_zone, ZONE_ENTER, zoneid));
+}
+
+/*
+ * Get id (if any) for specified zone.
+ *
+ * Call the real zone_get_id() in libzonecfg.so.1 if it can be found.
+ * Otherwise, perform a stripped-down version of the function.
+ * Any changes in one version should probably be reflected in the other.
+ *
+ * This stripped-down version of the function only checks for active
+ * (booted) zones, by numeric id or name.
+ */
+
+typedef int (*zone_get_id_t)(const char *, zoneid_t *);
+static zone_get_id_t real_zone_get_id = NULL;
+
+int
+zone_get_id(const char *str, zoneid_t *zip)
+{
+ zoneid_t zoneid;
+ char *cp;
+
+ /*
+ * The first time we are called, attempt to dlopen() libzonecfg.so.1
+ * and get a pointer to the real zone_get_id().
+ * If we fail, set our pointer to -1 so we won't try again.
+ */
+ if (real_zone_get_id == NULL) {
+ /*
+ * There's no harm in doing this more than once, even
+ * concurrently. We will get the same result each time,
+ * and the dynamic linker will single-thread the dlopen()
+ * with its own internal lock. The worst that can happen
+ * is that the handle gets a reference count greater than
+ * one, which doesn't matter since we never dlclose()
+ * the handle if we successfully find the symbol; the
+ * library just stays in the address space until exit().
+ */
+ void *dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY);
+ void *sym = (void *)(-1);
+
+ if (dlhandle != NULL &&
+ (sym = dlsym(dlhandle, "zone_get_id")) == NULL) {
+ sym = (void *)(-1);
+ (void) dlclose(dlhandle);
+ }
+ real_zone_get_id = (zone_get_id_t)sym;
+ }
+
+ /*
+ * If we've successfully loaded it, call the real zone_get_id().
+ * Otherwise, perform our stripped-down version of the code.
+ */
+ if (real_zone_get_id != (zone_get_id_t)(-1))
+ return (real_zone_get_id(str, zip));
+
+ /* first try looking for active zone by id */
+ errno = 0;
+ zoneid = (zoneid_t)strtol(str, &cp, 0);
+ if (errno == 0 && cp != str && *cp == '\0' &&
+ getzonenamebyid(zoneid, NULL, 0) != -1) {
+ *zip = zoneid;
+ return (0);
+ }
+
+ /* then look for active zone by name */
+ if ((zoneid = getzoneidbyname(str)) != -1) {
+ *zip = zoneid;
+ return (0);
+ }
+
+ /* not an active zone, return error */
+ return (-1);
+}
+
+int
+zone_list(zoneid_t *zonelist, uint_t *numzones)
+{
+ return (syscall(SYS_zone, ZONE_LIST, zonelist, numzones));
+}
+
+/*
+ * Underlying implementation for getzoneid and getzoneidbyname.
+ */
+static zoneid_t
+zone_lookup(const char *name)
+{
+ return ((zoneid_t)syscall(SYS_zone, ZONE_LOOKUP, name));
+}
+
+zoneid_t
+getzoneid(void)
+{
+ return (zone_lookup(NULL));
+}
+
+zoneid_t
+getzoneidbyname(const char *zonename)
+{
+ return (zone_lookup(zonename));
+}
+
+ssize_t
+getzonenamebyid(zoneid_t zoneid, char *buf, size_t buflen)
+{
+ return (zone_getattr(zoneid, ZONE_ATTR_NAME, buf, buflen));
+}