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