]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-error.c
bus: introduce bus_error_is_dirty() independently of sd_bus_error_is_set()
[thirdparty/systemd.git] / src / libsystemd-bus / bus-error.c
CommitLineData
de1c301e
LP
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
fbfa72b0
LP
34bool 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
de1c301e
LP
41void 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
54int 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;
fbfa72b0 61 if (bus_error_is_dirty(e))
de1c301e
LP
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
88int sd_bus_error_copy(sd_bus_error *dest, const sd_bus_error *e) {
89 if (!dest)
90 return 0;
fbfa72b0 91 if (bus_error_is_dirty(dest))
de1c301e
LP
92 return -EINVAL;
93 if (!sd_bus_error_is_set(e))
94 return 0;
95
96 if (e->need_free) {
97 char *x, *y = NULL;
98
99 x = strdup(e->name);
100 if (!x)
101 return -ENOMEM;
102
103 if (e->message) {
104 y = strdup(e->message);
105 if (!y) {
106 free(x);
107 return -ENOMEM;
108 }
109 }
110
111 dest->name = x;
112 dest->message = y;
113 dest->need_free = true;
114 } else
115 *dest = *e;
116
117 return 0;
118}
119
120void sd_bus_error_set_const(sd_bus_error *e, const char *name, const char *message) {
121 if (!e)
122 return;
fbfa72b0 123 if (bus_error_is_dirty(e))
de1c301e
LP
124 return;
125
126 e->name = name;
127 e->message = message;
fbfa72b0 128 e->need_free = false;
de1c301e
LP
129}
130
131int sd_bus_error_is_set(const sd_bus_error *e) {
132 if (!e)
133 return 0;
134
fbfa72b0 135 return !!e->name;
de1c301e
LP
136}
137
138int sd_bus_error_has_name(const sd_bus_error *e, const char *name) {
139 if (!e)
140 return 0;
141
142 return streq_ptr(e->name, name);
143}
144
145int bus_error_to_errno(const sd_bus_error* e) {
146
147 /* Better replce this with a gperf table */
148
149 if (!e->name)
150 return -EIO;
151
152 if (streq(e->name, "org.freedesktop.DBus.Error.NoMemory"))
153 return -ENOMEM;
154
155 if (streq(e->name, "org.freedesktop.DBus.Error.AuthFailed") ||
156 streq(e->name, "org.freedesktop.DBus.Error.AccessDenied"))
157 return -EPERM;
158
159 return -EIO;
160}
161
162int bus_error_from_errno(sd_bus_error *e, int error) {
163 if (!e)
164 return error;
165
166 if (error == -ENOMEM)
167 sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.NoMemory", strerror(-error));
168 else if (error == -EPERM || error == EACCES)
169 sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.AccessDenied", strerror(-error));
170 else
171 sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.Failed", "Operation failed");
172
173 return error;
174}