chiark / gitweb /
libsystemd-bus: add lightweight object vtable implementation for exposing objects...
[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 bool bus_error_is_dirty(sd_bus_error *e) {
35         if (!e)
36                 return 0;
37
38         return e->name || e->message || e->need_free;
39 }
40
41 void sd_bus_error_free(sd_bus_error *e) {
42         if (!e)
43                 return;
44
45         if (e->need_free) {
46                 free((void*) e->name);
47                 free((void*) e->message);
48         }
49
50         e->name = e->message = NULL;
51         e->need_free = false;
52 }
53
54 int sd_bus_error_set(sd_bus_error *e, const char *name, const char *message) {
55         char *n, *m = NULL;
56
57         if (!e)
58                 return 0;
59         if (bus_error_is_dirty(e))
60                 return -EINVAL;
61         if (!name)
62                 return -EINVAL;
63
64         n = strdup(name);
65         if (!n)
66                 return -ENOMEM;
67
68         if (message) {
69                 m = strdup(message);
70                 if (!m)
71                         return -ENOMEM;
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_setf(sd_bus_error *e, const char *name, const char *format, ...) {
82         char *n, *m = NULL;
83         va_list ap;
84         int r;
85
86         if (!e)
87                 return 0;
88         if (bus_error_is_dirty(e))
89                 return -EINVAL;
90         if (!name)
91                 return -EINVAL;
92
93         n = strdup(name);
94         if (!n)
95                 return -ENOMEM;
96
97         if (format) {
98                 va_start(ap, format);
99                 r = vasprintf(&m, format, ap);
100                 va_end(ap);
101
102                 if (r < 0) {
103                         free(n);
104                         return -ENOMEM;
105                 }
106         }
107
108         e->name = n;
109         e->message = m;
110         e->need_free = true;
111
112         return 0;
113 }
114
115 int sd_bus_error_copy(sd_bus_error *dest, const sd_bus_error *e) {
116         char *x, *y = NULL;
117
118         if (!dest)
119                 return 0;
120         if (bus_error_is_dirty(dest))
121                 return -EINVAL;
122         if (!sd_bus_error_is_set(e))
123                 return 0;
124
125         x = strdup(e->name);
126         if (!x)
127                 return -ENOMEM;
128
129         if (e->message) {
130                 y = strdup(e->message);
131                 if (!y) {
132                         free(x);
133                         return -ENOMEM;
134                 }
135         }
136
137         dest->name = x;
138         dest->message = y;
139         dest->need_free = true;
140         return 0;
141 }
142
143 void sd_bus_error_set_const(sd_bus_error *e, const char *name, const char *message) {
144         if (!e)
145                 return;
146         if (bus_error_is_dirty(e))
147                 return;
148
149         *e = SD_BUS_ERROR_MAKE(name, message);
150 }
151
152 int sd_bus_error_is_set(const sd_bus_error *e) {
153         if (!e)
154                 return 0;
155
156         return !!e->name;
157 }
158
159 int sd_bus_error_has_name(const sd_bus_error *e, const char *name) {
160         if (!e)
161                 return 0;
162
163         return streq_ptr(e->name, name);
164 }
165
166 int bus_error_to_errno(const sd_bus_error* e) {
167
168         /* Better replce this with a gperf table */
169
170         if (!e)
171                 return -EIO;
172
173         if (!e->name)
174                 return -EIO;
175
176         if (streq(e->name, "org.freedesktop.DBus.Error.NoMemory"))
177                 return -ENOMEM;
178
179         if (streq(e->name, "org.freedesktop.DBus.Error.AuthFailed") ||
180             streq(e->name, "org.freedesktop.DBus.Error.AccessDenied"))
181                 return -EPERM;
182
183         if (streq(e->name, "org.freedesktop.DBus.Error.InvalidArgs"))
184                 return -EINVAL;
185
186         if (streq(e->name, "org.freedesktop.DBus.Error.UnixProcessIdUnknown"))
187                 return -ESRCH;
188
189         if (streq(e->name, "org.freedesktop.DBus.Error.FileNotFound"))
190                 return -ENOENT;
191
192         if (streq(e->name, "org.freedesktop.DBus.Error.FileExists"))
193                 return -EEXIST;
194
195         if (streq(e->name, "org.freedesktop.DBus.Error.Timeout"))
196                 return -ETIMEDOUT;
197
198         if (streq(e->name, "org.freedesktop.DBus.Error.IOError"))
199                 return -EIO;
200
201         if (streq(e->name, "org.freedesktop.DBus.Error.Disconnected"))
202                 return -ECONNRESET;
203
204         if (streq(e->name, "org.freedesktop.DBus.Error.NotSupported"))
205                 return -ENOTSUP;
206
207         return -EIO;
208 }
209
210 int bus_error_from_errno(sd_bus_error *e, int error) {
211         if (!e)
212                 return error;
213
214         switch (error) {
215
216         case -ENOMEM:
217                 sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.NoMemory", "Out of memory");
218                 break;
219
220         case -EPERM:
221         case -EACCES:
222                 sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.AccessDenied", "Access denied");
223                 break;
224
225         case -EINVAL:
226                 sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid argument");
227                 break;
228
229         case -ESRCH:
230                 sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.UnixProcessIdUnknown", "No such process");
231                 break;
232
233         case -ENOENT:
234                 sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.FileNotFound", "File not found");
235                 break;
236
237         case -EEXIST:
238                 sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.FileExists", "File exists");
239                 break;
240
241         case -ETIMEDOUT:
242         case -ETIME:
243                 sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.Timeout", "Timed out");
244                 break;
245
246         case -EIO:
247                 sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.IOError", "Input/output error");
248                 break;
249
250         case -ENETRESET:
251         case -ECONNABORTED:
252         case -ECONNRESET:
253                 sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.Disconnected", "Disconnected");
254                 break;
255
256         case -ENOTSUP:
257                 sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.NotSupported", "Not supported");
258                 break;
259         }
260
261         sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.Failed", "Operation failed");
262         return error;
263 }
264
265 const char *bus_error_message(const sd_bus_error *e, int error) {
266         if (e && e->message)
267                 return e->message;
268
269         return strerror(error);
270 }