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