Line data Source code
1 : /*
2 : Authors:
3 : Pavel Březina <pbrezina@redhat.com>
4 :
5 : Copyright (C) 2014 Red Hat
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <dbus/dbus.h>
22 : #include <stdlib.h>
23 : #include <string.h>
24 :
25 : #include "lib/sifp/sss_sifp.h"
26 : #include "lib/sifp/sss_sifp_dbus.h"
27 : #include "lib/sifp/sss_sifp_private.h"
28 :
29 : #define DBUS_IFACE_PROP "org.freedesktop.DBus.Properties"
30 :
31 296 : static void * default_alloc(size_t size, void *pvt)
32 : {
33 296 : return malloc(size);
34 : }
35 :
36 303 : static void default_free(void *ptr, void *pvt)
37 : {
38 303 : free(ptr);
39 303 : }
40 :
41 6 : static DBusMessage * sss_sifp_create_prop_msg(const char *object_path,
42 : const char *method)
43 : {
44 6 : return sss_sifp_create_message(object_path, DBUS_IFACE_PROP, method);
45 : }
46 :
47 : sss_sifp_error
48 46 : sss_sifp_init(sss_sifp_ctx **_ctx)
49 : {
50 46 : return sss_sifp_init_ex(NULL, default_alloc, default_free, _ctx);
51 : }
52 :
53 : sss_sifp_error
54 46 : sss_sifp_init_ex(void *alloc_pvt,
55 : sss_sifp_alloc_func *alloc_func,
56 : sss_sifp_free_func *free_func,
57 : sss_sifp_ctx **_ctx)
58 : {
59 46 : sss_sifp_ctx *ctx = NULL;
60 46 : DBusConnection *conn = NULL;
61 : DBusError dbus_error;
62 : sss_sifp_error ret;
63 :
64 46 : if (_ctx == NULL || alloc_func == NULL || free_func == NULL) {
65 0 : return SSS_SIFP_INVALID_ARGUMENT;
66 : }
67 :
68 46 : dbus_error_init(&dbus_error);
69 :
70 46 : ctx = alloc_func(sizeof(sss_sifp_ctx), alloc_pvt);
71 46 : if (ctx == NULL) {
72 0 : ret = SSS_SIFP_OUT_OF_MEMORY;
73 0 : goto done;
74 : }
75 :
76 46 : ctx->conn = NULL;
77 46 : ctx->alloc_fn = alloc_func;
78 46 : ctx->free_fn = free_func;
79 46 : ctx->alloc_pvt = alloc_pvt;
80 46 : ctx->io_error = alloc_func(sizeof(DBusError), alloc_pvt);
81 46 : if (ctx->io_error == NULL) {
82 0 : ret = SSS_SIFP_OUT_OF_MEMORY;
83 0 : goto done;
84 : }
85 :
86 46 : dbus_error_init(ctx->io_error);
87 :
88 46 : conn = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error);
89 46 : if (dbus_error_is_set(&dbus_error)) {
90 0 : sss_sifp_set_io_error(ctx, &dbus_error);
91 0 : ret = SSS_SIFP_IO_ERROR;
92 0 : goto done;
93 : }
94 :
95 46 : ctx->conn = conn;
96 46 : *_ctx = ctx;
97 :
98 46 : ret = SSS_SIFP_OK;
99 :
100 : done:
101 46 : if (ret != SSS_SIFP_OK) {
102 0 : sss_sifp_free(&ctx);
103 : }
104 :
105 46 : dbus_error_free(&dbus_error);
106 46 : return ret;
107 : }
108 :
109 : const char *
110 0 : sss_sifp_get_last_io_error_name(sss_sifp_ctx *ctx)
111 : {
112 0 : if (ctx == NULL) {
113 0 : return "Invalid sss_sifp context";
114 : }
115 :
116 0 : if (!dbus_error_is_set(ctx->io_error)) {
117 0 : return NULL;
118 : }
119 :
120 0 : return ctx->io_error->name;
121 : }
122 :
123 : const char *
124 0 : sss_sifp_get_last_io_error_message(sss_sifp_ctx *ctx)
125 : {
126 0 : if (ctx == NULL) {
127 0 : return "Invalid sss_sifp context";
128 : }
129 :
130 0 : if (!dbus_error_is_set(ctx->io_error)) {
131 0 : return NULL;
132 : }
133 :
134 0 : return ctx->io_error->message;
135 : }
136 :
137 : sss_sifp_error
138 3 : sss_sifp_fetch_attr(sss_sifp_ctx *ctx,
139 : const char *object_path,
140 : const char *interface,
141 : const char *name,
142 : sss_sifp_attr ***_attrs)
143 : {
144 3 : DBusMessage *msg = NULL;
145 3 : DBusMessage *reply = NULL;
146 : dbus_bool_t bret;
147 : sss_sifp_error ret;
148 :
149 3 : if (ctx == NULL || object_path == NULL || interface == NULL
150 3 : || name == NULL || _attrs == NULL) {
151 0 : return SSS_SIFP_INVALID_ARGUMENT;
152 : }
153 :
154 : /* Message format:
155 : * In: string:interface
156 : * In: string:attribute
157 : * Out: variant(misc:value)
158 : */
159 :
160 3 : msg = sss_sifp_create_prop_msg(object_path, "Get");
161 3 : if (msg == NULL) {
162 0 : ret = SSS_SIFP_OUT_OF_MEMORY;
163 0 : goto done;
164 : }
165 :
166 3 : bret = dbus_message_append_args(msg, DBUS_TYPE_STRING, &interface,
167 : DBUS_TYPE_STRING, &name,
168 : DBUS_TYPE_INVALID);
169 3 : if (!bret) {
170 0 : ret = SSS_SIFP_OUT_OF_MEMORY;
171 0 : goto done;
172 : }
173 :
174 3 : ret = sss_sifp_send_message(ctx, msg, &reply);
175 3 : if (ret != SSS_SIFP_OK) {
176 0 : goto done;
177 : }
178 :
179 3 : ret = sss_sifp_parse_attr(ctx, name, reply, _attrs);
180 :
181 : done:
182 3 : if (msg != NULL) {
183 3 : dbus_message_unref(msg);
184 : }
185 :
186 3 : if (reply != NULL) {
187 3 : dbus_message_unref(reply);
188 : }
189 :
190 3 : return ret;
191 : }
192 :
193 : sss_sifp_error
194 3 : sss_sifp_fetch_all_attrs(sss_sifp_ctx *ctx,
195 : const char *object_path,
196 : const char *interface,
197 : sss_sifp_attr ***_attrs)
198 : {
199 3 : DBusMessage *msg = NULL;
200 3 : DBusMessage *reply = NULL;
201 : dbus_bool_t bret;
202 : sss_sifp_error ret;
203 :
204 3 : if (ctx == NULL || object_path == NULL || interface == NULL
205 3 : || _attrs == NULL) {
206 0 : return SSS_SIFP_INVALID_ARGUMENT;
207 : }
208 :
209 3 : msg = sss_sifp_create_prop_msg(object_path, "GetAll");
210 3 : if (msg == NULL) {
211 0 : ret = SSS_SIFP_OUT_OF_MEMORY;
212 0 : goto done;
213 : }
214 :
215 3 : bret = dbus_message_append_args(msg, DBUS_TYPE_STRING, &interface,
216 : DBUS_TYPE_INVALID);
217 3 : if (!bret) {
218 0 : ret = SSS_SIFP_OUT_OF_MEMORY;
219 0 : goto done;
220 : }
221 :
222 3 : ret = sss_sifp_send_message(ctx, msg, &reply);
223 3 : if (ret != SSS_SIFP_OK) {
224 0 : goto done;
225 : }
226 :
227 3 : ret = sss_sifp_parse_attr_list(ctx, reply, _attrs);
228 :
229 : done:
230 3 : if (msg != NULL) {
231 3 : dbus_message_unref(msg);
232 : }
233 :
234 3 : if (reply != NULL) {
235 3 : dbus_message_unref(reply);
236 : }
237 :
238 3 : return ret;
239 : }
240 :
241 : sss_sifp_error
242 2 : sss_sifp_fetch_object(sss_sifp_ctx *ctx,
243 : const char *object_path,
244 : const char *interface,
245 : sss_sifp_object **_object)
246 : {
247 2 : sss_sifp_object *object = NULL;
248 2 : sss_sifp_attr **attrs = NULL;
249 2 : const char *name = NULL;
250 : sss_sifp_error ret;
251 :
252 2 : if (ctx == NULL || object_path == NULL || interface == NULL
253 2 : || _object == NULL) {
254 0 : return SSS_SIFP_INVALID_ARGUMENT;
255 : }
256 :
257 2 : ret = sss_sifp_fetch_all_attrs(ctx, object_path, interface, &attrs);
258 2 : if (ret != SSS_SIFP_OK) {
259 0 : goto done;
260 : }
261 :
262 2 : ret = sss_sifp_find_attr_as_string(attrs, "name", &name);
263 2 : if (ret != SSS_SIFP_OK) {
264 0 : goto done;
265 : }
266 :
267 2 : object = _alloc_zero(ctx, sss_sifp_object, 1);
268 2 : if (object == NULL) {
269 0 : ret = SSS_SIFP_OUT_OF_MEMORY;
270 0 : goto done;
271 : }
272 :
273 2 : object->attrs = attrs;
274 :
275 2 : object->name = sss_sifp_strdup(ctx, name);
276 2 : if (object->name == NULL) {
277 0 : ret = SSS_SIFP_OUT_OF_MEMORY;
278 0 : goto done;
279 : }
280 :
281 2 : object->object_path = sss_sifp_strdup(ctx, object_path);
282 2 : if (object->object_path == NULL) {
283 0 : ret = SSS_SIFP_OUT_OF_MEMORY;
284 0 : goto done;
285 : }
286 :
287 2 : object->interface = sss_sifp_strdup(ctx, interface);
288 2 : if (object->interface == NULL) {
289 0 : ret = SSS_SIFP_OUT_OF_MEMORY;
290 0 : goto done;
291 : }
292 :
293 2 : *_object = object;
294 :
295 2 : ret = SSS_SIFP_OK;
296 :
297 : done:
298 2 : if (ret != SSS_SIFP_OK) {
299 0 : sss_sifp_free_object(ctx, &object);
300 : }
301 :
302 2 : return ret;
303 : }
304 :
305 : void
306 46 : sss_sifp_free(sss_sifp_ctx **_ctx)
307 : {
308 46 : sss_sifp_ctx *ctx = NULL;
309 :
310 46 : if (_ctx == NULL || *_ctx == NULL) {
311 0 : return;
312 : }
313 :
314 46 : ctx = *_ctx;
315 :
316 46 : if (ctx->conn != NULL) {
317 0 : dbus_connection_unref(ctx->conn);
318 : }
319 :
320 46 : if (ctx->io_error != NULL) {
321 46 : dbus_error_free(ctx->io_error);
322 46 : _free(ctx, ctx->io_error);
323 : }
324 :
325 46 : _free(ctx, ctx);
326 46 : *_ctx = NULL;
327 :
328 46 : return;
329 : }
330 :
331 : void
332 34 : sss_sifp_free_attrs(sss_sifp_ctx *ctx,
333 : sss_sifp_attr ***_attrs)
334 : {
335 34 : sss_sifp_attr **attrs = NULL;
336 : unsigned int i, j;
337 :
338 34 : if (_attrs == NULL || *_attrs == NULL) {
339 2 : return;
340 : }
341 :
342 32 : attrs = *_attrs;
343 :
344 71 : for (i = 0; attrs[i] != NULL; i++) {
345 39 : switch (attrs[i]->type) {
346 : case SSS_SIFP_ATTR_TYPE_BOOL:
347 3 : _free(ctx, attrs[i]->data.boolean);
348 3 : break;
349 : case SSS_SIFP_ATTR_TYPE_INT16:
350 1 : _free(ctx, attrs[i]->data.int16);
351 1 : break;
352 : case SSS_SIFP_ATTR_TYPE_UINT16:
353 1 : _free(ctx, attrs[i]->data.uint16);
354 1 : break;
355 : case SSS_SIFP_ATTR_TYPE_INT32:
356 3 : _free(ctx, attrs[i]->data.int32);
357 3 : break;
358 : case SSS_SIFP_ATTR_TYPE_UINT32:
359 10 : _free(ctx, attrs[i]->data.uint32);
360 10 : break;
361 : case SSS_SIFP_ATTR_TYPE_INT64:
362 3 : _free(ctx, attrs[i]->data.int64);
363 3 : break;
364 : case SSS_SIFP_ATTR_TYPE_UINT64:
365 3 : _free(ctx, attrs[i]->data.uint64);
366 3 : break;
367 : case SSS_SIFP_ATTR_TYPE_STRING:
368 32 : for (j = 0; j < attrs[i]->num_values; j++) {
369 18 : _free(ctx, attrs[i]->data.str[j]);
370 : }
371 14 : _free(ctx, attrs[i]->data.str);
372 14 : break;
373 : case SSS_SIFP_ATTR_TYPE_STRING_DICT:
374 1 : if (attrs[i]->data.str_dict != NULL) {
375 1 : hash_destroy(attrs[i]->data.str_dict);
376 : }
377 1 : attrs[i]->data.str_dict = NULL;
378 1 : break;
379 : }
380 39 : _free(ctx, attrs[i]->name);
381 39 : _free(ctx, attrs[i]);
382 : }
383 :
384 32 : _free(ctx, attrs);
385 :
386 32 : *_attrs = NULL;
387 : }
388 :
389 : void
390 2 : sss_sifp_free_object(sss_sifp_ctx *ctx,
391 : sss_sifp_object **_object)
392 : {
393 2 : sss_sifp_object *object = NULL;
394 :
395 2 : if (_object == NULL || *_object == NULL) {
396 0 : return;
397 : }
398 :
399 2 : object = *_object;
400 :
401 2 : sss_sifp_free_attrs(ctx, &object->attrs);
402 2 : _free(ctx, object->object_path);
403 2 : _free(ctx, object->interface);
404 2 : _free(ctx, object->name);
405 2 : _free(ctx, object);
406 :
407 2 : *_object = NULL;
408 : }
409 :
410 : void
411 14 : sss_sifp_free_string(sss_sifp_ctx *ctx,
412 : char **_str)
413 : {
414 14 : if (_str == NULL || *_str == NULL) {
415 0 : return;
416 : }
417 :
418 14 : _free(ctx, *_str);
419 :
420 14 : *_str = NULL;
421 : }
422 :
423 : void
424 5 : sss_sifp_free_string_array(sss_sifp_ctx *ctx,
425 : char ***_str_array)
426 : {
427 5 : char **str_array = NULL;
428 : int i;
429 :
430 5 : if (_str_array == NULL || *_str_array == NULL) {
431 0 : return;
432 : }
433 :
434 5 : str_array = *_str_array;
435 :
436 15 : for (i = 0; str_array[i] != NULL; i++) {
437 10 : _free(ctx, str_array[i]);
438 : }
439 :
440 5 : _free(ctx, str_array);
441 :
442 5 : *_str_array = NULL;
443 : }
|