chiark / gitweb /
bus: add basic implementation of a native bus client library
[elogind.git] / src / libsystemd-bus / bus-error.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
25 #include <stdbool.h>
26 #include <string.h>
27 #include <stdio.h>
28
29 #include "util.h"
30
31 #include "sd-bus.h"
32 #include "bus-error.h"
33
34 void sd_bus_error_free(sd_bus_error *e) {
35         if (!e)
36                 return;
37
38         if (e->need_free) {
39                 free((void*) e->name);
40                 free((void*) e->message);
41         }
42
43         e->name = e->message = NULL;
44         e->need_free = false;
45 }
46
47 int sd_bus_error_set(sd_bus_error *e, const char *name, const char *format, ...) {
48         char *n, *m = NULL;
49         va_list ap;
50         int r;
51
52         if (!e)
53                 return 0;
54         if (sd_bus_error_is_set(e))
55                 return -EINVAL;
56         if (!name)
57                 return -EINVAL;
58
59         n = strdup(name);
60         if (!n)
61                 return -ENOMEM;
62
63         if (format) {
64                 va_start(ap, format);
65                 r = vasprintf(&m, format, ap);
66                 va_end(ap);
67
68                 if (r < 0) {
69                         free(n);
70                         return -ENOMEM;
71                 }
72         }
73
74         e->name = n;
75         e->message = m;
76         e->need_free = true;
77
78         return 0;
79 }
80
81 int sd_bus_error_copy(sd_bus_error *dest, const sd_bus_error *e) {
82         if (!dest)
83                 return 0;
84         if (sd_bus_error_is_set(dest))
85                 return -EINVAL;
86         if (!sd_bus_error_is_set(e))
87                 return 0;
88
89         if (e->need_free) {
90                 char *x, *y = NULL;
91
92                 x = strdup(e->name);
93                 if (!x)
94                         return -ENOMEM;
95
96                 if (e->message) {
97                         y = strdup(e->message);
98                         if (!y) {
99                                 free(x);
100                                 return -ENOMEM;
101                         }
102                 }
103
104                 dest->name = x;
105                 dest->message = y;
106                 dest->need_free = true;
107         } else
108                 *dest = *e;
109
110         return 0;
111 }
112
113 void sd_bus_error_set_const(sd_bus_error *e, const char *name, const char *message) {
114         if (!e)
115                 return;
116         if (sd_bus_error_is_set(e))
117                 return;
118
119         e->name = name;
120         e->message = message;
121 }
122
123 int sd_bus_error_is_set(const sd_bus_error *e) {
124         if (!e)
125                 return 0;
126
127         return e->name || e->message || e->need_free;
128 }
129
130 int sd_bus_error_has_name(const sd_bus_error *e, const char *name) {
131         if (!e)
132                 return 0;
133
134         return streq_ptr(e->name, name);
135 }
136
137 int bus_error_to_errno(const sd_bus_error* e) {
138
139         /* Better replce this with a gperf table */
140
141         if (!e->name)
142                 return -EIO;
143
144         if (streq(e->name, "org.freedesktop.DBus.Error.NoMemory"))
145                 return -ENOMEM;
146
147         if (streq(e->name, "org.freedesktop.DBus.Error.AuthFailed") ||
148             streq(e->name, "org.freedesktop.DBus.Error.AccessDenied"))
149                 return -EPERM;
150
151         return -EIO;
152 }
153
154 int bus_error_from_errno(sd_bus_error *e, int error) {
155         if (!e)
156                 return error;
157
158         if (error == -ENOMEM)
159                 sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.NoMemory", strerror(-error));
160         else if (error == -EPERM || error == EACCES)
161                 sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.AccessDenied", strerror(-error));
162         else
163                 sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.Failed", "Operation failed");
164
165         return error;
166 }