diff options
Diffstat (limited to 'usr/src/lib/libc/port/sys/zone.c')
-rw-r--r-- | usr/src/lib/libc/port/sys/zone.c | 201 |
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)); +} |