1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
32 #include "bus-error.h"
34 bool bus_error_is_dirty(sd_bus_error *e) {
38 return e->name || e->message || e->need_free;
41 void sd_bus_error_free(sd_bus_error *e) {
46 free((void*) e->name);
47 free((void*) e->message);
50 e->name = e->message = NULL;
54 int sd_bus_error_set(sd_bus_error *e, const char *name, const char *message) {
60 assert_return(!bus_error_is_dirty(e), -EINVAL);
61 assert_return(name, -EINVAL);
80 int bus_error_setfv(sd_bus_error *e, const char *name, const char *format, va_list ap) {
87 assert_return(!bus_error_is_dirty(e), -EINVAL);
88 assert_return(name, -EINVAL);
95 r = vasprintf(&m, format, ap);
109 int sd_bus_error_setf(sd_bus_error *e, const char *name, const char *format, ...) {
115 va_start(ap, format);
116 r = bus_error_setfv(e, name, format, ap);
122 return sd_bus_error_set(e, name, NULL);
125 int sd_bus_error_copy(sd_bus_error *dest, const sd_bus_error *e) {
130 if (!sd_bus_error_is_set(e))
133 assert_return(!bus_error_is_dirty(dest), -EINVAL);
140 y = strdup(e->message);
149 dest->need_free = true;
153 int sd_bus_error_set_const(sd_bus_error *e, const char *name, const char *message) {
157 assert_return(!bus_error_is_dirty(e), -EINVAL);
158 assert_return(name, -EINVAL);
160 *e = SD_BUS_ERROR_MAKE(name, message);
164 int sd_bus_error_is_set(const sd_bus_error *e) {
171 int sd_bus_error_has_name(const sd_bus_error *e, const char *name) {
175 return streq_ptr(e->name, name);
178 int sd_bus_error_get_errno(const sd_bus_error* e) {
180 /* Better replce this with a gperf table */
188 if (streq(e->name, SD_BUS_ERROR_NO_MEMORY))
191 if (streq(e->name, SD_BUS_ERROR_SERVICE_UNKNOWN))
194 if (streq(e->name, SD_BUS_ERROR_NAME_HAS_NO_OWNER))
197 if (streq(e->name, SD_BUS_ERROR_NO_REPLY) ||
198 streq(e->name, SD_BUS_ERROR_TIMEOUT) ||
199 streq(e->name, "org.freedesktop.DBus.Error.TimedOut"))
202 if (streq(e->name, SD_BUS_ERROR_IO_ERROR))
205 if (streq(e->name, SD_BUS_ERROR_BAD_ADDRESS))
206 return EADDRNOTAVAIL;
208 if (streq(e->name, SD_BUS_ERROR_NOT_SUPPORTED))
211 if (streq(e->name, SD_BUS_ERROR_LIMITS_EXCEEDED))
214 if (streq(e->name, SD_BUS_ERROR_ACCESS_DENIED) ||
215 streq(e->name, SD_BUS_ERROR_AUTH_FAILED))
218 if (streq(e->name, SD_BUS_ERROR_NO_SERVER))
221 if (streq(e->name, SD_BUS_ERROR_NO_NETWORK))
224 if (streq(e->name, SD_BUS_ERROR_ADDRESS_IN_USE))
227 if (streq(e->name, SD_BUS_ERROR_DISCONNECTED))
230 if (streq(e->name, SD_BUS_ERROR_INVALID_ARGS) ||
231 streq(e->name, SD_BUS_ERROR_INVALID_SIGNATURE) ||
232 streq(e->name, "org.freedesktop.DBus.Error.MatchRuleInvalid") ||
233 streq(e->name, "org.freedesktop.DBus.Error.InvalidFileContent"))
236 if (streq(e->name, SD_BUS_ERROR_FILE_NOT_FOUND) ||
237 streq(e->name, "org.freedesktop.DBus.Error.MatchRuleNotFound"))
240 if (streq(e->name, SD_BUS_ERROR_FILE_EXISTS))
243 if (streq(e->name, SD_BUS_ERROR_UNKNOWN_METHOD) ||
244 streq(e->name, SD_BUS_ERROR_UNKNOWN_OBJECT) ||
245 streq(e->name, SD_BUS_ERROR_UNKNOWN_INTERFACE) ||
246 streq(e->name, SD_BUS_ERROR_UNKNOWN_PROPERTY))
249 if (streq(e->name, SD_BUS_ERROR_PROPERTY_READ_ONLY))
252 if (streq(e->name, SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN) ||
253 streq(e->name, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
256 if (streq(e->name, SD_BUS_ERROR_INCONSISTENT_MESSAGE))
259 if (streq(e->name, "org.freedesktop.DBus.Error.ObjectPathInUse"))
265 static int bus_error_set_strerror_or_const(sd_bus_error *e, const char *name, int error, const char *fallback) {
267 char *n = NULL, *m = NULL;
275 assert_return(!bus_error_is_dirty(e), -EINVAL);
276 assert_return(name, -EINVAL);
286 x = strerror_r(error, m, k);
287 if (errno == ERANGE || strlen(x) >= k - 1) {
301 sd_bus_error_set_const(e, name, x);
322 sd_bus_error_set_const(e, name, fallback);
326 static sd_bus_error map_from_errno(int error) {
334 return SD_BUS_ERROR_MAKE(SD_BUS_ERROR_NO_NETWORK, "Out of memory");
338 return SD_BUS_ERROR_MAKE(SD_BUS_ERROR_ACCESS_DENIED, "Access denied");
341 return SD_BUS_ERROR_MAKE(SD_BUS_ERROR_INVALID_ARGS, "Invalid argument");
344 return SD_BUS_ERROR_MAKE(SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN, "No such process");
347 return SD_BUS_ERROR_MAKE(SD_BUS_ERROR_FILE_NOT_FOUND, "File not found");
350 return SD_BUS_ERROR_MAKE(SD_BUS_ERROR_FILE_EXISTS, "File exists");
354 return SD_BUS_ERROR_MAKE(SD_BUS_ERROR_TIMEOUT, "Timed out");
357 return SD_BUS_ERROR_MAKE(SD_BUS_ERROR_IO_ERROR, "Input/output error");
362 return SD_BUS_ERROR_MAKE(SD_BUS_ERROR_DISCONNECTED, "Disconnected");
365 return SD_BUS_ERROR_MAKE(SD_BUS_ERROR_NOT_SUPPORTED, "Not supported");
368 return SD_BUS_ERROR_MAKE(SD_BUS_ERROR_BAD_ADDRESS, "Address not available");
371 return SD_BUS_ERROR_MAKE(SD_BUS_ERROR_LIMITS_EXCEEDED, "Limits exceeded");
374 return SD_BUS_ERROR_MAKE(SD_BUS_ERROR_ADDRESS_IN_USE, "Address in use");
377 return SD_BUS_ERROR_MAKE(SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Inconsistent message");
380 return SD_BUS_ERROR_MAKE(SD_BUS_ERROR_FAILED, "Operation failed");
383 int sd_bus_error_set_errno(sd_bus_error *e, int error) {
386 x = map_from_errno(error);
388 return bus_error_set_strerror_or_const(e, x.name, error, x.message);
391 int bus_error_set_errnofv(sd_bus_error *e, int error, const char *format, va_list ap) {
401 assert_return(!bus_error_is_dirty(e), -EINVAL);
403 x = map_from_errno(error);
408 r = vasprintf(&m, format, ap);
425 return bus_error_set_strerror_or_const(e, x.name, error, x.message);
428 int sd_bus_error_set_errnof(sd_bus_error *e, int error, const char *format, ...) {
434 assert_return(!bus_error_is_dirty(e), -EINVAL);
439 va_start(ap, format);
440 r = bus_error_set_errnofv(e, error, format, ap);
446 return sd_bus_error_set_errno(e, error);
449 const char *bus_error_message(const sd_bus_error *e, int error) {
457 return strerror(error);