2003-03-04 Havoc Pennington <hp@pobox.com>
[platform/upstream/dbus.git] / dbus / dbus-errors.c
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 1.2
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 <stdarg.h>
27 #include <stdio.h>
28
29 /**
30  * @defgroup DBusErrors Error reporting
31  * @ingroup  DBus
32  * @brief Error reporting
33  *
34  * Types and functions related to reporting errors.
35  *
36  *
37  * In essence D-BUS error reporting works as follows:
38  *
39  * @code
40  * DBusResultCode result = DBUS_RESULT_SUCCESS;
41  * dbus_some_function (arg1, arg2, &result);
42  * if (result != DBUS_RESULT_SUCCESS)
43  *   printf ("an error occurred\n");
44  * @endcode
45  *
46  * @todo add docs with DBusError
47  *
48  * @todo add dbus_error_is_set() to check
49  * whether an error is set.
50  * 
51  * @{
52  */
53
54 typedef struct
55 {
56   const char *name; /**< error name */
57   char *message; /**< error message */
58
59   unsigned int const_message : 1; /** Message is not owned by DBusError */
60
61   unsigned int dummy2 : 1; /**< placeholder */
62   unsigned int dummy3 : 1; /**< placeholder */
63   unsigned int dummy4 : 1; /**< placeholder */
64   unsigned int dummy5 : 1; /**< placeholder */
65
66   void *padding1; /**< placeholder */
67   
68 } DBusRealError;
69
70 /**
71  * Set a result code at a result code location,
72  * if code_address is not #NULL.
73  *
74  * @param code_address place to store the result code.
75  * @param code the result code itself.
76  */
77 void
78 dbus_set_result (DBusResultCode *code_address,
79                  DBusResultCode  code)
80 {
81   if (code_address)
82     *code_address = code;
83 }
84
85 /**
86  * Returns a string describing the given result code.
87  *
88  * @param code the result code to describe.
89  * @returns a constant string describing the code.
90  */
91 const char*
92 dbus_result_to_string (DBusResultCode code)
93 {
94   /* This is a switch to the compiler will complain if we
95    * aren't handling some codes
96    */
97   switch (code)
98     {
99     case DBUS_RESULT_SUCCESS:
100       return "Success";
101     case DBUS_RESULT_FAILED:
102       return "Unknown error";
103     case DBUS_RESULT_NO_MEMORY:
104       return "Not enough memory available";
105     case DBUS_RESULT_IO_ERROR:
106       return "Error reading or writing data";
107     case DBUS_RESULT_BAD_ADDRESS:
108       return "Could not parse address";
109     case DBUS_RESULT_NOT_SUPPORTED:
110       return "Feature not supported";
111     case DBUS_RESULT_LIMITS_EXCEEDED:
112       return "Resource limits exceeded";
113     case DBUS_RESULT_ACCESS_DENIED:
114       return "Permission denied";
115     case DBUS_RESULT_AUTH_FAILED:
116       return "Could not authenticate to server";
117     case DBUS_RESULT_NO_SERVER:
118       return "No server";
119     case DBUS_RESULT_TIMEOUT:
120       return "Connection timed out";
121     case DBUS_RESULT_NO_NETWORK:
122       return "Network unavailable";
123     case DBUS_RESULT_ADDRESS_IN_USE:
124       return "Address already in use";
125     case DBUS_RESULT_DISCONNECTED:
126       return "Disconnected.";
127     case DBUS_RESULT_INVALID_ARGS:
128       return "Invalid argumemts.";
129     case DBUS_RESULT_NO_REPLY:
130       return "Did not get a reply message.";
131     case DBUS_RESULT_FILE_NOT_FOUND:
132       return "File doesn't exist.";
133       
134       /* no default, it would break our compiler warnings */
135     }
136
137   return "Invalid error code";
138 }
139
140 /**
141  * Initializes a DBusError structure.
142  * 
143  * @todo calling dbus_error_init() in here is no good,
144  * for the same reason a GError* has to be set to NULL
145  * before you pass it in.
146  *
147  * @param error the DBusError.
148  */
149 void
150 dbus_error_init (DBusError *error)
151 {
152   DBusRealError *real;
153
154   _dbus_assert (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 created by dbus_error_init().
168  *
169  * @param error memory where the error is stored.
170  */
171 void
172 dbus_error_free (DBusError *error)
173 {
174   DBusRealError *real;
175
176   real = (DBusRealError *)error;
177
178   if (!real->const_message)
179     dbus_free (real->message);
180 }
181
182 /**
183  * Assigns an error name and message to a DBusError.
184  * Does nothing if error is #NULL.
185  *
186  * @param error the error.
187  * @param name the error name (not copied!!!)
188  * @param message the error message (not copied!!!)
189  */
190 void
191 dbus_set_error_const (DBusError  *error,
192                       const char *name,
193                       const char *message)
194 {
195   DBusRealError *real;
196
197   if (error == NULL)
198     return;
199
200   /* it's a bug to pile up errors */
201   _dbus_assert (error->name == NULL);
202   _dbus_assert (error->message == NULL);
203   _dbus_assert (name != NULL);
204   _dbus_assert (message != NULL);
205   
206   real = (DBusRealError *)error;
207   
208   real->name = name;
209   real->message = (char *)message;
210   real->const_message = TRUE;
211 }
212
213 /**
214  * Checks whether the error is set and has the given
215  * name.
216  * @param error the error
217  * @param name the name
218  * @returns #TRUE if the given named error occurred
219  */
220 dbus_bool_t
221 dbus_error_has_name (const DBusError *error,
222                      const char      *name)
223 {
224   _dbus_assert (error != NULL);
225   _dbus_assert (name != NULL);
226   _dbus_assert ((error->name != NULL && error->message != NULL) ||
227                 (error->name == NULL && error->message == NULL));
228   
229   if (error->name != NULL)
230     {
231       DBusString str1, str2;
232       _dbus_string_init_const (&str1, error->name);
233       _dbus_string_init_const (&str2, name);
234       return _dbus_string_equal (&str1, &str2);
235     }
236   else
237     return FALSE;
238 }
239
240 /**
241  * Checks whether an error occurred (the error is set).
242  *
243  * @param error the error object
244  * @returns #TRUE if an error occurred
245  */
246 dbus_bool_t
247 dbus_error_is_set (const DBusError *error)
248 {
249   _dbus_assert (error != NULL);
250   _dbus_assert ((error->name != NULL && error->message != NULL) ||
251                 (error->name == NULL && error->message == NULL));
252   return error->name != NULL;
253 }
254
255 /**
256  * Assigns an error name and message to a DBusError.
257  * Does nothing if error is #NULL.
258  *
259  * If no memory can be allocated for the error message, 
260  * an out-of-memory error message will be set instead.
261  *
262  * @todo stdio.h shouldn't be included in this file,
263  * should write _dbus_string_append_printf instead
264  * 
265  * @param error the error.
266  * @param name the error name (not copied!!!)
267  * @param format printf-style format string.
268  */
269 void
270 dbus_set_error (DBusError  *error,
271                 const char *name,
272                 const char *format,
273                 ...)
274 {
275   DBusRealError *real;
276   va_list args;
277   int message_length;
278   char *message;
279   char c;
280
281   if (error == NULL)
282     return;
283
284   /* it's a bug to pile up errors */
285   _dbus_assert (error->name == NULL);
286   _dbus_assert (error->message == NULL);
287   _dbus_assert (name != NULL);
288   _dbus_assert (format != NULL);
289   
290   va_start (args, format);
291   /* Measure the message length */
292   message_length = vsnprintf (&c, 1, format, args) + 1;
293   va_end (args);
294   
295   message = dbus_malloc (message_length);
296   
297   if (!message)
298     {
299       dbus_set_error_const (error, DBUS_ERROR_NO_MEMORY,
300                             "Failed to allocate memory for error message.");
301       return;
302     }
303   
304   va_start (args, format);  
305   vsprintf (message, format, args);  
306   va_end (args);
307
308   real = (DBusRealError *)error;
309   
310   real->name = name;
311   real->message = message;
312   real->const_message = FALSE;
313 }
314
315 /** @} */