(linenum→info "unix/slp.c:2238")

dbus/1.0.2/dbus/dbus-errors.c

    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:  */
   41: typedef struct
   42: {
   43:   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:  */
   65: static const char*
   66: message_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:  * By convention, all functions allow #NULL instead of a DBusError*,
  128:  * so callers who don't care about the error can ignore it.
  129:  * 
  130:  * There are some rules. An error passed to a D-Bus function must
  131:  * always be unset; you can't pass in an error that's already set.  If
  132:  * a function has a return code indicating whether an error occurred,
  133:  * and also a #DBusError parameter, then the error will always be set
  134:  * if and only if the return code indicates an error occurred. i.e.
  135:  * the return code and the error are never going to disagree.
  136:  *
  137:  * An error only needs to be freed if it's been set, not if
  138:  * it's merely been initialized.
  139:  *
  140:  * You can check the specific error that occurred using
  141:  * dbus_error_has_name().
  142:  * 
  143:  * Errors will not be set for programming errors, such as passing
  144:  * invalid arguments to the libdbus API. Instead, libdbus will print
  145:  * warnings, exit on a failed assertion, or even crash in those cases
  146:  * (in other words, incorrect use of the API results in undefined
  147:  * behavior, possibly accompanied by helpful debugging output if
  148:  * you're lucky).
  149:  * 
  150:  * @{
  151:  */
  152: 
  153: /**
  154:  * Initializes a DBusError structure. Does not allocate any memory;
  155:  * the error only needs to be freed if it is set at some point.
  156:  *
  157:  * @param error the DBusError.
  158:  */
  159: void
  160: dbus_error_init (DBusError *error)
  161: {
  162:   DBusRealError *real;
  163: 
  164:   _dbus_return_if_fail (error != NULL);
  165: 
  166:   _dbus_assert (sizeof (DBusError) == sizeof (DBusRealError));
  167: 
  168:   real = (DBusRealError *)error;
  169:   
  170:   real->name = NULL;  
  171:   real->message = NULL;
  172: 
  173:   real->const_message = TRUE;
  174: }
  175: 
  176: /**
  177:  * Frees an error that's been set (or just initialized),
  178:  * then reinitializes the error as in dbus_error_init().
  179:  *
  180:  * @param error memory where the error is stored.
  181:  */
  182: void
  183: dbus_error_free (DBusError *error)
  184: {
  185:   DBusRealError *real;
  186: 
  187:   _dbus_return_if_fail (error != NULL);
  188:   
  189:   real = (DBusRealError *)error;
  190: 
  191:   if (!real->const_message)
  192:     {
  193:       dbus_free (real->name);
  194:       dbus_free (real->message);
  195:     }
  196: 
  197:   dbus_error_init (error);
  198: }
  199: 
  200: /**
  201:  * Assigns an error name and message to a DBusError.  Does nothing if
  202:  * error is #NULL. The message may be #NULL, which means a default
  203:  * message will be deduced from the name. The default message will be
  204:  * totally useless, though, so using a #NULL message is not recommended.
  205:  *
  206:  * Because this function does not copy the error name or message, you
  207:  * must ensure the name and message are global data that won't be
  208:  * freed. You probably want dbus_set_error() instead, in most cases.
  209:  * 
  210:  * @param error the error.or #NULL
  211:  * @param name the error name (not copied!!!)
  212:  * @param message the error message (not copied!!!)
  213:  */
  214: void
  215: dbus_set_error_const (DBusError  *error,
  216:                       const char *name,
  217:                       const char *message)
  218: {
  219:   DBusRealError *real;
  220: 
  221:   _dbus_return_if_error_is_set (error);
  222:   _dbus_return_if_fail (name != NULL);
  223:   
  224:   if (error == NULL)
  225:     return;
  226: 
  227:   _dbus_assert (error->name == NULL);
  228:   _dbus_assert (error->message == NULL);
  229: 
  230:   if (message == NULL)
  231:     message = message_from_error (name);
  232:   
  233:   real = (DBusRealError *)error;
  234:   
  235:   real->name = (char*) name;
  236:   real->message = (char *)message;
  237:   real->const_message = TRUE;
  238: }
  239: 
  240: /**
  241:  * Moves an error src into dest, freeing src and
  242:  * overwriting dest. Both src and dest must be initialized.
  243:  * src is reinitialized to an empty error. dest may not
  244:  * contain an existing error. If the destination is
  245:  * #NULL, just frees and reinits the source error.
  246:  * 
  247:  * @param src the source error
  248:  * @param dest the destination error or #NULL
  249:  */
  250: void
  251: dbus_move_error (DBusError *src,
  252:                  DBusError *dest)
  253: {
  254:   _dbus_return_if_error_is_set (dest);
  255: 
  256:   if (dest)
  257:     {
  258:       dbus_error_free (dest);
  259:       *dest = *src;
  260:       dbus_error_init (src);
  261:     }
  262:   else
  263:     dbus_error_free (src);
  264: }
  265: 
  266: /**
  267:  * Checks whether the error is set and has the given
  268:  * name.
  269:  * @param error the error
  270:  * @param name the name
  271:  * @returns #TRUE if the given named error occurred
  272:  */
  273: dbus_bool_t
  274: dbus_error_has_name (const DBusError *error,
  275:                      const char      *name)
  276: {
  277:   _dbus_return_val_if_fail (error != NULL, FALSE);
  278:   _dbus_return_val_if_fail (name != NULL, FALSE);
  279: 
  280:   _dbus_assert ((error->name != NULL && error->message != NULL) ||
  281:                 (error->name == NULL && error->message == NULL));
  282:   
  283:   if (error->name != NULL)
  284:     {
  285:       DBusString str1, str2;
  286:       _dbus_string_init_const (&str1, error->name);
  287:       _dbus_string_init_const (&str2, name);
  288:       return _dbus_string_equal (&str1, &str2);
  289:     }
  290:   else
  291:     return FALSE;
  292: }
  293: 
  294: /**
  295:  * Checks whether an error occurred (the error is set).
  296:  *
  297:  * @param error the error object
  298:  * @returns #TRUE if an error occurred
  299:  */
  300: dbus_bool_t
  301: dbus_error_is_set (const DBusError *error)
  302: {
  303:   _dbus_return_val_if_fail (error != NULL, FALSE);  
  304:   _dbus_assert ((error->name != NULL && error->message != NULL) ||
  305:                 (error->name == NULL && error->message == NULL));
  306:   return error->name != NULL;
  307: }
  308: 
  309: /**
  310:  * Assigns an error name and message to a DBusError.
  311:  * Does nothing if error is #NULL.
  312:  *
  313:  * The format may be #NULL, which means a (pretty much useless)
  314:  * default message will be deduced from the name. This is not a good
  315:  * idea, just go ahead and provide a useful error message. It won't
  316:  * hurt you.
  317:  *
  318:  * If no memory can be allocated for the error message, 
  319:  * an out-of-memory error message will be set instead.
  320:  *
  321:  * @param error the error.or #NULL
  322:  * @param name the error name
  323:  * @param format printf-style format string.
  324:  */
  325: void
  326: dbus_set_error (DBusError  *error,
  327:                 const char *name,
  328:                 const char *format,
  329:                 ...)
  330: {
  331:   DBusRealError *real;
  332:   DBusString str;
  333:   va_list args;
  334:   
  335:   if (error == NULL)
  336:     return;
  337: 
  338:   /* it's a bug to pile up errors */
  339:   _dbus_return_if_error_is_set (error);
  340:   _dbus_return_if_fail (name != NULL);
  341:   
  342:   _dbus_assert (error->name == NULL);
  343:   _dbus_assert (error->message == NULL);
  344: 
  345:   if (!_dbus_string_init (&str))
  346:     goto nomem;
  347:   
  348:   if (format == NULL)
  349:     {
  350:       if (!_dbus_string_append (&str,
  351:                                 message_from_error (name)))
  352:         {
  353:           _dbus_string_free (&str);
  354:           goto nomem;
  355:         }
  356:     }
  357:   else
  358:     {
  359:       va_start (args, format);
  360:       if (!_dbus_string_append_printf_valist (&str, format, args))
  361:         {
  362:           _dbus_string_free (&str);
  363:           goto nomem;
  364:         }
  365:       va_end (args);
  366:     }
  367: 
  368:   real = (DBusRealError *)error;
  369: 
  370:   if (!_dbus_string_steal_data (&str, &real->message))
  371:     {
  372:       _dbus_string_free (&str);
  373:       goto nomem;
  374:     }
  375:   _dbus_string_free (&str);
  376:   
  377:   real->name = _dbus_strdup (name);
  378:   if (real->name == NULL)
  379:     {
  380:       dbus_free (real->message);
  381:       real->message = NULL;
  382:       goto nomem;
  383:     }
  384:   real->const_message = FALSE;
  385: 
  386:   return;
  387:   
  388:  nomem:
  389:   _DBUS_SET_OOM (error);
  390: }
  391: 
  392: /** @} */ /* End public API */
Syntax (Markdown)