mirror of
				https://git.proxmox.com/git/mirror_zfs
				synced 2025-11-04 03:00:20 +00:00 
			
		
		
		
	The commit replaces all findings of the link: http://www.opensolaris.org/os/licensing with this one: https://opensource.org/licenses/CDDL-1.0 Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Tino Reichardt <milky-zfs@mcmilk.de> Closes #13619
		
			
				
	
	
		
			255 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			255 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * 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 https://opensource.org/licenses/CDDL-1.0.
 | 
						|
 * 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 (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
 | 
						|
 */
 | 
						|
 | 
						|
#include "libuutil_common.h"
 | 
						|
 | 
						|
#include <assert.h>
 | 
						|
#include <errno.h>
 | 
						|
#include <libintl.h>
 | 
						|
#include <pthread.h>
 | 
						|
#include <stdarg.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include <sys/debug.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <ctype.h>
 | 
						|
 | 
						|
#if !defined(TEXT_DOMAIN)
 | 
						|
#define	TEXT_DOMAIN "SYS_TEST"
 | 
						|
#endif
 | 
						|
 | 
						|
/*
 | 
						|
 * All of the old code under !defined(PTHREAD_ONCE_KEY_NP)
 | 
						|
 * is here to enable the building of a native version of
 | 
						|
 * libuutil.so when the build machine has not yet been upgraded
 | 
						|
 * to a version of libc that provides pthread_key_create_once_np().
 | 
						|
 * It should all be deleted when solaris_nevada ships.
 | 
						|
 * The code is not MT-safe in a relaxed memory model.
 | 
						|
 */
 | 
						|
 | 
						|
#if defined(PTHREAD_ONCE_KEY_NP)
 | 
						|
static pthread_key_t	uu_error_key = PTHREAD_ONCE_KEY_NP;
 | 
						|
#else	/* PTHREAD_ONCE_KEY_NP */
 | 
						|
static pthread_key_t	uu_error_key = 0;
 | 
						|
static pthread_mutex_t	uu_key_lock = PTHREAD_MUTEX_INITIALIZER;
 | 
						|
#endif	/* PTHREAD_ONCE_KEY_NP */
 | 
						|
 | 
						|
static int		uu_error_key_setup = 0;
 | 
						|
 | 
						|
static pthread_mutex_t	uu_panic_lock = PTHREAD_MUTEX_INITIALIZER;
 | 
						|
/* LINTED static unused */
 | 
						|
static const char	*uu_panic_format;
 | 
						|
/* LINTED static unused */
 | 
						|
static va_list		uu_panic_args;
 | 
						|
static pthread_t	uu_panic_thread;
 | 
						|
 | 
						|
static uint32_t		_uu_main_error;
 | 
						|
static __thread int	_uu_main_thread = 0;
 | 
						|
 | 
						|
void
 | 
						|
uu_set_error(uint_t code)
 | 
						|
{
 | 
						|
	if (_uu_main_thread) {
 | 
						|
		_uu_main_error = code;
 | 
						|
		return;
 | 
						|
	}
 | 
						|
#if defined(PTHREAD_ONCE_KEY_NP)
 | 
						|
	if (pthread_key_create_once_np(&uu_error_key, NULL) != 0)
 | 
						|
		uu_error_key_setup = -1;
 | 
						|
	else
 | 
						|
		uu_error_key_setup = 1;
 | 
						|
#else	/* PTHREAD_ONCE_KEY_NP */
 | 
						|
	if (uu_error_key_setup == 0) {
 | 
						|
		(void) pthread_mutex_lock(&uu_key_lock);
 | 
						|
		if (uu_error_key_setup == 0) {
 | 
						|
			if (pthread_key_create(&uu_error_key, NULL) != 0)
 | 
						|
				uu_error_key_setup = -1;
 | 
						|
			else
 | 
						|
				uu_error_key_setup = 1;
 | 
						|
		}
 | 
						|
		(void) pthread_mutex_unlock(&uu_key_lock);
 | 
						|
	}
 | 
						|
#endif	/* PTHREAD_ONCE_KEY_NP */
 | 
						|
	if (uu_error_key_setup > 0)
 | 
						|
		(void) pthread_setspecific(uu_error_key,
 | 
						|
		    (void *)(uintptr_t)code);
 | 
						|
}
 | 
						|
 | 
						|
uint32_t
 | 
						|
uu_error(void)
 | 
						|
{
 | 
						|
	if (_uu_main_thread)
 | 
						|
		return (_uu_main_error);
 | 
						|
 | 
						|
	if (uu_error_key_setup < 0)	/* can't happen? */
 | 
						|
		return (UU_ERROR_UNKNOWN);
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Because UU_ERROR_NONE == 0, if uu_set_error() was
 | 
						|
	 * never called, then this will return UU_ERROR_NONE:
 | 
						|
	 */
 | 
						|
	return ((uint32_t)(uintptr_t)pthread_getspecific(uu_error_key));
 | 
						|
}
 | 
						|
 | 
						|
const char *
 | 
						|
uu_strerror(uint32_t code)
 | 
						|
{
 | 
						|
	const char *str;
 | 
						|
 | 
						|
	switch (code) {
 | 
						|
	case UU_ERROR_NONE:
 | 
						|
		str = dgettext(TEXT_DOMAIN, "No error");
 | 
						|
		break;
 | 
						|
 | 
						|
	case UU_ERROR_INVALID_ARGUMENT:
 | 
						|
		str = dgettext(TEXT_DOMAIN, "Invalid argument");
 | 
						|
		break;
 | 
						|
 | 
						|
	case UU_ERROR_UNKNOWN_FLAG:
 | 
						|
		str = dgettext(TEXT_DOMAIN, "Unknown flag passed");
 | 
						|
		break;
 | 
						|
 | 
						|
	case UU_ERROR_NO_MEMORY:
 | 
						|
		str = dgettext(TEXT_DOMAIN, "Out of memory");
 | 
						|
		break;
 | 
						|
 | 
						|
	case UU_ERROR_CALLBACK_FAILED:
 | 
						|
		str = dgettext(TEXT_DOMAIN, "Callback-initiated failure");
 | 
						|
		break;
 | 
						|
 | 
						|
	case UU_ERROR_NOT_SUPPORTED:
 | 
						|
		str = dgettext(TEXT_DOMAIN, "Operation not supported");
 | 
						|
		break;
 | 
						|
 | 
						|
	case UU_ERROR_EMPTY:
 | 
						|
		str = dgettext(TEXT_DOMAIN, "No value provided");
 | 
						|
		break;
 | 
						|
 | 
						|
	case UU_ERROR_UNDERFLOW:
 | 
						|
		str = dgettext(TEXT_DOMAIN, "Value too small");
 | 
						|
		break;
 | 
						|
 | 
						|
	case UU_ERROR_OVERFLOW:
 | 
						|
		str = dgettext(TEXT_DOMAIN, "Value too large");
 | 
						|
		break;
 | 
						|
 | 
						|
	case UU_ERROR_INVALID_CHAR:
 | 
						|
		str = dgettext(TEXT_DOMAIN,
 | 
						|
		    "Value contains unexpected character");
 | 
						|
		break;
 | 
						|
 | 
						|
	case UU_ERROR_INVALID_DIGIT:
 | 
						|
		str = dgettext(TEXT_DOMAIN,
 | 
						|
		    "Value contains digit not in base");
 | 
						|
		break;
 | 
						|
 | 
						|
	case UU_ERROR_SYSTEM:
 | 
						|
		str = dgettext(TEXT_DOMAIN, "Underlying system error");
 | 
						|
		break;
 | 
						|
 | 
						|
	case UU_ERROR_UNKNOWN:
 | 
						|
		str = dgettext(TEXT_DOMAIN, "Error status not known");
 | 
						|
		break;
 | 
						|
 | 
						|
	default:
 | 
						|
		errno = ESRCH;
 | 
						|
		str = NULL;
 | 
						|
		break;
 | 
						|
	}
 | 
						|
	return (str);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
uu_panic(const char *format, ...)
 | 
						|
{
 | 
						|
	va_list args;
 | 
						|
 | 
						|
	va_start(args, format);
 | 
						|
 | 
						|
	(void) pthread_mutex_lock(&uu_panic_lock);
 | 
						|
	if (uu_panic_thread == 0) {
 | 
						|
		uu_panic_thread = pthread_self();
 | 
						|
		uu_panic_format = format;
 | 
						|
		va_copy(uu_panic_args, args);
 | 
						|
	}
 | 
						|
	(void) pthread_mutex_unlock(&uu_panic_lock);
 | 
						|
 | 
						|
	(void) vfprintf(stderr, format, args);
 | 
						|
 | 
						|
	va_end(args);
 | 
						|
 | 
						|
	if (uu_panic_thread == pthread_self())
 | 
						|
		abort();
 | 
						|
	else
 | 
						|
		for (;;)
 | 
						|
			(void) pause();
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
uu_lockup(void)
 | 
						|
{
 | 
						|
	(void) pthread_mutex_lock(&uu_panic_lock);
 | 
						|
#if !defined(PTHREAD_ONCE_KEY_NP)
 | 
						|
	(void) pthread_mutex_lock(&uu_key_lock);
 | 
						|
#endif
 | 
						|
	uu_avl_lockup();
 | 
						|
	uu_list_lockup();
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
uu_release(void)
 | 
						|
{
 | 
						|
	(void) pthread_mutex_unlock(&uu_panic_lock);
 | 
						|
#if !defined(PTHREAD_ONCE_KEY_NP)
 | 
						|
	(void) pthread_mutex_unlock(&uu_key_lock);
 | 
						|
#endif
 | 
						|
	uu_avl_release();
 | 
						|
	uu_list_release();
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
uu_release_child(void)
 | 
						|
{
 | 
						|
	uu_panic_format = NULL;
 | 
						|
	uu_panic_thread = 0;
 | 
						|
 | 
						|
	uu_release();
 | 
						|
}
 | 
						|
 | 
						|
#ifdef __GNUC__
 | 
						|
static void
 | 
						|
uu_init(void) __attribute__((constructor));
 | 
						|
#else
 | 
						|
#pragma init(uu_init)
 | 
						|
#endif
 | 
						|
 | 
						|
static void
 | 
						|
uu_init(void)
 | 
						|
{
 | 
						|
	_uu_main_thread = 1;
 | 
						|
	(void) pthread_atfork(uu_lockup, uu_release, uu_release_child);
 | 
						|
}
 |