]> git.proxmox.com Git - mirror_zfs.git/blame - lib/libuutil/uu_misc.c
FreeBSD: Add zfs_link_create() error handling
[mirror_zfs.git] / lib / libuutil / uu_misc.c
CommitLineData
34dc7c2f
BB
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1d3ba0bf 9 * or https://opensource.org/licenses/CDDL-1.0.
34dc7c2f
BB
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
572e2857 23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
34dc7c2f
BB
24 */
25
34dc7c2f
BB
26#include "libuutil_common.h"
27
28#include <assert.h>
29#include <errno.h>
30#include <libintl.h>
31#include <pthread.h>
32#include <stdarg.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <sys/debug.h>
34dc7c2f 37#include <unistd.h>
572e2857 38#include <ctype.h>
34dc7c2f
BB
39
40#if !defined(TEXT_DOMAIN)
41#define TEXT_DOMAIN "SYS_TEST"
42#endif
43
44/*
45 * All of the old code under !defined(PTHREAD_ONCE_KEY_NP)
46 * is here to enable the building of a native version of
47 * libuutil.so when the build machine has not yet been upgraded
48 * to a version of libc that provides pthread_key_create_once_np().
49 * It should all be deleted when solaris_nevada ships.
50 * The code is not MT-safe in a relaxed memory model.
51 */
52
53#if defined(PTHREAD_ONCE_KEY_NP)
54static pthread_key_t uu_error_key = PTHREAD_ONCE_KEY_NP;
55#else /* PTHREAD_ONCE_KEY_NP */
56static pthread_key_t uu_error_key = 0;
57static pthread_mutex_t uu_key_lock = PTHREAD_MUTEX_INITIALIZER;
58#endif /* PTHREAD_ONCE_KEY_NP */
59
60static int uu_error_key_setup = 0;
61
62static pthread_mutex_t uu_panic_lock = PTHREAD_MUTEX_INITIALIZER;
63/* LINTED static unused */
64static const char *uu_panic_format;
65/* LINTED static unused */
66static va_list uu_panic_args;
67static pthread_t uu_panic_thread;
68
69static uint32_t _uu_main_error;
1e33ac1e 70static __thread int _uu_main_thread = 0;
34dc7c2f
BB
71
72void
73uu_set_error(uint_t code)
74{
1e33ac1e 75 if (_uu_main_thread) {
34dc7c2f
BB
76 _uu_main_error = code;
77 return;
78 }
79#if defined(PTHREAD_ONCE_KEY_NP)
80 if (pthread_key_create_once_np(&uu_error_key, NULL) != 0)
81 uu_error_key_setup = -1;
82 else
83 uu_error_key_setup = 1;
84#else /* PTHREAD_ONCE_KEY_NP */
85 if (uu_error_key_setup == 0) {
86 (void) pthread_mutex_lock(&uu_key_lock);
87 if (uu_error_key_setup == 0) {
88 if (pthread_key_create(&uu_error_key, NULL) != 0)
89 uu_error_key_setup = -1;
90 else
91 uu_error_key_setup = 1;
92 }
93 (void) pthread_mutex_unlock(&uu_key_lock);
94 }
95#endif /* PTHREAD_ONCE_KEY_NP */
96 if (uu_error_key_setup > 0)
97 (void) pthread_setspecific(uu_error_key,
98 (void *)(uintptr_t)code);
99}
100
101uint32_t
102uu_error(void)
103{
1e33ac1e 104 if (_uu_main_thread)
34dc7c2f
BB
105 return (_uu_main_error);
106
107 if (uu_error_key_setup < 0) /* can't happen? */
108 return (UU_ERROR_UNKNOWN);
109
110 /*
111 * Because UU_ERROR_NONE == 0, if uu_set_error() was
112 * never called, then this will return UU_ERROR_NONE:
113 */
114 return ((uint32_t)(uintptr_t)pthread_getspecific(uu_error_key));
115}
116
117const char *
118uu_strerror(uint32_t code)
119{
120 const char *str;
121
122 switch (code) {
123 case UU_ERROR_NONE:
124 str = dgettext(TEXT_DOMAIN, "No error");
125 break;
126
127 case UU_ERROR_INVALID_ARGUMENT:
128 str = dgettext(TEXT_DOMAIN, "Invalid argument");
129 break;
130
131 case UU_ERROR_UNKNOWN_FLAG:
132 str = dgettext(TEXT_DOMAIN, "Unknown flag passed");
133 break;
134
135 case UU_ERROR_NO_MEMORY:
136 str = dgettext(TEXT_DOMAIN, "Out of memory");
137 break;
138
139 case UU_ERROR_CALLBACK_FAILED:
140 str = dgettext(TEXT_DOMAIN, "Callback-initiated failure");
141 break;
142
143 case UU_ERROR_NOT_SUPPORTED:
144 str = dgettext(TEXT_DOMAIN, "Operation not supported");
145 break;
146
147 case UU_ERROR_EMPTY:
148 str = dgettext(TEXT_DOMAIN, "No value provided");
149 break;
150
151 case UU_ERROR_UNDERFLOW:
152 str = dgettext(TEXT_DOMAIN, "Value too small");
153 break;
154
155 case UU_ERROR_OVERFLOW:
156 str = dgettext(TEXT_DOMAIN, "Value too large");
157 break;
158
159 case UU_ERROR_INVALID_CHAR:
160 str = dgettext(TEXT_DOMAIN,
161 "Value contains unexpected character");
162 break;
163
164 case UU_ERROR_INVALID_DIGIT:
165 str = dgettext(TEXT_DOMAIN,
166 "Value contains digit not in base");
167 break;
168
169 case UU_ERROR_SYSTEM:
170 str = dgettext(TEXT_DOMAIN, "Underlying system error");
171 break;
172
173 case UU_ERROR_UNKNOWN:
174 str = dgettext(TEXT_DOMAIN, "Error status not known");
175 break;
176
177 default:
178 errno = ESRCH;
179 str = NULL;
180 break;
181 }
182 return (str);
183}
184
185void
186uu_panic(const char *format, ...)
187{
188 va_list args;
189
190 va_start(args, format);
191
192 (void) pthread_mutex_lock(&uu_panic_lock);
193 if (uu_panic_thread == 0) {
194 uu_panic_thread = pthread_self();
195 uu_panic_format = format;
196 va_copy(uu_panic_args, args);
197 }
198 (void) pthread_mutex_unlock(&uu_panic_lock);
199
200 (void) vfprintf(stderr, format, args);
201
a64f903b
GN
202 va_end(args);
203
34dc7c2f
BB
204 if (uu_panic_thread == pthread_self())
205 abort();
206 else
207 for (;;)
208 (void) pause();
209}
210
34dc7c2f
BB
211static void
212uu_lockup(void)
213{
214 (void) pthread_mutex_lock(&uu_panic_lock);
215#if !defined(PTHREAD_ONCE_KEY_NP)
216 (void) pthread_mutex_lock(&uu_key_lock);
217#endif
218 uu_avl_lockup();
219 uu_list_lockup();
220}
221
222static void
223uu_release(void)
224{
225 (void) pthread_mutex_unlock(&uu_panic_lock);
226#if !defined(PTHREAD_ONCE_KEY_NP)
227 (void) pthread_mutex_unlock(&uu_key_lock);
228#endif
229 uu_avl_release();
230 uu_list_release();
231}
232
233static void
234uu_release_child(void)
235{
236 uu_panic_format = NULL;
237 uu_panic_thread = 0;
238
239 uu_release();
240}
241
0ccd9d24
BB
242#ifdef __GNUC__
243static void
244uu_init(void) __attribute__((constructor));
245#else
34dc7c2f 246#pragma init(uu_init)
0ccd9d24
BB
247#endif
248
34dc7c2f
BB
249static void
250uu_init(void)
251{
1e33ac1e 252 _uu_main_thread = 1;
34dc7c2f
BB
253 (void) pthread_atfork(uu_lockup, uu_release, uu_release_child);
254}