dbus-errors.c revision b459906a7a6519c034f5882c472f0c945371dfc6
1/* -*- mode: C; c-file-style: "gnu" -*- */ 2/* dbus-errors.c Error reporting 3 * 4 * Copyright (C) 2002, 2004 Red Hat Inc. 5 * Copyright (C) 2003 CodeFactory AB 6 * 7 * Licensed under the Academic Free License version 2.1 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 "dbus-protocol.h" 28#include <stdarg.h> 29#include <string.h> 30 31/** 32 * @defgroup DBusErrorInternals Error reporting internals 33 * @ingroup DBusInternals 34 * @brief Error reporting internals 35 * @{ 36 */ 37 38/** 39 * Internals of DBusError 40 */ 41typedef struct 42{ 43 const char *name; /**< error name */ 44 char *message; /**< error message */ 45 46 unsigned int const_message : 1; /**< Message is not owned by DBusError */ 47 48 unsigned int dummy2 : 1; /**< placeholder */ 49 unsigned int dummy3 : 1; /**< placeholder */ 50 unsigned int dummy4 : 1; /**< placeholder */ 51 unsigned int dummy5 : 1; /**< placeholder */ 52 53 void *padding1; /**< placeholder */ 54 55} DBusRealError; 56 57/** 58 * Returns a longer message describing an error name. 59 * If the error name is unknown, returns the name 60 * itself. 61 * 62 * @param error the error to describe 63 * @returns a constant string describing the error. 64 */ 65static const char* 66message_from_error (const char *error) 67{ 68 if (strcmp (error, DBUS_ERROR_FAILED) == 0) 69 return "Unknown error"; 70 else if (strcmp (error, DBUS_ERROR_NO_MEMORY) == 0) 71 return "Not enough memory available"; 72 else if (strcmp (error, DBUS_ERROR_IO_ERROR) == 0) 73 return "Error reading or writing data"; 74 else if (strcmp (error, DBUS_ERROR_BAD_ADDRESS) == 0) 75 return "Could not parse address"; 76 else if (strcmp (error, DBUS_ERROR_NOT_SUPPORTED) == 0) 77 return "Feature not supported"; 78 else if (strcmp (error, DBUS_ERROR_LIMITS_EXCEEDED) == 0) 79 return "Resource limits exceeded"; 80 else if (strcmp (error, DBUS_ERROR_ACCESS_DENIED) == 0) 81 return "Permission denied"; 82 else if (strcmp (error, DBUS_ERROR_AUTH_FAILED) == 0) 83 return "Could not authenticate to server"; 84 else if (strcmp (error, DBUS_ERROR_NO_SERVER) == 0) 85 return "No server available at address"; 86 else if (strcmp (error, DBUS_ERROR_TIMEOUT) == 0) 87 return "Connection timed out"; 88 else if (strcmp (error, DBUS_ERROR_NO_NETWORK) == 0) 89 return "Network unavailable"; 90 else if (strcmp (error, DBUS_ERROR_ADDRESS_IN_USE) == 0) 91 return "Address already in use"; 92 else if (strcmp (error, DBUS_ERROR_DISCONNECTED) == 0) 93 return "Disconnected."; 94 else if (strcmp (error, DBUS_ERROR_INVALID_ARGS) == 0) 95 return "Invalid arguments."; 96 else if (strcmp (error, DBUS_ERROR_NO_REPLY) == 0) 97 return "Did not get a reply message."; 98 else if (strcmp (error, DBUS_ERROR_FILE_NOT_FOUND) == 0) 99 return "File doesn't exist."; 100 else 101 return error; 102} 103 104/** @} */ /* End of internals */ 105 106/** 107 * @defgroup DBusErrors Error reporting 108 * @ingroup DBus 109 * @brief Error reporting 110 * 111 * Types and functions related to reporting errors. 112 * 113 * 114 * In essence D-BUS error reporting works as follows: 115 * 116 * @code 117 * DBusError error; 118 * dbus_error_init (&error); 119 * dbus_some_function (arg1, arg2, &error); 120 * if (dbus_error_is_set (&error)) 121 * { 122 * fprintf (stderr, "an error occurred: %s\n", error.message); 123 * dbus_error_free (&error); 124 * } 125 * @endcode 126 * 127 * There are some rules. An error passed to a D-BUS function must 128 * always be unset; you can't pass in an error that's already set. If 129 * a function has a return code indicating whether an error occurred, 130 * and also a #DBusError parameter, then the error will always be set 131 * if and only if the return code indicates an error occurred. i.e. 132 * the return code and the error are never going to disagree. 133 * 134 * An error only needs to be freed if it's been set, not if 135 * it's merely been initialized. 136 * 137 * You can check the specific error that occurred using 138 * dbus_error_has_name(). 139 * 140 * @{ 141 */ 142 143/** 144 * Initializes a DBusError structure. Does not allocate 145 * any memory; the error only needs to be freed 146 * if it is set at some point. 147 * 148 * @param error the DBusError. 149 */ 150void 151dbus_error_init (DBusError *error) 152{ 153 DBusRealError *real; 154 155 _dbus_return_if_fail (error != NULL); 156 157 _dbus_assert (sizeof (DBusError) == sizeof (DBusRealError)); 158 159 real = (DBusRealError *)error; 160 161 real->name = NULL; 162 real->message = NULL; 163 164 real->const_message = TRUE; 165} 166 167/** 168 * Frees an error that's been set (or just initialized), 169 * then reinitializes the error as in dbus_error_init(). 170 * 171 * @param error memory where the error is stored. 172 */ 173void 174dbus_error_free (DBusError *error) 175{ 176 DBusRealError *real; 177 178 _dbus_return_if_fail (error != NULL); 179 180 real = (DBusRealError *)error; 181 182 if (!real->const_message) 183 { 184 dbus_free (real->name); 185 dbus_free (real->message); 186 } 187 188 dbus_error_init (error); 189} 190 191/** 192 * Assigns an error name and message to a DBusError. Does nothing if 193 * error is #NULL. The message may be NULL, which means a default 194 * message will be deduced from the name. If the error name is unknown 195 * to D-BUS the default message will be totally useless, though. 196 * 197 * @param error the error. 198 * @param name the error name (not copied!!!) 199 * @param message the error message (not copied!!!) 200 */ 201void 202dbus_set_error_const (DBusError *error, 203 const char *name, 204 const char *message) 205{ 206 DBusRealError *real; 207 208 _dbus_return_if_error_is_set (error); 209 _dbus_return_if_fail (name != NULL); 210 211 if (error == NULL) 212 return; 213 214 _dbus_assert (error->name == NULL); 215 _dbus_assert (error->message == NULL); 216 217 if (message == NULL) 218 message = message_from_error (name); 219 220 real = (DBusRealError *)error; 221 222 real->name = name; 223 real->message = (char *)message; 224 real->const_message = TRUE; 225} 226 227/** 228 * Moves an error src into dest, freeing src and 229 * overwriting dest. Both src and dest must be initialized. 230 * src is reinitialized to an empty error. dest may not 231 * contain an existing error. If the destination is 232 * #NULL, just frees and reinits the source error. 233 * 234 * @param src the source error 235 * @param dest the destination error or #NULL 236 */ 237void 238dbus_move_error (DBusError *src, 239 DBusError *dest) 240{ 241 _dbus_return_if_error_is_set (dest); 242 243 if (dest) 244 { 245 dbus_error_free (dest); 246 *dest = *src; 247 dbus_error_init (src); 248 } 249 else 250 dbus_error_free (src); 251} 252 253/** 254 * Checks whether the error is set and has the given 255 * name. 256 * @param error the error 257 * @param name the name 258 * @returns #TRUE if the given named error occurred 259 */ 260dbus_bool_t 261dbus_error_has_name (const DBusError *error, 262 const char *name) 263{ 264 _dbus_return_val_if_fail (error != NULL, FALSE); 265 _dbus_return_val_if_fail (name != NULL, FALSE); 266 267 _dbus_assert ((error->name != NULL && error->message != NULL) || 268 (error->name == NULL && error->message == NULL)); 269 270 if (error->name != NULL) 271 { 272 DBusString str1, str2; 273 _dbus_string_init_const (&str1, error->name); 274 _dbus_string_init_const (&str2, name); 275 return _dbus_string_equal (&str1, &str2); 276 } 277 else 278 return FALSE; 279} 280 281/** 282 * Checks whether an error occurred (the error is set). 283 * 284 * @param error the error object 285 * @returns #TRUE if an error occurred 286 */ 287dbus_bool_t 288dbus_error_is_set (const DBusError *error) 289{ 290 _dbus_return_val_if_fail (error != NULL, FALSE); 291 _dbus_assert ((error->name != NULL && error->message != NULL) || 292 (error->name == NULL && error->message == NULL)); 293 return error->name != NULL; 294} 295 296/** 297 * Assigns an error name and message to a DBusError. 298 * Does nothing if error is #NULL. 299 * 300 * The format may be NULL, which means a default message will be 301 * deduced from the name. If the error name is unknown to D-BUS the 302 * default message will be totally useless, though. 303 * 304 * If no memory can be allocated for the error message, 305 * an out-of-memory error message will be set instead. 306 * 307 * @param error the error. 308 * @param name the error name 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 _dbus_string_free (&str); 362 363 real->name = _dbus_strdup (name); 364 if (real->name == NULL) 365 { 366 dbus_free (real->message); 367 real->message = NULL; 368 goto nomem; 369 } 370 real->const_message = FALSE; 371 372 return; 373 374 nomem: 375 _DBUS_SET_OOM (error); 376} 377 378/** @} */ /* End public API */ 379