8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / scsi / libses / common / ses_subr.c
blobaa1013e678f606ca809742b7232d4366d3f6f473
1 /*
2 * CDDL HEADER START
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.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
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]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <scsi/libses.h>
30 #include "ses_impl.h"
32 __thread ses_errno_t _ses_errno;
33 __thread char _ses_errmsg[1024];
34 __thread char _ses_nverr_member[256];
36 static void ses_vpanic(const char *, va_list) __NORETURN;
38 static void
39 ses_vpanic(const char *fmt, va_list ap)
41 int oserr = errno;
42 char msg[BUFSIZ];
43 size_t len;
45 (void) snprintf(msg, sizeof (msg), "ABORT: ");
46 len = strlen(msg);
47 (void) vsnprintf(msg + len, sizeof (msg) - len, fmt, ap);
49 if (strchr(fmt, '\n') == NULL) {
50 len = strlen(msg);
51 (void) snprintf(msg + len, sizeof (msg) - len, ": %s\n",
52 strerror(oserr));
55 (void) write(STDERR_FILENO, msg, strlen(msg));
57 abort:
58 abort();
59 _exit(1);
62 /*PRINTFLIKE1*/
63 void
64 ses_panic(const char *fmt, ...)
66 va_list ap;
68 va_start(ap, fmt);
69 ses_vpanic(fmt, ap);
70 va_end(ap);
73 int
74 ses_assert(const char *expr, const char *file, int line)
76 ses_panic("\"%s\", line %d: assertion failed: %s\n", file, line, expr);
78 /*NOTREACHED*/
79 return (0);
82 int
83 nvlist_add_fixed_string(nvlist_t *nvl, const char *name,
84 const char *buf, size_t len)
86 char *str = alloca(len + 1);
87 bcopy(buf, str, len);
88 str[len] = '\0';
90 return (nvlist_add_string(nvl, name, str));
94 * Like fixed_string, but clears any leading or trailing spaces.
96 int
97 nvlist_add_fixed_string_trunc(nvlist_t *nvl, const char *name,
98 const char *buf, size_t len)
100 while (buf[0] == ' ' && len > 0) {
101 buf++;
102 len--;
105 while (len > 0 && buf[len - 1] == ' ')
106 len--;
108 return (nvlist_add_fixed_string(nvl, name, buf, len));
111 ses_errno_t
112 ses_errno(void)
114 return (_ses_errno);
117 const char *
118 ses_errmsg(void)
120 if (_ses_errmsg[0] == '\0')
121 (void) snprintf(_ses_errmsg, sizeof (_ses_errmsg), "%s",
122 ses_strerror(_ses_errno));
124 return (_ses_errmsg);
127 const char *
128 ses_nv_error_member(void)
130 if (_ses_nverr_member[0] != '\0')
131 return (_ses_nverr_member);
132 else
133 return (NULL);
136 static int
137 __ses_set_errno(ses_errno_t err, const char *nvm)
139 if (nvm == NULL) {
140 _ses_nverr_member[0] = '\0';
141 } else {
142 (void) strlcpy(_ses_nverr_member, nvm,
143 sizeof (_ses_nverr_member));
145 _ses_errmsg[0] = '\0';
146 _ses_errno = err;
148 return (-1);
152 ses_set_errno(ses_errno_t err)
154 return (__ses_set_errno(err, NULL));
158 ses_set_nverrno(int err, const char *member)
160 ses_errno_t se = (err == ENOMEM || err == EAGAIN) ?
161 ESES_NOMEM : ESES_NVL;
164 * If the error is ESES_NVL, then we should always have a member
165 * available. The only time 'member' is NULL is when nvlist_alloc()
166 * fails, which should only be possible if memory allocation fails.
168 assert(se == ESES_NOMEM || member != NULL);
170 return (__ses_set_errno(se, member));
173 static int
174 ses_verror(ses_errno_t err, const char *fmt, va_list ap)
176 int syserr = errno;
177 size_t n;
178 char *errmsg;
180 errmsg = alloca(sizeof (_ses_errmsg));
181 (void) vsnprintf(errmsg, sizeof (_ses_errmsg), fmt, ap);
182 (void) ses_set_errno(err);
184 n = strlen(errmsg);
186 while (n != 0 && errmsg[n - 1] == '\n')
187 errmsg[--n] = '\0';
189 bcopy(errmsg, _ses_errmsg, sizeof (_ses_errmsg));
190 errno = syserr;
192 return (-1);
195 static int
196 ses_vnverror(int err, const char *member, const char *fmt,
197 va_list ap)
199 int syserr = errno;
200 size_t n;
201 char *errmsg;
203 errmsg = alloca(sizeof (_ses_errmsg));
204 (void) vsnprintf(errmsg, sizeof (_ses_errmsg), fmt, ap);
205 (void) ses_set_nverrno(err, member);
207 n = strlen(errmsg);
209 while (n != 0 && errmsg[n - 1] == '\n')
210 errmsg[--n] = '\0';
212 (void) snprintf(errmsg + n, sizeof (_ses_errmsg) - n, ": %s",
213 strerror(err));
215 bcopy(errmsg, _ses_errmsg, sizeof (_ses_errmsg));
216 errno = syserr;
218 return (-1);
222 ses_error(ses_errno_t err, const char *fmt, ...)
224 va_list ap;
225 int rv;
227 va_start(ap, fmt);
228 rv = ses_verror(err, fmt, ap);
229 va_end(ap);
231 return (rv);
235 ses_nverror(int err, const char *member, const char *fmt, ...)
237 va_list ap;
238 int rv;
240 va_start(ap, fmt);
241 rv = ses_vnverror(err, member, fmt, ap);
242 va_end(ap);
244 return (rv);
248 ses_libscsi_error(libscsi_hdl_t *shp, const char *fmt, ...)
250 va_list ap;
251 char errmsg[LIBSES_ERRMSGLEN];
252 libscsi_errno_t se = libscsi_errno(shp);
253 ses_errno_t e;
255 switch (se) {
256 case ESCSI_NONE:
257 return (0);
258 case ESCSI_NOMEM:
259 e = ESES_NOMEM;
260 break;
261 case ESCSI_NOTSUP:
262 e = ESES_NOTSUP;
263 break;
264 case ESCSI_ZERO_LENGTH:
265 case ESCSI_VERSION:
266 case ESCSI_BADFLAGS:
267 case ESCSI_BOGUSFLAGS:
268 case ESCSI_BADLENGTH:
269 case ESCSI_NEEDBUF:
270 va_start(ap, fmt);
271 (void) vsnprintf(errmsg, sizeof (errmsg), fmt, ap);
272 va_end(ap);
273 ses_panic("%s: unexpected libscsi error %s: %s", errmsg,
274 libscsi_errname(se), libscsi_errmsg(shp));
275 break;
276 case ESCSI_UNKNOWN:
277 e = ESES_UNKNOWN;
278 break;
279 default:
280 e = ESES_LIBSCSI;
281 break;
284 va_start(ap, fmt);
285 (void) vsnprintf(errmsg, sizeof (errmsg), fmt, ap);
286 va_end(ap);
288 return (ses_error(e, "%s: %s", errmsg, libscsi_errmsg(shp)));
292 ses_scsi_error(libscsi_action_t *ap, const char *fmt, ...)
294 va_list args;
295 char errmsg[LIBSES_ERRMSGLEN];
296 uint64_t asc = 0, ascq = 0, key = 0;
297 const char *code, *keystr;
299 va_start(args, fmt);
300 (void) vsnprintf(errmsg, sizeof (errmsg), fmt, args);
301 va_end(args);
303 if (libscsi_action_parse_sense(ap, &key, &asc, &ascq, NULL) != 0)
304 return (ses_error(ESES_LIBSCSI,
305 "%s: SCSI status %d (no sense data available)", errmsg,
306 libscsi_action_get_status(ap)));
308 code = libscsi_sense_code_name(asc, ascq);
309 keystr = libscsi_sense_key_name(key);
311 return (ses_error(ESES_LIBSCSI, "%s: SCSI status %d sense key %llu "
312 "(%s) additional sense code 0x%llx/0x%llx (%s)", errmsg,
313 libscsi_action_get_status(ap), key, keystr ? keystr : "<unknown>",
314 asc, ascq, code ? code : "<unknown>"));
317 void *
318 ses_alloc(size_t sz)
320 void *p;
322 if (sz == 0)
323 ses_panic("attempted zero-length allocation");
325 if ((p = malloc(sz)) == NULL)
326 (void) ses_set_errno(ESES_NOMEM);
328 return (p);
331 void *
332 ses_zalloc(size_t sz)
334 void *p;
336 if ((p = ses_alloc(sz)) != NULL)
337 bzero(p, sz);
339 return (p);
342 char *
343 ses_strdup(const char *s)
345 char *p;
346 size_t len;
348 if (s == NULL)
349 ses_panic("attempted zero-length allocation");
351 len = strlen(s) + 1;
353 if ((p = ses_alloc(len)) != NULL)
354 bcopy(s, p, len);
356 return (p);
359 void *
360 ses_realloc(void *p, size_t sz)
362 if (sz == 0)
363 ses_panic("attempted zero-length allocation");
365 if ((p = realloc(p, sz)) == NULL)
366 (void) ses_set_errno(ESES_NOMEM);
368 return (p);
371 /*ARGSUSED*/
372 void
373 ses_free(void *p)
375 free(p);