diff options
Diffstat (limited to 'usr/src/common')
| -rw-r--r-- | usr/src/common/brand/lx/lx_signum.c | 244 | ||||
| -rw-r--r-- | usr/src/common/brand/lx/lx_signum.h | 81 | ||||
| -rw-r--r-- | usr/src/common/brand/lx/lx_syscall.h | 47 | ||||
| -rw-r--r-- | usr/src/common/ctf/ctf_create.c | 2 | ||||
| -rw-r--r-- | usr/src/common/ctf/ctf_hash.c | 160 | ||||
| -rw-r--r-- | usr/src/common/ctf/ctf_impl.h | 6 | ||||
| -rw-r--r-- | usr/src/common/ctf/ctf_types.c | 64 | ||||
| -rw-r--r-- | usr/src/common/fs/bootfsops.c | 329 | ||||
| -rw-r--r-- | usr/src/common/util/string.c | 7 | ||||
| -rw-r--r-- | usr/src/common/util/string.h | 1 | ||||
| -rw-r--r-- | usr/src/common/util/strtolctype.h | 4 | ||||
| -rw-r--r-- | usr/src/common/zfs/zfs_prop.c | 17 | ||||
| -rw-r--r-- | usr/src/common/zfs/zfs_prop.h | 2 |
13 files changed, 957 insertions, 7 deletions
diff --git a/usr/src/common/brand/lx/lx_signum.c b/usr/src/common/brand/lx/lx_signum.c new file mode 100644 index 0000000000..08ab453885 --- /dev/null +++ b/usr/src/common/brand/lx/lx_signum.c @@ -0,0 +1,244 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (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 2010 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * Copyright (c) 2014, Joyent, Inc. All rights reserved. + */ + +#include <sys/signal.h> +#include <lx_signum.h> + +/* + * Delivering signals to a Linux process is complicated by differences in + * signal numbering, stack structure and contents, and the action taken when a + * signal handler exits. In addition, many signal-related structures, such as + * sigset_ts, vary between Solaris and Linux. + * + * The simplest transformation that must be done when sending signals is to + * translate between Linux and Solaris signal numbers. + * + * These are the major signal number differences between Linux and Solaris: + * + * ==================================== + * | Number | Linux | Solaris | + * | ====== | ========= | ========== | + * | 7 | SIGBUS | SIGEMT | + * | 10 | SIGUSR1 | SIGBUS | + * | 12 | SIGUSR2 | SIGSYS | + * | 16 | SIGSTKFLT | SIGUSR1 | + * | 17 | SIGCHLD | SIGUSR2 | + * | 18 | SIGCONT | SIGCHLD | + * | 19 | SIGSTOP | SIGPWR | + * | 20 | SIGTSTP | SIGWINCH | + * | 21 | SIGTTIN | SIGURG | + * | 22 | SIGTTOU | SIGPOLL | + * | 23 | SIGURG | SIGSTOP | + * | 24 | SIGXCPU | SIGTSTP | + * | 25 | SIGXFSZ | SIGCONT | + * | 26 | SIGVTALARM | SIGTTIN | + * | 27 | SIGPROF | SIGTTOU | + * | 28 | SIGWINCH | SIGVTALARM | + * | 29 | SIGPOLL | SIGPROF | + * | 30 | SIGPWR | SIGXCPU | + * | 31 | SIGSYS | SIGXFSZ | + * ==================================== + * + * Not every Linux signal maps to a Solaris signal, nor does every Solaris + * signal map to a Linux counterpart. However, when signals do map, the + * mapping is unique. + * + * One mapping issue is that Linux supports 33 real time signals, with SIGRTMIN + * typically starting at or near 32 (SIGRTMIN) and proceeding to 64 (SIGRTMAX) + * (SIGRTMIN is "at or near" 32 because glibc usually "steals" one ore more of + * these signals for its own internal use, adjusting SIGRTMIN and SIGRTMAX as + * needed.) Conversely, Solaris actively uses signals 32-40 for other purposes + * and supports exactly 32 real time signals, in the range 41 (SIGRTMIN) + * to 72 (SIGRTMAX). + * + * At present, attempting to translate a Linux signal equal to 63 + * will generate an error (we allow SIGRTMAX because a program + * should be able to send SIGRTMAX without getting an EINVAL, though obviously + * anything that loops through the signals from SIGRTMIN to SIGRTMAX will + * fail.) + * + * Similarly, attempting to translate a native Solaris signal in the range + * 32-40 will also generate an error as we don't want to support the receipt of + * those signals from the Solaris global zone. + */ + +/* + * Linux to Solaris signal map + * + * Usage: solaris_signal = ltos_signum[lx_signal]; + */ +const int +ltos_signo[LX_NSIG + 1] = { + 0, + SIGHUP, + SIGINT, + SIGQUIT, + SIGILL, + SIGTRAP, + SIGABRT, + SIGBUS, + SIGFPE, + SIGKILL, + SIGUSR1, + SIGSEGV, + SIGUSR2, + SIGPIPE, + SIGALRM, + SIGTERM, + SIGEMT, /* 16: Linux SIGSTKFLT; use Solaris SIGEMT */ + SIGCHLD, + SIGCONT, + SIGSTOP, + SIGTSTP, + SIGTTIN, + SIGTTOU, + SIGURG, + SIGXCPU, + SIGXFSZ, + SIGVTALRM, + SIGPROF, + SIGWINCH, + SIGPOLL, + SIGPWR, + SIGSYS, + _SIGRTMIN, /* 32: Linux SIGRTMIN */ + _SIGRTMIN + 1, + _SIGRTMIN + 2, + _SIGRTMIN + 3, + _SIGRTMIN + 4, + _SIGRTMIN + 5, + _SIGRTMIN + 6, + _SIGRTMIN + 7, + _SIGRTMIN + 8, + _SIGRTMIN + 9, + _SIGRTMIN + 10, + _SIGRTMIN + 11, + _SIGRTMIN + 12, + _SIGRTMIN + 13, + _SIGRTMIN + 14, + _SIGRTMIN + 15, + _SIGRTMIN + 16, + _SIGRTMIN + 17, + _SIGRTMIN + 18, + _SIGRTMIN + 19, + _SIGRTMIN + 20, + _SIGRTMIN + 21, + _SIGRTMIN + 22, + _SIGRTMIN + 23, + _SIGRTMIN + 24, + _SIGRTMIN + 25, + _SIGRTMIN + 26, + _SIGRTMIN + 27, + _SIGRTMIN + 28, + _SIGRTMIN + 29, + _SIGRTMIN + 30, + -1, /* 63: Linux SIGRTMIN + 31, or SIGRTMAX - 1 */ + _SIGRTMAX, /* 64: Linux SIGRTMAX */ +}; + +/* + * Solaris to Linux signal map + * + * Usage: lx_signal = stol_signo[solaris_signal]; + */ +const int +stol_signo[NSIG] = { + 0, + LX_SIGHUP, + LX_SIGINT, + LX_SIGQUIT, + LX_SIGILL, + LX_SIGTRAP, + LX_SIGABRT, + LX_SIGSTKFLT, /* 7: Solaris SIGEMT; use for LX_SIGSTKFLT */ + LX_SIGFPE, + LX_SIGKILL, + LX_SIGBUS, + LX_SIGSEGV, + LX_SIGSYS, + LX_SIGPIPE, + LX_SIGALRM, + LX_SIGTERM, + LX_SIGUSR1, + LX_SIGUSR2, + LX_SIGCHLD, + LX_SIGPWR, + LX_SIGWINCH, + LX_SIGURG, + LX_SIGPOLL, + LX_SIGSTOP, + LX_SIGTSTP, + LX_SIGCONT, + LX_SIGTTIN, + LX_SIGTTOU, + LX_SIGVTALRM, + LX_SIGPROF, + LX_SIGXCPU, + LX_SIGXFSZ, + -1, /* 32: Solaris SIGWAITING */ + -1, /* 33: Solaris SIGLWP */ + -1, /* 34: Solaris SIGFREEZE */ + -1, /* 35: Solaris SIGTHAW */ + -1, /* 36: Solaris SIGCANCEL */ + -1, /* 37: Solaris SIGLOST */ + -1, /* 38: Solaris SIGXRES */ + -1, /* 39: Solaris SIGJVM1 */ + -1, /* 40: Solaris SIGJVM2 */ + -1, /* 41: Solaris SIGINFO */ + LX_SIGRTMIN, /* 42: Solaris _SIGRTMIN */ + LX_SIGRTMIN + 1, + LX_SIGRTMIN + 2, + LX_SIGRTMIN + 3, + LX_SIGRTMIN + 4, + LX_SIGRTMIN + 5, + LX_SIGRTMIN + 6, + LX_SIGRTMIN + 7, + LX_SIGRTMIN + 8, + LX_SIGRTMIN + 9, + LX_SIGRTMIN + 10, + LX_SIGRTMIN + 11, + LX_SIGRTMIN + 12, + LX_SIGRTMIN + 13, + LX_SIGRTMIN + 14, + LX_SIGRTMIN + 15, + LX_SIGRTMIN + 16, + LX_SIGRTMIN + 17, + LX_SIGRTMIN + 18, + LX_SIGRTMIN + 19, + LX_SIGRTMIN + 20, + LX_SIGRTMIN + 21, + LX_SIGRTMIN + 22, + LX_SIGRTMIN + 23, + LX_SIGRTMIN + 24, + LX_SIGRTMIN + 25, + LX_SIGRTMIN + 26, + LX_SIGRTMIN + 27, + LX_SIGRTMIN + 28, + LX_SIGRTMIN + 29, + LX_SIGRTMIN + 30, + LX_SIGRTMAX, /* 73: Solaris _SIGRTMAX */ +}; diff --git a/usr/src/common/brand/lx/lx_signum.h b/usr/src/common/brand/lx/lx_signum.h new file mode 100644 index 0000000000..f410500925 --- /dev/null +++ b/usr/src/common/brand/lx/lx_signum.h @@ -0,0 +1,81 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (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 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * Copyright 2014 Joyent, Inc. All rights reserved. + */ + +#ifndef _LX_SIGNUM_H +#define _LX_SIGNUM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define LX_SIGHUP 1 +#define LX_SIGINT 2 +#define LX_SIGQUIT 3 +#define LX_SIGILL 4 +#define LX_SIGTRAP 5 +#define LX_SIGABRT 6 +#define LX_SIGIOT 6 +#define LX_SIGBUS 7 +#define LX_SIGFPE 8 +#define LX_SIGKILL 9 +#define LX_SIGUSR1 10 +#define LX_SIGSEGV 11 +#define LX_SIGUSR2 12 +#define LX_SIGPIPE 13 +#define LX_SIGALRM 14 +#define LX_SIGTERM 15 +#define LX_SIGSTKFLT 16 +#define LX_SIGCHLD 17 +#define LX_SIGCONT 18 +#define LX_SIGSTOP 19 +#define LX_SIGTSTP 20 +#define LX_SIGTTIN 21 +#define LX_SIGTTOU 22 +#define LX_SIGURG 23 +#define LX_SIGXCPU 24 +#define LX_SIGXFSZ 25 +#define LX_SIGVTALRM 26 +#define LX_SIGPROF 27 +#define LX_SIGWINCH 28 +#define LX_SIGIO 29 +#define LX_SIGPOLL LX_SIGIO +#define LX_SIGPWR 30 +#define LX_SIGSYS 31 +#define LX_SIGUNUSED 31 + +#define LX_NSIG 64 /* Linux _NSIG */ + +#define LX_SIGRTMIN 32 +#define LX_SIGRTMAX LX_NSIG + +extern const int ltos_signo[]; +extern const int stol_signo[]; + +#ifdef __cplusplus +} +#endif + +#endif /* _LX_SIGNUM_H */ diff --git a/usr/src/common/brand/lx/lx_syscall.h b/usr/src/common/brand/lx/lx_syscall.h new file mode 100644 index 0000000000..7bfc0537c9 --- /dev/null +++ b/usr/src/common/brand/lx/lx_syscall.h @@ -0,0 +1,47 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2014 Joyent, Inc. All rights reserved. + */ + +#ifndef _LX_SYSCALL_H +#define _LX_SYSCALL_H + +#include <sys/lx_brand.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The br_scall_args field of lx_lwp_data is going to be populated with + * pointers to structs. The types of these structs should be defined in this + * header file. These are Linux specific arguments to system calls that don't + * exist in illumos. Each section should be labelled with which system call it + * belongs to. + */ + +/* arguments for waitpid(2) */ +/* see comments in usr/src/lib/brand/lx/lx_brand/common/wait.c */ +#define LX_WNOTHREAD 0x20000000 /* Do not wait on siblings' children */ +#define LX_WALL 0x40000000 /* Wait on all children */ +#define LX_WCLONE 0x80000000 /* Wait only on clone children */ +typedef struct lx_waitid_args { + int waitid_flags; +} lx_waitid_args_t; + + +#ifdef __cplusplus +} +#endif + +#endif /* _LX_SYSCALL_H */ diff --git a/usr/src/common/ctf/ctf_create.c b/usr/src/common/ctf/ctf_create.c index 239d166f44..f9feca81cf 100644 --- a/usr/src/common/ctf/ctf_create.c +++ b/usr/src/common/ctf/ctf_create.c @@ -574,7 +574,7 @@ ctf_dtd_lookup(ctf_file_t *fp, ctf_id_t type) int ctf_discard(ctf_file_t *fp) { - ctf_dtdef_t *dtd, *ntd; + ctf_dtdef_t *dtd, *ntd = NULL; if (!(fp->ctf_flags & LCTF_RDWR)) return (ctf_set_errno(fp, ECTF_RDONLY)); diff --git a/usr/src/common/ctf/ctf_hash.c b/usr/src/common/ctf/ctf_hash.c index b10a7618f6..e68fe8e516 100644 --- a/usr/src/common/ctf/ctf_hash.c +++ b/usr/src/common/ctf/ctf_hash.c @@ -25,9 +25,8 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <ctf_impl.h> +#include <sys/debug.h> static const ushort_t _CTF_EMPTY[1] = { 0 }; @@ -176,3 +175,160 @@ ctf_hash_destroy(ctf_hash_t *hp) hp->h_chains = NULL; } } + +int +ctf_idhash_create(ctf_idhash_t *ihp, ulong_t nelems) +{ + if (nelems > USHRT_MAX) + return (EOVERFLOW); + + /* + * If the hash table is going to be empty, don't bother allocating any + * memory and make the only bucket point to a zero so lookups fail. + */ + if (nelems == 0) { + bzero(ihp, sizeof (ctf_idhash_t)); + ihp->ih_buckets = (ushort_t *)_CTF_EMPTY; + ihp->ih_nbuckets = 1; + return (0); + } + + ihp->ih_nbuckets = 211; /* use a prime number of hash buckets */ + ihp->ih_nelems = nelems + 1; /* we use index zero as a sentinel */ + ihp->ih_free = 1; /* first free element is index 1 */ + + ihp->ih_buckets = ctf_alloc(sizeof (ushort_t) * ihp->ih_nbuckets); + ihp->ih_chains = ctf_alloc(sizeof (ctf_ihelem_t) * ihp->ih_nelems); + + if (ihp->ih_buckets == NULL || ihp->ih_chains == NULL) { + ctf_idhash_destroy(ihp); + return (EAGAIN); + } + + bzero(ihp->ih_buckets, sizeof (ushort_t) * ihp->ih_nbuckets); + bzero(ihp->ih_chains, sizeof (ctf_ihelem_t) * ihp->ih_nelems); + + return (0); +} + +void +ctf_idhash_clear(ctf_idhash_t *ihp) +{ + /* Nothing to do for a sentinel hash */ + if (ihp->ih_nbuckets == 1) { + ASSERT(ihp->ih_buckets == (ushort_t *)_CTF_EMPTY); + return; + } + + ihp->ih_free = 1; + bzero(ihp->ih_buckets, sizeof (ushort_t) * ihp->ih_nbuckets); + bzero(ihp->ih_chains, sizeof (ctf_ihelem_t) * ihp->ih_nelems); +} + +uint_t +ctf_idhash_size(const ctf_idhash_t *hp) +{ + return (hp->ih_nelems ? hp->ih_nelems - 1 : 0); +} + +static ulong_t +ctf_idhash_compute(ctf_id_t id) +{ + return (id); +} + +int +ctf_idhash_insert(ctf_idhash_t *ihp, ushort_t type, ushort_t value) +{ + ctf_ihelem_t *ihep = &ihp->ih_chains[ihp->ih_free]; + ulong_t h; + + if (ihp->ih_free >= ihp->ih_nelems) + return (EOVERFLOW); + + ihep->ih_type = type; + ihep->ih_value = value; + h = ctf_idhash_compute(type) % ihp->ih_nbuckets; + ihep->ih_next = ihp->ih_buckets[h]; + ihp->ih_buckets[h] = ihp->ih_free++; + + return (0); +} + +int +ctf_idhash_define(ctf_idhash_t *ihp, ushort_t type, ushort_t value) +{ + ctf_ihelem_t *hep = ctf_idhash_lookup(ihp, type); + + if (hep == NULL) + return (ctf_idhash_insert(ihp, type, value)); + + hep->ih_value = value; + return (0); +} + + +ctf_ihelem_t * +ctf_idhash_lookup(ctf_idhash_t *ihp, ushort_t key) +{ + ctf_ihelem_t *ihep; + ushort_t i; + + ulong_t h = ctf_idhash_compute(key) % ihp->ih_nbuckets; + + for (i = ihp->ih_buckets[h]; i != 0; i = ihep->ih_next) { + ihep = &ihp->ih_chains[i]; + + if (ihep->ih_type == key) + return (ihep); + } + + return (NULL); +} + +void +ctf_idhash_destroy(ctf_idhash_t *ihp) +{ + if (ihp->ih_buckets != NULL && ihp->ih_nbuckets != 1) { + ctf_free(ihp->ih_buckets, sizeof (ushort_t) * ihp->ih_nbuckets); + ihp->ih_buckets = NULL; + } + + if (ihp->ih_chains != NULL) { + ctf_free(ihp->ih_chains, sizeof (ctf_helem_t) * ihp->ih_nelems); + ihp->ih_chains = NULL; + } +} + +/*ARGSUSED*/ +int +ctf_idhash_iter_init(ctf_idhash_t *ihp, ctf_idhash_iter_t **iterp) +{ + + *iterp = ctf_alloc(sizeof (ctf_idhash_iter_t)); + if (*iterp == NULL) + return (ENOMEM); + + if (ihp->ih_free == 0) + (*iterp)->cii_id = 0; + else + (*iterp)->cii_id = 1; + + return (0); +} + +const ctf_ihelem_t * +ctf_idhash_iter(ctf_idhash_t *ihp, ctf_idhash_iter_t *iter) +{ + if (iter->cii_id >= ihp->ih_free) + return (NULL); + + return (&ihp->ih_chains[iter->cii_id++]); +} + +/*ARGSUSED*/ +void +ctf_idhash_iter_fini(ctf_idhash_t *ihp, ctf_idhash_iter_t *iter) +{ + ctf_free(iter, sizeof (ctf_idhash_iter_t)); +} diff --git a/usr/src/common/ctf/ctf_impl.h b/usr/src/common/ctf/ctf_impl.h index f56fa6a005..42aec80a43 100644 --- a/usr/src/common/ctf/ctf_impl.h +++ b/usr/src/common/ctf/ctf_impl.h @@ -25,7 +25,7 @@ * Use is subject to license terms. */ /* - * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ #ifndef _CTF_IMPL_H @@ -77,6 +77,10 @@ typedef struct ctf_hash { uint_t h_free; /* index of next free hash element */ } ctf_hash_t; +struct ctf_idhash_iter { + int cii_id; /* Current iteration id */ +}; + typedef struct ctf_strs { const char *cts_strs; /* base address of string table */ size_t cts_len; /* size of string table in bytes */ diff --git a/usr/src/common/ctf/ctf_types.c b/usr/src/common/ctf/ctf_types.c index ab1b9ff14b..93168f25cb 100644 --- a/usr/src/common/ctf/ctf_types.c +++ b/usr/src/common/ctf/ctf_types.c @@ -26,6 +26,7 @@ */ #include <ctf_impl.h> +#include <sys/debug.h> ssize_t ctf_get_ctt_size(const ctf_file_t *fp, const ctf_type_t *tp, ssize_t *sizep, @@ -868,3 +869,66 @@ ctf_type_visit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg) { return (ctf_type_rvisit(fp, type, func, arg, "", 0, 0)); } + +int +ctf_func_info_by_id(ctf_file_t *fp, ctf_id_t type, ctf_funcinfo_t *fip) +{ + ctf_file_t *ofp = fp; + const ctf_type_t *tp; + const ushort_t *dp; + int nargs; + ssize_t increment; + + if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) + return (CTF_ERR); /* errno is set for us */ + + if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_FUNCTION) + return (ctf_set_errno(ofp, ECTF_NOTFUNC)); + + fip->ctc_return = tp->ctt_type; + nargs = LCTF_INFO_VLEN(fp, tp->ctt_info); + fip->ctc_argc = nargs; + fip->ctc_flags = 0; + + /* dp should now point to the first argument */ + if (nargs != 0) { + (void) ctf_get_ctt_size(fp, tp, NULL, &increment); + dp = (ushort_t *)((uintptr_t)fp->ctf_buf + + fp->ctf_txlate[CTF_TYPE_TO_INDEX(type)] + increment); + if (dp[nargs - 1] == 0) { + fip->ctc_flags |= CTF_FUNC_VARARG; + fip->ctc_argc--; + } + } + + return (0); +} + +int +ctf_func_args_by_id(ctf_file_t *fp, ctf_id_t type, uint_t argc, ctf_id_t *argv) +{ + ctf_file_t *ofp = fp; + const ctf_type_t *tp; + const ushort_t *dp; + int nargs; + ssize_t increment; + + if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) + return (CTF_ERR); /* errno is set for us */ + + if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_FUNCTION) + return (ctf_set_errno(ofp, ECTF_NOTFUNC)); + + nargs = LCTF_INFO_VLEN(fp, tp->ctt_info); + (void) ctf_get_ctt_size(fp, tp, NULL, &increment); + dp = (ushort_t *)((uintptr_t)fp->ctf_buf + + fp->ctf_txlate[CTF_TYPE_TO_INDEX(type)] + + increment); + if (nargs != 0 && dp[nargs - 1] == 0) + nargs--; + + for (nargs = MIN(argc, nargs); nargs != 0; nargs--) + *argv++ = *dp++; + + return (0); +} diff --git a/usr/src/common/fs/bootfsops.c b/usr/src/common/fs/bootfsops.c new file mode 100644 index 0000000000..5a693b80e5 --- /dev/null +++ b/usr/src/common/fs/bootfsops.c @@ -0,0 +1,329 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2013 Joyent, Inc. All rights reserved. + */ + +#include <sys/bootconf.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/vnode.h> +#include <sys/fs/ufs_fsdir.h> +#include <sys/fs/ufs_fs.h> +#include <sys/fs/ufs_inode.h> +#include <sys/sysmacros.h> +#include <sys/bootvfs.h> +#include <sys/bootinfo.h> +#include <sys/filep.h> + +#ifdef _BOOT +#include "../common/util.h" +#else +#include <sys/sunddi.h> +#endif + +#define MAX_FILES MAX_BOOT_MODULES +#define MAX_FDS 256 + +extern void *bkmem_alloc(size_t); +extern void bkmem_free(void *, size_t); + +/* + * TODO: Replace these declarations with inclusion of the ordinary userland + * bootfs headers once they're available. + */ +typedef struct bfile { + char bf_name[MAXPATHLEN]; + caddr_t bf_addr; + size_t bf_size; + struct bfile *bf_next; + uint64_t bf_ino; +} bfile_t; + +typedef struct bf_fd { + bfile_t *fd_file; + off_t fd_pos; +} bf_fd_t; + +static bfile_t *head; +static uint_t init_done; +static bf_fd_t fds[MAX_FDS]; + +static char cpath[MAXPATHLEN]; /* For canonicalising filenames */ + +static void bbootfs_closeall(int); + +static void +canonicalise(const char *fn, char *out) +{ + const char *p; + char *q, *s; + char *last; + char *oc; + int is_slash = 0; + static char scratch[MAXPATHLEN]; + + if (fn == NULL) { + *out = '\0'; + return; + } + + /* + * Remove leading slashes and condense all multiple slashes into one. + */ + p = fn; + while (*p == '/') + ++p; + + for (q = scratch; *p != '\0'; p++) { + if (*p == '/' && !is_slash) { + *q++ = '/'; + is_slash = 1; + } else if (*p != '/') { + *q++ = *p; + is_slash = 0; + } + } + *q = '\0'; + + if (strncmp(scratch, "system/boot/", 12) == 0 || + strcmp(scratch, "system/boot") == 0) { + s = scratch + 12; + } else { + s = scratch; + } + + for (last = strsep(&s, "/"), q = oc = out; last != NULL; + last = strsep(&s, "/")) { + if (strcmp(last, ".") == 0) + continue; + if (strcmp(last, "..") == 0) { + for (oc = q; oc > out && *oc != '/'; oc--) + ; + q = oc; + continue; + } + if (q > out) + *q++ = '/'; + q += snprintf(q, MAXPATHLEN - (q - out), "%s", last); + } + + *q = '\0'; +} + +/* ARGSUSED */ +static int +bbootfs_mountroot(char *str) +{ + return (-1); +} + +static int +bbootfs_unmountroot(void) +{ + return (-1); +} + +static int +bbootfs_init(void) +{ + bfile_t *fp; + char propname[32]; + uint64_t propval; + uint_t i; + + for (i = 0; i < MAX_FILES; i++) { + (void) snprintf(propname, sizeof (propname), + "module-name-%u", i); + if (do_bsys_getproplen(NULL, propname) < 0) + break; + + if ((fp = bkmem_alloc(sizeof (bfile_t))) == NULL) { + bbootfs_closeall(1); + return (-1); + } + + (void) do_bsys_getprop(NULL, propname, cpath); + canonicalise(cpath, fp->bf_name); + + (void) snprintf(propname, sizeof (propname), + "module-addr-%u", i); + if (do_bsys_getproplen(NULL, propname) != sizeof (uint64_t)) { + bkmem_free(fp, sizeof (bfile_t)); + continue; + } + (void) do_bsys_getprop(NULL, propname, &propval); + fp->bf_addr = (void *)(uintptr_t)propval; + + (void) snprintf(propname, sizeof (propname), + "module-size-%u", i); + if (do_bsys_getproplen(NULL, propname) != sizeof (uint64_t)) { + bkmem_free(fp, sizeof (bfile_t)); + continue; + } + (void) do_bsys_getprop(NULL, propname, &propval); + fp->bf_size = (size_t)propval; + fp->bf_ino = i; + + fp->bf_next = head; + head = fp; + } + + return (0); +} + +/*ARGSUSED*/ +static int +bbootfs_open(char *fn, int flags) +{ + uint_t i; + bfile_t *fp; + + if (!init_done) { + if (bbootfs_init() != 0) + return (-1); + + init_done = 1; + } + + canonicalise(fn, cpath); + + for (fp = head; fp != NULL; fp = fp->bf_next) { + if (strcmp(fp->bf_name, cpath) == 0) + break; + } + + if (fp == NULL) + return (-1); + + for (i = 0; i < MAX_FDS; i++) { + if (fds[i].fd_file == NULL) { + fds[i].fd_file = fp; + fds[i].fd_pos = 0; + return (i); + } + } + + return (-1); +} + +static int +bbootfs_close(int fd) +{ + if (fds[fd].fd_file == NULL) + return (-1); + + fds[fd].fd_file = NULL; + fds[fd].fd_pos = 0; + + return (0); +} + +static ssize_t +bbootfs_read(int fd, caddr_t buf, size_t size) +{ + ssize_t len; + bf_fd_t *fdp = &fds[fd]; + + if (fdp->fd_file == NULL) + return (-1); + + if (fdp->fd_pos >= fdp->fd_file->bf_size) + return (-1); + + if (fdp->fd_pos + size > fdp->fd_file->bf_size) + len = fdp->fd_file->bf_size - fdp->fd_pos; + else + len = size; + + bcopy(fdp->fd_file->bf_addr + fdp->fd_pos, buf, len); + + fdp->fd_pos += len; + + return (len); +} + +static off_t +bbootfs_lseek(int fd, off_t addr, int whence) +{ + bf_fd_t *fdp = &fds[fd]; + + if (fdp->fd_file == NULL) + return (-1); + + switch (whence) { + case SEEK_CUR: + fdp->fd_pos += addr; + break; + case SEEK_SET: + fdp->fd_pos = addr; + break; + case SEEK_END: + fdp->fd_pos = fdp->fd_file->bf_size; + break; + default: + return (-1); + } + + return (0); +} + +static int +bbootfs_fstat(int fd, struct bootstat *bsp) +{ + bf_fd_t *fdp = &fds[fd]; + + if (fdp->fd_file == NULL) + return (-1); + + bsp->st_dev = 1; + bsp->st_ino = fdp->fd_file->bf_ino; + bsp->st_mode = 0444; + bsp->st_nlink = 1; + bsp->st_uid = bsp->st_gid = 0; + bsp->st_rdev = 0; + bsp->st_size = fdp->fd_file->bf_size; + bsp->st_blksize = 1; + bsp->st_blocks = fdp->fd_file->bf_size; + (void) strcpy(bsp->st_fstype, "bootfs"); + + return (0); +} + +/* ARGSUSED */ +static void +bbootfs_closeall(int flag) +{ + bfile_t *fp; + + while (head != NULL) { + fp = head; + head = head->bf_next; + + bkmem_free(fp, sizeof (bfile_t)); + } + + init_done = 0; +} + +struct boot_fs_ops bbootfs_ops = { + "bootfs", + bbootfs_mountroot, + bbootfs_unmountroot, + bbootfs_open, + bbootfs_close, + bbootfs_read, + bbootfs_lseek, + bbootfs_fstat, + bbootfs_closeall, + NULL +}; diff --git a/usr/src/common/util/string.c b/usr/src/common/util/string.c index d54b58d59c..80a076c436 100644 --- a/usr/src/common/util/string.c +++ b/usr/src/common/util/string.c @@ -21,6 +21,7 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2014 Joyent, Inc. All rights reserved. */ /* @@ -264,7 +265,7 @@ next_fmt: if (sign && pad == '0') ADDCHAR('-'); - while (width-- > sign) + while ((!left_align) && (width-- > sign)) ADDCHAR(pad); if (sign && pad == ' ') ADDCHAR('-'); @@ -280,6 +281,10 @@ next_fmt: ADDCHAR(*sp); } + /* add left-alignment padding */ + while (width-- > sign) + ADDCHAR(' '); + if (c == 'b' && ul != 0) { int any = 0; c = *bs++; diff --git a/usr/src/common/util/string.h b/usr/src/common/util/string.h index 052eeab4a4..f7acd734bd 100644 --- a/usr/src/common/util/string.h +++ b/usr/src/common/util/string.h @@ -61,6 +61,7 @@ extern char *strncpy(char *, const char *, size_t); extern char *strrchr(const char *, int c); extern char *strstr(const char *, const char *); extern char *strpbrk(const char *, const char *); +extern char *strsep(char **, const char *); extern char *strncat(char *, const char *, size_t); extern size_t strlcat(char *, const char *, size_t); extern size_t strlcpy(char *, const char *, size_t); diff --git a/usr/src/common/util/strtolctype.h b/usr/src/common/util/strtolctype.h index 5675e42be7..535c014d1f 100644 --- a/usr/src/common/util/strtolctype.h +++ b/usr/src/common/util/strtolctype.h @@ -44,7 +44,7 @@ extern "C" { * safe in probe context. */ -#if defined(_KERNEL) && !defined(_BOOT) +#if defined(_KERNEL) || defined(_BOOT) #define isalnum(ch) (isalpha(ch) || isdigit(ch)) #define isalpha(ch) (isupper(ch) || islower(ch)) @@ -56,7 +56,7 @@ extern "C" { #define isxdigit(ch) (isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \ ((ch) >= 'A' && (ch) <= 'F')) -#endif /* _KERNEL && !_BOOT */ +#endif /* _KERNEL || _BOOT */ #define DIGIT(x) \ (isdigit(x) ? (x) - '0' : islower(x) ? (x) + 10 - 'a' : (x) + 10 - 'A') diff --git a/usr/src/common/zfs/zfs_prop.c b/usr/src/common/zfs/zfs_prop.c index e145b1c866..54aaa027dd 100644 --- a/usr/src/common/zfs/zfs_prop.c +++ b/usr/src/common/zfs/zfs_prop.c @@ -444,6 +444,23 @@ zfs_prop_delegatable(zfs_prop_t prop) return (pd->pd_attr != PROP_READONLY); } +boolean_t +zfs_prop_cacheable(zfs_prop_t prop) +{ + /* + * It'd be nice if each prop had a flags field which could have flag + * like PROP_CACHEABLE, but since zprop_attr_t is an enum and this + * setting is orthogonal to the concepts of PROP_READONLY, etc., we have + * this function. + */ + return (prop == ZFS_PROP_VERSION || + prop == ZFS_PROP_NORMALIZE || + prop == ZFS_PROP_UTF8ONLY || + prop == ZFS_PROP_CASE || + prop == ZFS_PROP_VOLSIZE || + prop == ZFS_PROP_VOLBLOCKSIZE); +} + /* * Given a zfs dataset property name, returns the corresponding property ID. */ diff --git a/usr/src/common/zfs/zfs_prop.h b/usr/src/common/zfs/zfs_prop.h index a63262311b..1796642c68 100644 --- a/usr/src/common/zfs/zfs_prop.h +++ b/usr/src/common/zfs/zfs_prop.h @@ -21,6 +21,7 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ #ifndef _ZFS_PROP_H @@ -86,6 +87,7 @@ typedef struct { void zfs_prop_init(void); zprop_type_t zfs_prop_get_type(zfs_prop_t); boolean_t zfs_prop_delegatable(zfs_prop_t prop); +boolean_t zfs_prop_cacheable(zfs_prop_t prop); zprop_desc_t *zfs_prop_get_table(void); /* |
