error.c revision 1.1.1.3 1 1.1 jmmv /*
2 1.1 jmmv * Automated Testing Framework (atf)
3 1.1 jmmv *
4 1.1.1.3 jmmv * Copyright (c) 2008, 2009, 2010 The NetBSD Foundation, Inc.
5 1.1 jmmv * All rights reserved.
6 1.1 jmmv *
7 1.1 jmmv * Redistribution and use in source and binary forms, with or without
8 1.1 jmmv * modification, are permitted provided that the following conditions
9 1.1 jmmv * are met:
10 1.1 jmmv * 1. Redistributions of source code must retain the above copyright
11 1.1 jmmv * notice, this list of conditions and the following disclaimer.
12 1.1 jmmv * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 jmmv * notice, this list of conditions and the following disclaimer in the
14 1.1 jmmv * documentation and/or other materials provided with the distribution.
15 1.1 jmmv *
16 1.1 jmmv * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17 1.1 jmmv * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 1.1 jmmv * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 1.1 jmmv * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 1.1 jmmv * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21 1.1 jmmv * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 1.1 jmmv * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 1.1 jmmv * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 1.1 jmmv * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 1.1 jmmv * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 1.1 jmmv * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 1.1 jmmv * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 1.1 jmmv */
29 1.1 jmmv
30 1.1 jmmv #include <stdarg.h>
31 1.1 jmmv #include <stdio.h>
32 1.1 jmmv #include <stdlib.h>
33 1.1 jmmv #include <string.h>
34 1.1 jmmv
35 1.1 jmmv #include "atf-c/error.h"
36 1.1 jmmv #include "atf-c/sanity.h"
37 1.1 jmmv
38 1.1.1.2 jmmv /* Theoretically, there can only be a single error intance at any given
39 1.1.1.2 jmmv * point in time, because errors are raised at one point and must be
40 1.1.1.2 jmmv * handled immediately. If another error has to be raised during the
41 1.1.1.2 jmmv * handling process, something else has to be done with the previous
42 1.1.1.2 jmmv * error.
43 1.1.1.2 jmmv *
44 1.1.1.2 jmmv * This is per-thread information and will break threaded tests, but we
45 1.1.1.2 jmmv * currently do not have any threading support; therefore, this is fine. */
46 1.1.1.2 jmmv static bool error_on_flight = false;
47 1.1.1.2 jmmv
48 1.1 jmmv /* ---------------------------------------------------------------------
49 1.1 jmmv * Auxiliary functions.
50 1.1 jmmv * --------------------------------------------------------------------- */
51 1.1 jmmv
52 1.1 jmmv static
53 1.1 jmmv void
54 1.1 jmmv error_format(const atf_error_t err, char *buf, size_t buflen)
55 1.1 jmmv {
56 1.1 jmmv PRE(err != NULL);
57 1.1 jmmv snprintf(buf, buflen, "Error '%s'", err->m_type);
58 1.1 jmmv }
59 1.1 jmmv
60 1.1 jmmv static
61 1.1 jmmv bool
62 1.1 jmmv error_init(atf_error_t err, const char *type, void *data, size_t datalen,
63 1.1 jmmv void (*format)(const atf_error_t, char *, size_t))
64 1.1 jmmv {
65 1.1 jmmv bool ok;
66 1.1 jmmv
67 1.1 jmmv PRE(data != NULL || datalen == 0);
68 1.1 jmmv PRE(datalen != 0 || data == NULL);
69 1.1 jmmv
70 1.1 jmmv err->m_free = false;
71 1.1 jmmv err->m_type = type;
72 1.1 jmmv err->m_format = (format == NULL) ? error_format : format;
73 1.1 jmmv
74 1.1 jmmv ok = true;
75 1.1 jmmv if (data == NULL) {
76 1.1 jmmv err->m_data = NULL;
77 1.1 jmmv } else {
78 1.1 jmmv err->m_data = malloc(datalen);
79 1.1.1.2 jmmv if (err->m_data == NULL) {
80 1.1 jmmv ok = false;
81 1.1.1.2 jmmv } else
82 1.1 jmmv memcpy(err->m_data, data, datalen);
83 1.1 jmmv }
84 1.1 jmmv
85 1.1 jmmv return ok;
86 1.1 jmmv }
87 1.1 jmmv
88 1.1 jmmv /* ---------------------------------------------------------------------
89 1.1 jmmv * The "atf_error" type.
90 1.1 jmmv * --------------------------------------------------------------------- */
91 1.1 jmmv
92 1.1 jmmv atf_error_t
93 1.1 jmmv atf_error_new(const char *type, void *data, size_t datalen,
94 1.1 jmmv void (*format)(const atf_error_t, char *, size_t))
95 1.1 jmmv {
96 1.1 jmmv atf_error_t err;
97 1.1 jmmv
98 1.1.1.2 jmmv PRE(!error_on_flight);
99 1.1 jmmv PRE(data != NULL || datalen == 0);
100 1.1 jmmv PRE(datalen != 0 || data == NULL);
101 1.1 jmmv
102 1.1 jmmv err = malloc(sizeof(*err));
103 1.1 jmmv if (err == NULL)
104 1.1 jmmv err = atf_no_memory_error();
105 1.1 jmmv else {
106 1.1 jmmv if (!error_init(err, type, data, datalen, format)) {
107 1.1 jmmv free(err);
108 1.1 jmmv err = atf_no_memory_error();
109 1.1.1.2 jmmv } else {
110 1.1 jmmv err->m_free = true;
111 1.1.1.2 jmmv error_on_flight = true;
112 1.1.1.2 jmmv }
113 1.1 jmmv }
114 1.1 jmmv
115 1.1 jmmv INV(err != NULL);
116 1.1.1.2 jmmv POST(error_on_flight);
117 1.1 jmmv return err;
118 1.1 jmmv }
119 1.1 jmmv
120 1.1 jmmv void
121 1.1 jmmv atf_error_free(atf_error_t err)
122 1.1 jmmv {
123 1.1 jmmv bool freeit;
124 1.1 jmmv
125 1.1.1.2 jmmv PRE(error_on_flight);
126 1.1 jmmv PRE(err != NULL);
127 1.1 jmmv
128 1.1 jmmv freeit = err->m_free;
129 1.1 jmmv
130 1.1 jmmv if (err->m_data != NULL)
131 1.1 jmmv free(err->m_data);
132 1.1 jmmv
133 1.1 jmmv if (freeit)
134 1.1 jmmv free(err);
135 1.1.1.2 jmmv
136 1.1.1.2 jmmv error_on_flight = false;
137 1.1 jmmv }
138 1.1 jmmv
139 1.1 jmmv atf_error_t
140 1.1 jmmv atf_no_error(void)
141 1.1 jmmv {
142 1.1 jmmv return NULL;
143 1.1 jmmv }
144 1.1 jmmv
145 1.1 jmmv bool
146 1.1 jmmv atf_is_error(const atf_error_t err)
147 1.1 jmmv {
148 1.1 jmmv return err != NULL;
149 1.1 jmmv }
150 1.1 jmmv
151 1.1 jmmv bool
152 1.1 jmmv atf_error_is(const atf_error_t err, const char *type)
153 1.1 jmmv {
154 1.1 jmmv PRE(err != NULL);
155 1.1 jmmv
156 1.1 jmmv return strcmp(err->m_type, type) == 0;
157 1.1 jmmv }
158 1.1 jmmv
159 1.1 jmmv const void *
160 1.1 jmmv atf_error_data(const atf_error_t err)
161 1.1 jmmv {
162 1.1 jmmv PRE(err != NULL);
163 1.1 jmmv
164 1.1 jmmv return err->m_data;
165 1.1 jmmv }
166 1.1 jmmv
167 1.1 jmmv void
168 1.1 jmmv atf_error_format(const atf_error_t err, char *buf, size_t buflen)
169 1.1 jmmv {
170 1.1 jmmv PRE(err != NULL);
171 1.1 jmmv err->m_format(err, buf, buflen);
172 1.1 jmmv }
173 1.1 jmmv
174 1.1 jmmv /* ---------------------------------------------------------------------
175 1.1 jmmv * Common error types.
176 1.1 jmmv * --------------------------------------------------------------------- */
177 1.1 jmmv
178 1.1 jmmv /*
179 1.1 jmmv * The "libc" error.
180 1.1 jmmv */
181 1.1 jmmv
182 1.1 jmmv struct atf_libc_error_data {
183 1.1 jmmv int m_errno;
184 1.1 jmmv char m_what[4096];
185 1.1 jmmv };
186 1.1 jmmv typedef struct atf_libc_error_data atf_libc_error_data_t;
187 1.1 jmmv
188 1.1 jmmv static
189 1.1 jmmv void
190 1.1 jmmv libc_format(const atf_error_t err, char *buf, size_t buflen)
191 1.1 jmmv {
192 1.1 jmmv const atf_libc_error_data_t *data;
193 1.1 jmmv
194 1.1 jmmv PRE(atf_error_is(err, "libc"));
195 1.1 jmmv
196 1.1 jmmv data = atf_error_data(err);
197 1.1 jmmv snprintf(buf, buflen, "%s: %s", data->m_what, strerror(data->m_errno));
198 1.1 jmmv }
199 1.1 jmmv
200 1.1 jmmv atf_error_t
201 1.1 jmmv atf_libc_error(int syserrno, const char *fmt, ...)
202 1.1 jmmv {
203 1.1 jmmv atf_error_t err;
204 1.1 jmmv atf_libc_error_data_t data;
205 1.1 jmmv va_list ap;
206 1.1 jmmv
207 1.1 jmmv data.m_errno = syserrno;
208 1.1 jmmv va_start(ap, fmt);
209 1.1 jmmv vsnprintf(data.m_what, sizeof(data.m_what), fmt, ap);
210 1.1 jmmv va_end(ap);
211 1.1 jmmv
212 1.1 jmmv err = atf_error_new("libc", &data, sizeof(data), libc_format);
213 1.1 jmmv
214 1.1 jmmv return err;
215 1.1 jmmv }
216 1.1 jmmv
217 1.1 jmmv int
218 1.1 jmmv atf_libc_error_code(const atf_error_t err)
219 1.1 jmmv {
220 1.1 jmmv const struct atf_libc_error_data *data;
221 1.1 jmmv
222 1.1 jmmv PRE(atf_error_is(err, "libc"));
223 1.1 jmmv
224 1.1 jmmv data = atf_error_data(err);
225 1.1 jmmv
226 1.1 jmmv return data->m_errno;
227 1.1 jmmv }
228 1.1 jmmv
229 1.1.1.2 jmmv const char *
230 1.1.1.2 jmmv atf_libc_error_msg(const atf_error_t err)
231 1.1.1.2 jmmv {
232 1.1.1.2 jmmv const struct atf_libc_error_data *data;
233 1.1.1.2 jmmv
234 1.1.1.2 jmmv PRE(atf_error_is(err, "libc"));
235 1.1.1.2 jmmv
236 1.1.1.2 jmmv data = atf_error_data(err);
237 1.1.1.2 jmmv
238 1.1.1.2 jmmv return data->m_what;
239 1.1.1.2 jmmv }
240 1.1.1.2 jmmv
241 1.1 jmmv /*
242 1.1 jmmv * The "no_memory" error.
243 1.1 jmmv */
244 1.1 jmmv
245 1.1 jmmv static struct atf_error no_memory_error;
246 1.1 jmmv
247 1.1 jmmv static
248 1.1 jmmv void
249 1.1 jmmv no_memory_format(const atf_error_t err, char *buf, size_t buflen)
250 1.1 jmmv {
251 1.1 jmmv PRE(atf_error_is(err, "no_memory"));
252 1.1 jmmv
253 1.1 jmmv snprintf(buf, buflen, "Not enough memory");
254 1.1 jmmv }
255 1.1 jmmv
256 1.1 jmmv atf_error_t
257 1.1 jmmv atf_no_memory_error(void)
258 1.1 jmmv {
259 1.1.1.2 jmmv PRE(!error_on_flight);
260 1.1.1.2 jmmv
261 1.1.1.2 jmmv error_init(&no_memory_error, "no_memory", NULL, 0,
262 1.1.1.2 jmmv no_memory_format);
263 1.1 jmmv
264 1.1.1.2 jmmv error_on_flight = true;
265 1.1 jmmv return &no_memory_error;
266 1.1 jmmv }
267