1*ac88567aSHyon Kim /* 2*ac88567aSHyon Kim * CDDL HEADER START 3*ac88567aSHyon Kim * 4*ac88567aSHyon Kim * The contents of this file are subject to the terms of the 5*ac88567aSHyon Kim * Common Development and Distribution License (the "License"). 6*ac88567aSHyon Kim * You may not use this file except in compliance with the License. 7*ac88567aSHyon Kim * 8*ac88567aSHyon Kim * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*ac88567aSHyon Kim * or http://www.opensolaris.org/os/licensing. 10*ac88567aSHyon Kim * See the License for the specific language governing permissions 11*ac88567aSHyon Kim * and limitations under the License. 12*ac88567aSHyon Kim * 13*ac88567aSHyon Kim * When distributing Covered Code, include this CDDL HEADER in each 14*ac88567aSHyon Kim * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*ac88567aSHyon Kim * If applicable, add the following below this CDDL HEADER, with the 16*ac88567aSHyon Kim * fields enclosed by brackets "[]" replaced with your own identifying 17*ac88567aSHyon Kim * information: Portions Copyright [yyyy] [name of copyright owner] 18*ac88567aSHyon Kim * 19*ac88567aSHyon Kim * CDDL HEADER END 20*ac88567aSHyon Kim */ 21*ac88567aSHyon Kim 22*ac88567aSHyon Kim /* 23*ac88567aSHyon Kim * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 24*ac88567aSHyon Kim */ 25*ac88567aSHyon Kim 26*ac88567aSHyon Kim #include <sys/types.h> 27*ac88567aSHyon Kim 28*ac88567aSHyon Kim #include <stddef.h> 29*ac88567aSHyon Kim #include <stdlib.h> 30*ac88567aSHyon Kim #include <string.h> 31*ac88567aSHyon Kim #include <strings.h> 32*ac88567aSHyon Kim #include <alloca.h> 33*ac88567aSHyon Kim #include <stdio.h> 34*ac88567aSHyon Kim #include <unistd.h> 35*ac88567aSHyon Kim #include <dlfcn.h> 36*ac88567aSHyon Kim #include <thread.h> 37*ac88567aSHyon Kim #include <pthread.h> 38*ac88567aSHyon Kim #include <ctype.h> 39*ac88567aSHyon Kim 40*ac88567aSHyon Kim #include <scsi/libsmp.h> 41*ac88567aSHyon Kim #include <scsi/libsmp_plugin.h> 42*ac88567aSHyon Kim #include "smp_impl.h" 43*ac88567aSHyon Kim 44*ac88567aSHyon Kim __thread smp_errno_t _smp_errno; 45*ac88567aSHyon Kim __thread char _smp_errmsg[LIBSMP_ERRMSGLEN]; 46*ac88567aSHyon Kim 47*ac88567aSHyon Kim int 48*ac88567aSHyon Kim smp_assert(const char *expr, const char *file, int line) 49*ac88567aSHyon Kim { 50*ac88567aSHyon Kim char *msg; 51*ac88567aSHyon Kim size_t len; 52*ac88567aSHyon Kim 53*ac88567aSHyon Kim len = snprintf(NULL, 0, 54*ac88567aSHyon Kim "ABORT: \"%s\", line %d: assertion failed: %s\n", file, line, expr); 55*ac88567aSHyon Kim 56*ac88567aSHyon Kim msg = alloca(len + 1); 57*ac88567aSHyon Kim 58*ac88567aSHyon Kim (void) snprintf(msg, len + 1, 59*ac88567aSHyon Kim "ABORT: \"%s\", line %d: assertion failed: %s\n", file, line, expr); 60*ac88567aSHyon Kim 61*ac88567aSHyon Kim (void) write(STDERR_FILENO, msg, strlen(msg)); 62*ac88567aSHyon Kim 63*ac88567aSHyon Kim abort(); 64*ac88567aSHyon Kim _exit(1); 65*ac88567aSHyon Kim 66*ac88567aSHyon Kim /*NOTREACHED*/ 67*ac88567aSHyon Kim return (0); 68*ac88567aSHyon Kim } 69*ac88567aSHyon Kim 70*ac88567aSHyon Kim int 71*ac88567aSHyon Kim smp_set_errno(smp_errno_t err) 72*ac88567aSHyon Kim { 73*ac88567aSHyon Kim _smp_errno = err; 74*ac88567aSHyon Kim _smp_errmsg[0] = '\0'; 75*ac88567aSHyon Kim 76*ac88567aSHyon Kim return (-1); 77*ac88567aSHyon Kim } 78*ac88567aSHyon Kim 79*ac88567aSHyon Kim /* 80*ac88567aSHyon Kim * Internal routine for setting both _smp_errno and _smp_errmsg. We save 81*ac88567aSHyon Kim * and restore the UNIX errno across this routing so the caller can use either 82*ac88567aSHyon Kim * smp_set_errno(), smp_error(), or smp_verror() without this value changing. 83*ac88567aSHyon Kim */ 84*ac88567aSHyon Kim int 85*ac88567aSHyon Kim smp_verror(smp_errno_t err, const char *fmt, va_list ap) 86*ac88567aSHyon Kim { 87*ac88567aSHyon Kim size_t n; 88*ac88567aSHyon Kim char *errmsg; 89*ac88567aSHyon Kim 90*ac88567aSHyon Kim /* 91*ac88567aSHyon Kim * To allow the existing error message to itself be used in an error 92*ac88567aSHyon Kim * message, we put the new error message into a buffer on the stack, 93*ac88567aSHyon Kim * and then copy it into lsh_errmsg. We also need to set the errno, 94*ac88567aSHyon Kim * but because the call to smp_set_errno() is destructive to 95*ac88567aSHyon Kim * lsh_errmsg, we do this after we print into our temporary buffer 96*ac88567aSHyon Kim * (in case _smp_errmsg is part of the error message) and before we 97*ac88567aSHyon Kim * copy the temporary buffer on to _smp_errmsg (to prevent our new 98*ac88567aSHyon Kim * message from being nuked by the call to smp_set_errno()). 99*ac88567aSHyon Kim */ 100*ac88567aSHyon Kim errmsg = alloca(sizeof (_smp_errmsg)); 101*ac88567aSHyon Kim (void) vsnprintf(errmsg, sizeof (_smp_errmsg), fmt, ap); 102*ac88567aSHyon Kim (void) smp_set_errno(err); 103*ac88567aSHyon Kim 104*ac88567aSHyon Kim n = strlen(errmsg); 105*ac88567aSHyon Kim 106*ac88567aSHyon Kim if (n != 0 && errmsg[n - 1] == '\n') 107*ac88567aSHyon Kim errmsg[n - 1] = '\0'; 108*ac88567aSHyon Kim 109*ac88567aSHyon Kim bcopy(errmsg, _smp_errmsg, n + 1); 110*ac88567aSHyon Kim 111*ac88567aSHyon Kim return (-1); 112*ac88567aSHyon Kim } 113*ac88567aSHyon Kim 114*ac88567aSHyon Kim int 115*ac88567aSHyon Kim smp_error(smp_errno_t err, const char *fmt, ...) 116*ac88567aSHyon Kim { 117*ac88567aSHyon Kim va_list ap; 118*ac88567aSHyon Kim 119*ac88567aSHyon Kim if (fmt == NULL) 120*ac88567aSHyon Kim return (smp_set_errno(err)); 121*ac88567aSHyon Kim 122*ac88567aSHyon Kim va_start(ap, fmt); 123*ac88567aSHyon Kim err = smp_verror(err, fmt, ap); 124*ac88567aSHyon Kim va_end(ap); 125*ac88567aSHyon Kim 126*ac88567aSHyon Kim return (err); 127*ac88567aSHyon Kim } 128*ac88567aSHyon Kim 129*ac88567aSHyon Kim smp_errno_t 130*ac88567aSHyon Kim smp_errno(void) 131*ac88567aSHyon Kim { 132*ac88567aSHyon Kim return (_smp_errno); 133*ac88567aSHyon Kim } 134*ac88567aSHyon Kim 135*ac88567aSHyon Kim const char * 136*ac88567aSHyon Kim smp_errmsg(void) 137*ac88567aSHyon Kim { 138*ac88567aSHyon Kim if (_smp_errmsg[0] == '\0') 139*ac88567aSHyon Kim (void) strlcpy(_smp_errmsg, smp_strerror(_smp_errno), 140*ac88567aSHyon Kim sizeof (_smp_errmsg)); 141*ac88567aSHyon Kim 142*ac88567aSHyon Kim return (_smp_errmsg); 143*ac88567aSHyon Kim } 144*ac88567aSHyon Kim 145*ac88567aSHyon Kim /*ARGSUSED*/ 146*ac88567aSHyon Kim void * 147*ac88567aSHyon Kim smp_alloc(size_t size) 148*ac88567aSHyon Kim { 149*ac88567aSHyon Kim void *mem; 150*ac88567aSHyon Kim 151*ac88567aSHyon Kim if (size == 0) { 152*ac88567aSHyon Kim (void) smp_set_errno(ESMP_ZERO_LENGTH); 153*ac88567aSHyon Kim return (NULL); 154*ac88567aSHyon Kim } 155*ac88567aSHyon Kim 156*ac88567aSHyon Kim if ((mem = malloc(size)) == NULL) 157*ac88567aSHyon Kim (void) smp_set_errno(ESMP_NOMEM); 158*ac88567aSHyon Kim 159*ac88567aSHyon Kim return (mem); 160*ac88567aSHyon Kim } 161*ac88567aSHyon Kim 162*ac88567aSHyon Kim void * 163*ac88567aSHyon Kim smp_zalloc(size_t size) 164*ac88567aSHyon Kim { 165*ac88567aSHyon Kim void *mem; 166*ac88567aSHyon Kim 167*ac88567aSHyon Kim if ((mem = smp_alloc(size)) == NULL) 168*ac88567aSHyon Kim return (NULL); 169*ac88567aSHyon Kim 170*ac88567aSHyon Kim bzero(mem, size); 171*ac88567aSHyon Kim 172*ac88567aSHyon Kim return (mem); 173*ac88567aSHyon Kim } 174*ac88567aSHyon Kim 175*ac88567aSHyon Kim char * 176*ac88567aSHyon Kim smp_strdup(const char *str) 177*ac88567aSHyon Kim { 178*ac88567aSHyon Kim size_t len = strlen(str); 179*ac88567aSHyon Kim char *dup = smp_alloc(len + 1); 180*ac88567aSHyon Kim 181*ac88567aSHyon Kim if (dup == NULL) 182*ac88567aSHyon Kim return (NULL); 183*ac88567aSHyon Kim 184*ac88567aSHyon Kim return (strcpy(dup, str)); 185*ac88567aSHyon Kim } 186*ac88567aSHyon Kim 187*ac88567aSHyon Kim void 188*ac88567aSHyon Kim smp_free(void *ptr) 189*ac88567aSHyon Kim { 190*ac88567aSHyon Kim free(ptr); 191*ac88567aSHyon Kim } 192*ac88567aSHyon Kim 193*ac88567aSHyon Kim /* 194*ac88567aSHyon Kim * Trim any leading and/or trailing spaces from the fixed-length string 195*ac88567aSHyon Kim * argument and return a newly-allocated copy of it. 196*ac88567aSHyon Kim */ 197*ac88567aSHyon Kim char * 198*ac88567aSHyon Kim smp_trim_strdup(const char *str, size_t len) 199*ac88567aSHyon Kim { 200*ac88567aSHyon Kim const char *p; 201*ac88567aSHyon Kim char *r; 202*ac88567aSHyon Kim 203*ac88567aSHyon Kim for (p = str; p - str < len && isspace(*p); p++) 204*ac88567aSHyon Kim ; 205*ac88567aSHyon Kim 206*ac88567aSHyon Kim len -= (p - str); 207*ac88567aSHyon Kim 208*ac88567aSHyon Kim if (len == 0) 209*ac88567aSHyon Kim return (NULL); 210*ac88567aSHyon Kim 211*ac88567aSHyon Kim for (str = p + len - 1; str > p && isspace(*str); str--, len--) 212*ac88567aSHyon Kim ; 213*ac88567aSHyon Kim 214*ac88567aSHyon Kim if (len == 0) 215*ac88567aSHyon Kim return (NULL); 216*ac88567aSHyon Kim 217*ac88567aSHyon Kim r = smp_alloc(len + 1); 218*ac88567aSHyon Kim if (r == NULL) 219*ac88567aSHyon Kim return (NULL); 220*ac88567aSHyon Kim 221*ac88567aSHyon Kim bcopy(p, r, len); 222*ac88567aSHyon Kim r[len] = '\0'; 223*ac88567aSHyon Kim 224*ac88567aSHyon Kim return (r); 225*ac88567aSHyon Kim } 226*ac88567aSHyon Kim 227*ac88567aSHyon Kim int 228*ac88567aSHyon Kim smp_init(int version) 229*ac88567aSHyon Kim { 230*ac88567aSHyon Kim if (version != LIBSMP_VERSION) 231*ac88567aSHyon Kim return (smp_error(ESMP_VERSION, 232*ac88567aSHyon Kim "library version %d does not match requested version %d", 233*ac88567aSHyon Kim LIBSMP_VERSION, version)); 234*ac88567aSHyon Kim 235*ac88567aSHyon Kim smp_engine_init(); 236*ac88567aSHyon Kim 237*ac88567aSHyon Kim return (0); 238*ac88567aSHyon Kim } 239*ac88567aSHyon Kim 240*ac88567aSHyon Kim void 241*ac88567aSHyon Kim smp_fini(void) 242*ac88567aSHyon Kim { 243*ac88567aSHyon Kim smp_engine_fini(); 244*ac88567aSHyon Kim } 245