uu_misc.c revision 240415
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 28240415Smm#define HAVE_ASSFAIL 1 29240415Smm 30168404Spjd#include <assert.h> 31168404Spjd#include <errno.h> 32168404Spjd#include <libintl.h> 33168404Spjd#include <pthread.h> 34168404Spjd#include <stdarg.h> 35168404Spjd#include <stdio.h> 36168404Spjd#include <stdlib.h> 37168404Spjd#include <string.h> 38168404Spjd#include <sys/debug.h> 39168404Spjd#include <thread.h> 40168404Spjd#include <unistd.h> 41219089Spjd#include <ctype.h> 42168404Spjd 43168404Spjd#if !defined(TEXT_DOMAIN) 44168404Spjd#define TEXT_DOMAIN "SYS_TEST" 45168404Spjd#endif 46168404Spjd 47168404Spjd/* 48168404Spjd * All of the old code under !defined(PTHREAD_ONCE_KEY_NP) 49168404Spjd * is here to enable the building of a native version of 50168404Spjd * libuutil.so when the build machine has not yet been upgraded 51168404Spjd * to a version of libc that provides pthread_key_create_once_np(). 52168404Spjd * It should all be deleted when solaris_nevada ships. 53168404Spjd * The code is not MT-safe in a relaxed memory model. 54168404Spjd */ 55168404Spjd 56168404Spjd#if defined(PTHREAD_ONCE_KEY_NP) 57168404Spjdstatic pthread_key_t uu_error_key = PTHREAD_ONCE_KEY_NP; 58168404Spjd#else /* PTHREAD_ONCE_KEY_NP */ 59168404Spjdstatic pthread_key_t uu_error_key = 0; 60168404Spjdstatic pthread_mutex_t uu_key_lock = PTHREAD_MUTEX_INITIALIZER; 61168404Spjd#endif /* PTHREAD_ONCE_KEY_NP */ 62168404Spjd 63168404Spjdstatic int uu_error_key_setup = 0; 64168404Spjd 65168404Spjdstatic pthread_mutex_t uu_panic_lock = PTHREAD_MUTEX_INITIALIZER; 66168404Spjd/* LINTED static unused */ 67168404Spjdstatic const char *uu_panic_format; 68168404Spjd/* LINTED static unused */ 69168404Spjdstatic va_list uu_panic_args; 70168404Spjdstatic pthread_t uu_panic_thread; 71168404Spjd 72168404Spjdstatic uint32_t _uu_main_error; 73168404Spjd 74168404Spjdvoid 75168404Spjduu_set_error(uint_t code) 76168404Spjd{ 77168404Spjd 78168404Spjd#if defined(PTHREAD_ONCE_KEY_NP) 79168404Spjd if (pthread_key_create_once_np(&uu_error_key, NULL) != 0) 80168404Spjd uu_error_key_setup = -1; 81168404Spjd else 82168404Spjd uu_error_key_setup = 1; 83168404Spjd#else /* PTHREAD_ONCE_KEY_NP */ 84168404Spjd if (uu_error_key_setup == 0) { 85168404Spjd (void) pthread_mutex_lock(&uu_key_lock); 86168404Spjd if (uu_error_key_setup == 0) { 87168404Spjd if (pthread_key_create(&uu_error_key, NULL) != 0) 88168404Spjd uu_error_key_setup = -1; 89168404Spjd else 90168404Spjd uu_error_key_setup = 1; 91168404Spjd } 92168404Spjd (void) pthread_mutex_unlock(&uu_key_lock); 93168404Spjd } 94168404Spjd#endif /* PTHREAD_ONCE_KEY_NP */ 95168404Spjd if (uu_error_key_setup > 0) 96168404Spjd (void) pthread_setspecific(uu_error_key, 97168404Spjd (void *)(uintptr_t)code); 98168404Spjd} 99168404Spjd 100168404Spjduint32_t 101168404Spjduu_error(void) 102168404Spjd{ 103168404Spjd 104168404Spjd if (uu_error_key_setup < 0) /* can't happen? */ 105168404Spjd return (UU_ERROR_UNKNOWN); 106168404Spjd 107168404Spjd /* 108168404Spjd * Because UU_ERROR_NONE == 0, if uu_set_error() was 109168404Spjd * never called, then this will return UU_ERROR_NONE: 110168404Spjd */ 111168404Spjd return ((uint32_t)(uintptr_t)pthread_getspecific(uu_error_key)); 112168404Spjd} 113168404Spjd 114168404Spjdconst char * 115168404Spjduu_strerror(uint32_t code) 116168404Spjd{ 117168404Spjd const char *str; 118168404Spjd 119168404Spjd switch (code) { 120168404Spjd case UU_ERROR_NONE: 121168404Spjd str = dgettext(TEXT_DOMAIN, "No error"); 122168404Spjd break; 123168404Spjd 124168404Spjd case UU_ERROR_INVALID_ARGUMENT: 125168404Spjd str = dgettext(TEXT_DOMAIN, "Invalid argument"); 126168404Spjd break; 127168404Spjd 128168404Spjd case UU_ERROR_UNKNOWN_FLAG: 129168404Spjd str = dgettext(TEXT_DOMAIN, "Unknown flag passed"); 130168404Spjd break; 131168404Spjd 132168404Spjd case UU_ERROR_NO_MEMORY: 133168404Spjd str = dgettext(TEXT_DOMAIN, "Out of memory"); 134168404Spjd break; 135168404Spjd 136168404Spjd case UU_ERROR_CALLBACK_FAILED: 137168404Spjd str = dgettext(TEXT_DOMAIN, "Callback-initiated failure"); 138168404Spjd break; 139168404Spjd 140168404Spjd case UU_ERROR_NOT_SUPPORTED: 141168404Spjd str = dgettext(TEXT_DOMAIN, "Operation not supported"); 142168404Spjd break; 143168404Spjd 144168404Spjd case UU_ERROR_EMPTY: 145168404Spjd str = dgettext(TEXT_DOMAIN, "No value provided"); 146168404Spjd break; 147168404Spjd 148168404Spjd case UU_ERROR_UNDERFLOW: 149168404Spjd str = dgettext(TEXT_DOMAIN, "Value too small"); 150168404Spjd break; 151168404Spjd 152168404Spjd case UU_ERROR_OVERFLOW: 153168404Spjd str = dgettext(TEXT_DOMAIN, "Value too large"); 154168404Spjd break; 155168404Spjd 156168404Spjd case UU_ERROR_INVALID_CHAR: 157168404Spjd str = dgettext(TEXT_DOMAIN, 158168404Spjd "Value contains unexpected character"); 159168404Spjd break; 160168404Spjd 161168404Spjd case UU_ERROR_INVALID_DIGIT: 162168404Spjd str = dgettext(TEXT_DOMAIN, 163168404Spjd "Value contains digit not in base"); 164168404Spjd break; 165168404Spjd 166168404Spjd case UU_ERROR_SYSTEM: 167168404Spjd str = dgettext(TEXT_DOMAIN, "Underlying system error"); 168168404Spjd break; 169168404Spjd 170168404Spjd case UU_ERROR_UNKNOWN: 171168404Spjd str = dgettext(TEXT_DOMAIN, "Error status not known"); 172168404Spjd break; 173168404Spjd 174168404Spjd default: 175168404Spjd errno = ESRCH; 176168404Spjd str = NULL; 177168404Spjd break; 178168404Spjd } 179168404Spjd return (str); 180168404Spjd} 181168404Spjd 182168404Spjdvoid 183168404Spjduu_panic(const char *format, ...) 184168404Spjd{ 185168404Spjd va_list args; 186168404Spjd 187168404Spjd va_start(args, format); 188168404Spjd 189168404Spjd (void) pthread_mutex_lock(&uu_panic_lock); 190168404Spjd if (uu_panic_thread == 0) { 191168404Spjd uu_panic_thread = pthread_self(); 192168404Spjd uu_panic_format = format; 193168404Spjd va_copy(uu_panic_args, args); 194168404Spjd } 195168404Spjd (void) pthread_mutex_unlock(&uu_panic_lock); 196168404Spjd 197168404Spjd (void) vfprintf(stderr, format, args); 198168404Spjd 199168404Spjd if (uu_panic_thread == pthread_self()) 200168404Spjd abort(); 201168404Spjd else 202168404Spjd for (;;) 203168404Spjd (void) pause(); 204168404Spjd} 205168404Spjd 206168404Spjdint 207168404Spjdassfail(const char *astring, const char *file, int line) 208168404Spjd{ 209168404Spjd __assert(astring, file, line); 210168404Spjd /*NOTREACHED*/ 211168404Spjd return (0); 212168404Spjd} 213168404Spjd 214168404Spjdstatic void 215168404Spjduu_lockup(void) 216168404Spjd{ 217168404Spjd (void) pthread_mutex_lock(&uu_panic_lock); 218168404Spjd#if !defined(PTHREAD_ONCE_KEY_NP) 219168404Spjd (void) pthread_mutex_lock(&uu_key_lock); 220168404Spjd#endif 221168404Spjd uu_avl_lockup(); 222168404Spjd uu_list_lockup(); 223168404Spjd} 224168404Spjd 225168404Spjdstatic void 226168404Spjduu_release(void) 227168404Spjd{ 228168404Spjd (void) pthread_mutex_unlock(&uu_panic_lock); 229168404Spjd#if !defined(PTHREAD_ONCE_KEY_NP) 230168404Spjd (void) pthread_mutex_unlock(&uu_key_lock); 231168404Spjd#endif 232168404Spjd uu_avl_release(); 233168404Spjd uu_list_release(); 234168404Spjd} 235168404Spjd 236168404Spjdstatic void 237168404Spjduu_release_child(void) 238168404Spjd{ 239168404Spjd uu_panic_format = NULL; 240168404Spjd uu_panic_thread = 0; 241168404Spjd 242168404Spjd uu_release(); 243168404Spjd} 244168404Spjd 245168404Spjd#pragma init(uu_init) 246168404Spjdstatic void 247168404Spjduu_init(void) 248168404Spjd{ 249168404Spjd (void) pthread_atfork(uu_lockup, uu_release, uu_release_child); 250168404Spjd} 251219089Spjd 252219089Spjd/* 253219089Spjd * Dump a block of memory in hex+ascii, for debugging 254219089Spjd */ 255219089Spjdvoid 256219089Spjduu_dump(FILE *out, const char *prefix, const void *buf, size_t len) 257219089Spjd{ 258219089Spjd const unsigned char *p = buf; 259219089Spjd int i; 260219089Spjd 261219089Spjd for (i = 0; i < len; i += 16) { 262219089Spjd int j; 263219089Spjd 264219089Spjd (void) fprintf(out, "%s", prefix); 265219089Spjd for (j = 0; j < 16 && i + j < len; j++) { 266219089Spjd (void) fprintf(out, "%2.2x ", p[i + j]); 267219089Spjd } 268219089Spjd for (; j < 16; j++) { 269219089Spjd (void) fprintf(out, " "); 270219089Spjd } 271219089Spjd for (j = 0; j < 16 && i + j < len; j++) { 272219089Spjd (void) fprintf(out, "%c", 273219089Spjd isprint(p[i + j]) ? p[i + j] : '.'); 274219089Spjd } 275219089Spjd (void) fprintf(out, "\n"); 276219089Spjd } 277219089Spjd} 278