uu_misc.c revision 219089
1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5168404Spjd * Common Development and Distribution License (the "License"). 6168404Spjd * You may not use this file except in compliance with the License. 7168404Spjd * 8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168404Spjd * or http://www.opensolaris.org/os/licensing. 10168404Spjd * See the License for the specific language governing permissions 11168404Spjd * and limitations under the License. 12168404Spjd * 13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168404Spjd * If applicable, add the following below this CDDL HEADER, with the 16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18168404Spjd * 19168404Spjd * CDDL HEADER END 20168404Spjd */ 21168404Spjd 22168404Spjd/* 23219089Spjd * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 24168404Spjd */ 25168404Spjd 26168404Spjd#include "libuutil_common.h" 27168404Spjd 28168404Spjd#include <assert.h> 29168404Spjd#include <errno.h> 30168404Spjd#include <libintl.h> 31168404Spjd#include <pthread.h> 32168404Spjd#include <stdarg.h> 33168404Spjd#include <stdio.h> 34168404Spjd#include <stdlib.h> 35168404Spjd#include <string.h> 36168404Spjd#include <sys/debug.h> 37168404Spjd#include <thread.h> 38168404Spjd#include <unistd.h> 39219089Spjd#include <ctype.h> 40168404Spjd 41168404Spjd#if !defined(TEXT_DOMAIN) 42168404Spjd#define TEXT_DOMAIN "SYS_TEST" 43168404Spjd#endif 44168404Spjd 45168404Spjd/* 46168404Spjd * All of the old code under !defined(PTHREAD_ONCE_KEY_NP) 47168404Spjd * is here to enable the building of a native version of 48168404Spjd * libuutil.so when the build machine has not yet been upgraded 49168404Spjd * to a version of libc that provides pthread_key_create_once_np(). 50168404Spjd * It should all be deleted when solaris_nevada ships. 51168404Spjd * The code is not MT-safe in a relaxed memory model. 52168404Spjd */ 53168404Spjd 54168404Spjd#if defined(PTHREAD_ONCE_KEY_NP) 55168404Spjdstatic pthread_key_t uu_error_key = PTHREAD_ONCE_KEY_NP; 56168404Spjd#else /* PTHREAD_ONCE_KEY_NP */ 57168404Spjdstatic pthread_key_t uu_error_key = 0; 58168404Spjdstatic pthread_mutex_t uu_key_lock = PTHREAD_MUTEX_INITIALIZER; 59168404Spjd#endif /* PTHREAD_ONCE_KEY_NP */ 60168404Spjd 61168404Spjdstatic int uu_error_key_setup = 0; 62168404Spjd 63168404Spjdstatic pthread_mutex_t uu_panic_lock = PTHREAD_MUTEX_INITIALIZER; 64168404Spjd/* LINTED static unused */ 65168404Spjdstatic const char *uu_panic_format; 66168404Spjd/* LINTED static unused */ 67168404Spjdstatic va_list uu_panic_args; 68168404Spjdstatic pthread_t uu_panic_thread; 69168404Spjd 70168404Spjdstatic uint32_t _uu_main_error; 71168404Spjd 72168404Spjdvoid 73168404Spjduu_set_error(uint_t code) 74168404Spjd{ 75168404Spjd 76168404Spjd#if defined(PTHREAD_ONCE_KEY_NP) 77168404Spjd if (pthread_key_create_once_np(&uu_error_key, NULL) != 0) 78168404Spjd uu_error_key_setup = -1; 79168404Spjd else 80168404Spjd uu_error_key_setup = 1; 81168404Spjd#else /* PTHREAD_ONCE_KEY_NP */ 82168404Spjd if (uu_error_key_setup == 0) { 83168404Spjd (void) pthread_mutex_lock(&uu_key_lock); 84168404Spjd if (uu_error_key_setup == 0) { 85168404Spjd if (pthread_key_create(&uu_error_key, NULL) != 0) 86168404Spjd uu_error_key_setup = -1; 87168404Spjd else 88168404Spjd uu_error_key_setup = 1; 89168404Spjd } 90168404Spjd (void) pthread_mutex_unlock(&uu_key_lock); 91168404Spjd } 92168404Spjd#endif /* PTHREAD_ONCE_KEY_NP */ 93168404Spjd if (uu_error_key_setup > 0) 94168404Spjd (void) pthread_setspecific(uu_error_key, 95168404Spjd (void *)(uintptr_t)code); 96168404Spjd} 97168404Spjd 98168404Spjduint32_t 99168404Spjduu_error(void) 100168404Spjd{ 101168404Spjd 102168404Spjd if (uu_error_key_setup < 0) /* can't happen? */ 103168404Spjd return (UU_ERROR_UNKNOWN); 104168404Spjd 105168404Spjd /* 106168404Spjd * Because UU_ERROR_NONE == 0, if uu_set_error() was 107168404Spjd * never called, then this will return UU_ERROR_NONE: 108168404Spjd */ 109168404Spjd return ((uint32_t)(uintptr_t)pthread_getspecific(uu_error_key)); 110168404Spjd} 111168404Spjd 112168404Spjdconst char * 113168404Spjduu_strerror(uint32_t code) 114168404Spjd{ 115168404Spjd const char *str; 116168404Spjd 117168404Spjd switch (code) { 118168404Spjd case UU_ERROR_NONE: 119168404Spjd str = dgettext(TEXT_DOMAIN, "No error"); 120168404Spjd break; 121168404Spjd 122168404Spjd case UU_ERROR_INVALID_ARGUMENT: 123168404Spjd str = dgettext(TEXT_DOMAIN, "Invalid argument"); 124168404Spjd break; 125168404Spjd 126168404Spjd case UU_ERROR_UNKNOWN_FLAG: 127168404Spjd str = dgettext(TEXT_DOMAIN, "Unknown flag passed"); 128168404Spjd break; 129168404Spjd 130168404Spjd case UU_ERROR_NO_MEMORY: 131168404Spjd str = dgettext(TEXT_DOMAIN, "Out of memory"); 132168404Spjd break; 133168404Spjd 134168404Spjd case UU_ERROR_CALLBACK_FAILED: 135168404Spjd str = dgettext(TEXT_DOMAIN, "Callback-initiated failure"); 136168404Spjd break; 137168404Spjd 138168404Spjd case UU_ERROR_NOT_SUPPORTED: 139168404Spjd str = dgettext(TEXT_DOMAIN, "Operation not supported"); 140168404Spjd break; 141168404Spjd 142168404Spjd case UU_ERROR_EMPTY: 143168404Spjd str = dgettext(TEXT_DOMAIN, "No value provided"); 144168404Spjd break; 145168404Spjd 146168404Spjd case UU_ERROR_UNDERFLOW: 147168404Spjd str = dgettext(TEXT_DOMAIN, "Value too small"); 148168404Spjd break; 149168404Spjd 150168404Spjd case UU_ERROR_OVERFLOW: 151168404Spjd str = dgettext(TEXT_DOMAIN, "Value too large"); 152168404Spjd break; 153168404Spjd 154168404Spjd case UU_ERROR_INVALID_CHAR: 155168404Spjd str = dgettext(TEXT_DOMAIN, 156168404Spjd "Value contains unexpected character"); 157168404Spjd break; 158168404Spjd 159168404Spjd case UU_ERROR_INVALID_DIGIT: 160168404Spjd str = dgettext(TEXT_DOMAIN, 161168404Spjd "Value contains digit not in base"); 162168404Spjd break; 163168404Spjd 164168404Spjd case UU_ERROR_SYSTEM: 165168404Spjd str = dgettext(TEXT_DOMAIN, "Underlying system error"); 166168404Spjd break; 167168404Spjd 168168404Spjd case UU_ERROR_UNKNOWN: 169168404Spjd str = dgettext(TEXT_DOMAIN, "Error status not known"); 170168404Spjd break; 171168404Spjd 172168404Spjd default: 173168404Spjd errno = ESRCH; 174168404Spjd str = NULL; 175168404Spjd break; 176168404Spjd } 177168404Spjd return (str); 178168404Spjd} 179168404Spjd 180168404Spjdvoid 181168404Spjduu_panic(const char *format, ...) 182168404Spjd{ 183168404Spjd va_list args; 184168404Spjd 185168404Spjd va_start(args, format); 186168404Spjd 187168404Spjd (void) pthread_mutex_lock(&uu_panic_lock); 188168404Spjd if (uu_panic_thread == 0) { 189168404Spjd uu_panic_thread = pthread_self(); 190168404Spjd uu_panic_format = format; 191168404Spjd va_copy(uu_panic_args, args); 192168404Spjd } 193168404Spjd (void) pthread_mutex_unlock(&uu_panic_lock); 194168404Spjd 195168404Spjd (void) vfprintf(stderr, format, args); 196168404Spjd 197168404Spjd if (uu_panic_thread == pthread_self()) 198168404Spjd abort(); 199168404Spjd else 200168404Spjd for (;;) 201168404Spjd (void) pause(); 202168404Spjd} 203168404Spjd 204168404Spjdint 205168404Spjdassfail(const char *astring, const char *file, int line) 206168404Spjd{ 207168404Spjd __assert(astring, file, line); 208168404Spjd /*NOTREACHED*/ 209168404Spjd return (0); 210168404Spjd} 211168404Spjd 212168404Spjdstatic void 213168404Spjduu_lockup(void) 214168404Spjd{ 215168404Spjd (void) pthread_mutex_lock(&uu_panic_lock); 216168404Spjd#if !defined(PTHREAD_ONCE_KEY_NP) 217168404Spjd (void) pthread_mutex_lock(&uu_key_lock); 218168404Spjd#endif 219168404Spjd uu_avl_lockup(); 220168404Spjd uu_list_lockup(); 221168404Spjd} 222168404Spjd 223168404Spjdstatic void 224168404Spjduu_release(void) 225168404Spjd{ 226168404Spjd (void) pthread_mutex_unlock(&uu_panic_lock); 227168404Spjd#if !defined(PTHREAD_ONCE_KEY_NP) 228168404Spjd (void) pthread_mutex_unlock(&uu_key_lock); 229168404Spjd#endif 230168404Spjd uu_avl_release(); 231168404Spjd uu_list_release(); 232168404Spjd} 233168404Spjd 234168404Spjdstatic void 235168404Spjduu_release_child(void) 236168404Spjd{ 237168404Spjd uu_panic_format = NULL; 238168404Spjd uu_panic_thread = 0; 239168404Spjd 240168404Spjd uu_release(); 241168404Spjd} 242168404Spjd 243168404Spjd#pragma init(uu_init) 244168404Spjdstatic void 245168404Spjduu_init(void) 246168404Spjd{ 247168404Spjd (void) pthread_atfork(uu_lockup, uu_release, uu_release_child); 248168404Spjd} 249219089Spjd 250219089Spjd/* 251219089Spjd * Dump a block of memory in hex+ascii, for debugging 252219089Spjd */ 253219089Spjdvoid 254219089Spjduu_dump(FILE *out, const char *prefix, const void *buf, size_t len) 255219089Spjd{ 256219089Spjd const unsigned char *p = buf; 257219089Spjd int i; 258219089Spjd 259219089Spjd for (i = 0; i < len; i += 16) { 260219089Spjd int j; 261219089Spjd 262219089Spjd (void) fprintf(out, "%s", prefix); 263219089Spjd for (j = 0; j < 16 && i + j < len; j++) { 264219089Spjd (void) fprintf(out, "%2.2x ", p[i + j]); 265219089Spjd } 266219089Spjd for (; j < 16; j++) { 267219089Spjd (void) fprintf(out, " "); 268219089Spjd } 269219089Spjd for (j = 0; j < 16 && i + j < len; j++) { 270219089Spjd (void) fprintf(out, "%c", 271219089Spjd isprint(p[i + j]) ? p[i + j] : '.'); 272219089Spjd } 273219089Spjd (void) fprintf(out, "\n"); 274219089Spjd } 275219089Spjd} 276