dbus-errors.c revision a1df3040f29223eddaa3ace0fe018fcb28cddcd9
1/* -*- mode: C; c-file-style: "gnu" -*- */ 2/* dbus-errors.c Error reporting 3 * 4 * Copyright (C) 2002 Red Hat Inc. 5 * Copyright (C) 2003 CodeFactory AB 6 * 7 * Licensed under the Academic Free License version 2.0 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * 23 */ 24#include "dbus-errors.h" 25#include "dbus-internals.h" 26#include "dbus-string.h" 27#include <stdarg.h> 28#include <string.h> 29 30/** 31 * @defgroup DBusErrorInternals Error reporting internals 32 * @ingroup DBusInternals 33 * @brief Error reporting internals 34 * @{ 35 */ 36 37/** 38 * Internals of DBusError 39 */ 40typedef struct 41{ 42 const char *name; /**< error name */ 43 char *message; /**< error message */ 44 45 unsigned int const_message : 1; /**< Message is not owned by DBusError */ 46 47 unsigned int dummy2 : 1; /**< placeholder */ 48 unsigned int dummy3 : 1; /**< placeholder */ 49 unsigned int dummy4 : 1; /**< placeholder */ 50 unsigned int dummy5 : 1; /**< placeholder */ 51 52 void *padding1; /**< placeholder */ 53 54} DBusRealError; 55 56/** 57 * Returns a longer message describing an error name. 58 * If the error name is unknown, returns the name 59 * itself. 60 * 61 * @param error the error to describe 62 * @returns a constant string describing the error. 63 */ 64static const char* 65message_from_error (const char *error) 66{ 67 if (strcmp (error, DBUS_ERROR_FAILED) == 0) 68 return "Unknown error"; 69 else if (strcmp (error, DBUS_ERROR_NO_MEMORY) == 0) 70 return "Not enough memory available"; 71 else if (strcmp (error, DBUS_ERROR_IO_ERROR) == 0) 72 return "Error reading or writing data"; 73 else if (strcmp (error, DBUS_ERROR_BAD_ADDRESS) == 0) 74 return "Could not parse address"; 75 else if (strcmp (error, DBUS_ERROR_NOT_SUPPORTED) == 0) 76 return "Feature not supported"; 77 else if (strcmp (error, DBUS_ERROR_LIMITS_EXCEEDED) == 0) 78 return "Resource limits exceeded"; 79 else if (strcmp (error, DBUS_ERROR_ACCESS_DENIED) == 0) 80 return "Permission denied"; 81 else if (strcmp (error, DBUS_ERROR_AUTH_FAILED) == 0) 82 return "Could not authenticate to server"; 83 else if (strcmp (error, DBUS_ERROR_NO_SERVER) == 0) 84 return "No server available at address"; 85 else if (strcmp (error, DBUS_ERROR_TIMEOUT) == 0) 86 return "Connection timed out"; 87 else if (strcmp (error, DBUS_ERROR_NO_NETWORK) == 0) 88 return "Network unavailable"; 89 else if (strcmp (error, DBUS_ERROR_ADDRESS_IN_USE) == 0) 90 return "Address already in use"; 91 else if (strcmp (error, DBUS_ERROR_DISCONNECTED) == 0) 92 return "Disconnected."; 93 else if (strcmp (error, DBUS_ERROR_INVALID_ARGS) == 0) 94 return "Invalid argumemts."; 95 else if (strcmp (error, DBUS_ERROR_NO_REPLY) == 0) 96 return "Did not get a reply message."; 97 else if (strcmp (error, DBUS_ERROR_FILE_NOT_FOUND) == 0) 98 return "File doesn't exist."; 99 else 100 return error; 101} 102 103/** @} */ /* End of internals */ 104 105/** 106 * @defgroup DBusErrors Error reporting 107 * @ingroup DBus 108 * @brief Error reporting 109 * 110 * Types and functions related to reporting errors. 111 * 112 * 113 * In essence D-BUS error reporting works as follows: 114 * 115 * @code 116 * DBusError error; 117 * dbus_error_init (&error); 118 * dbus_some_function (arg1, arg2, &error); 119 * if (dbus_error_is_set (&error)) 120 * { 121 * fprintf (stderr, "an error occurred: %s\n", error.message); 122 * dbus_error_free (&error); 123 * } 124 * @endcode 125 * 126 * There are some rules. An error passed to a D-BUS function must 127 * always be unset; you can't pass in an error that's already set. If 128 * a function has a return code indicating whether an error occurred, 129 * and also a #DBusError parameter, then the error will always be set 130 * if and only if the return code indicates an error occurred. i.e. 131 * the return code and the error are never going to disagree. 132 * 133 * An error only needs to be freed if it's been set, not if 134 * it's merely been initialized. 135 * 136 * You can check the specific error that occurred using 137 * dbus_error_has_name(). 138 * 139 * @{ 140 */ 141 142/** 143 * Initializes a DBusError structure. Does not allocate 144 * any memory; the error only needs to be freed 145 * if it is set at some point. 146 * 147 * @param error the DBusError. 148 */ 149void 150dbus_error_init (DBusError *error) 151{ 152 DBusRealError *real; 153 154 _dbus_return_if_fail (error != NULL); 155 156 _dbus_assert (sizeof (DBusError) == sizeof (DBusRealError)); 157 158 real = (DBusRealError *)error; 159 160 real->name = NULL; 161 real->message = NULL; 162 163 real->const_message = TRUE; 164} 165 166/** 167 * Frees an error that's been set (or just initialized), 168 * then reinitializes the error as in dbus_error_init(). 169 * 170 * @param error memory where the error is stored. 171 */ 172void 173dbus_error_free (DBusError *error) 174{ 175 DBusRealError *real; 176 177 _dbus_return_if_fail (error != NULL); 178 179 real = (DBusRealError *)error; 180 181 if (!real->const_message) 182 dbus_free (real->message); 183 184 dbus_error_init (error); 185} 186 187/** 188 * Assigns an error name and message to a DBusError. Does nothing if 189 * error is #NULL. The message may be NULL, which means a default 190 * message will be deduced from the name. If the error name is unknown 191 * to D-BUS the default message will be totally useless, though. 192 * 193 * @todo should be called dbus_error_set_const() 194 * 195 * @param error the error. 196 * @param name the error name (not copied!!!) 197 * @param message the error message (not copied!!!) 198 */ 199void 200dbus_set_error_const (DBusError *error, 201 const char *name, 202 const char *message) 203{ 204 DBusRealError *real; 205 206 _dbus_return_if_error_is_set (error); 207 _dbus_return_if_fail (name != NULL); 208 209 if (error == NULL) 210 return; 211 212 _dbus_assert (error->name == NULL); 213 _dbus_assert (error->message == NULL); 214 215 if (message == NULL) 216 message = message_from_error (name); 217 218 real = (DBusRealError *)error; 219 220 real->name = name; 221 real->message = (char *)message; 222 real->const_message = TRUE; 223} 224 225/** 226 * Moves an error src into dest, freeing src and 227 * overwriting dest. Both src and dest must be initialized. 228 * src is reinitialized to an empty error. dest may not 229 * contain an existing error. If the destination is 230 * #NULL, just frees and reinits the source error. 231 * 232 * @param src the source error 233 * @param dest the destination error or #NULL 234 */ 235void 236dbus_move_error (DBusError *src, 237 DBusError *dest) 238{ 239 _dbus_return_if_error_is_set (dest); 240 241 if (dest) 242 { 243 dbus_error_free (dest); 244 *dest = *src; 245 dbus_error_init (src); 246 } 247 else 248 dbus_error_free (src); 249} 250 251/** 252 * Checks whether the error is set and has the given 253 * name. 254 * @param error the error 255 * @param name the name 256 * @returns #TRUE if the given named error occurred 257 */ 258dbus_bool_t 259dbus_error_has_name (const DBusError *error, 260 const char *name) 261{ 262 _dbus_return_val_if_fail (error != NULL, FALSE); 263 _dbus_return_val_if_fail (name != NULL, FALSE); 264 265 _dbus_assert ((error->name != NULL && error->message != NULL) || 266 (error->name == NULL && error->message == NULL)); 267 268 if (error->name != NULL) 269 { 270 DBusString str1, str2; 271 _dbus_string_init_const (&str1, error->name); 272 _dbus_string_init_const (&str2, name); 273 return _dbus_string_equal (&str1, &str2); 274 } 275 else 276 return FALSE; 277} 278 279/** 280 * Checks whether an error occurred (the error is set). 281 * 282 * @param error the error object 283 * @returns #TRUE if an error occurred 284 */ 285dbus_bool_t 286dbus_error_is_set (const DBusError *error) 287{ 288 _dbus_return_val_if_fail (error != NULL, FALSE); 289 _dbus_assert ((error->name != NULL && error->message != NULL) || 290 (error->name == NULL && error->message == NULL)); 291 return error->name != NULL; 292} 293 294/** 295 * Assigns an error name and message to a DBusError. 296 * Does nothing if error is #NULL. 297 * 298 * The format may be NULL, which means a default message will be 299 * deduced from the name. If the error name is unknown to D-BUS the 300 * default message will be totally useless, though. 301 * 302 * If no memory can be allocated for the error message, 303 * an out-of-memory error message will be set instead. 304 * 305 * @todo should be called dbus_error_set() 306 * 307 * @param error the error. 308 * @param name the error name (not copied!!!) 309 * @param format printf-style format string. 310 */ 311void 312dbus_set_error (DBusError *error, 313 const char *name, 314 const char *format, 315 ...) 316{ 317 DBusRealError *real; 318 DBusString str; 319 va_list args; 320 321 if (error == NULL) 322 return; 323 324 /* it's a bug to pile up errors */ 325 _dbus_return_if_error_is_set (error); 326 _dbus_return_if_fail (name != NULL); 327 328 _dbus_assert (error->name == NULL); 329 _dbus_assert (error->message == NULL); 330 331 if (!_dbus_string_init (&str)) 332 goto nomem; 333 334 if (format == NULL) 335 { 336 if (!_dbus_string_append (&str, 337 message_from_error (name))) 338 { 339 _dbus_string_free (&str); 340 goto nomem; 341 } 342 } 343 else 344 { 345 va_start (args, format); 346 if (!_dbus_string_append_printf_valist (&str, format, args)) 347 { 348 _dbus_string_free (&str); 349 goto nomem; 350 } 351 va_end (args); 352 } 353 354 real = (DBusRealError *)error; 355 356 if (!_dbus_string_steal_data (&str, &real->message)) 357 { 358 _dbus_string_free (&str); 359 goto nomem; 360 } 361 362 real->name = name; 363 real->const_message = FALSE; 364 365 _dbus_string_free (&str); 366 367 return; 368 369 nomem: 370 dbus_set_error_const (error, DBUS_ERROR_NO_MEMORY, NULL); 371} 372 373/** @} */ /* End public API */ 374