Imported Upstream version 2
[platform/upstream/buxton.git] / src / libbuxton / lbuxton.c
1 /*
2  * This file is part of buxton.
3  *
4  * Copyright (C) 2013 Intel Corporation
5  *
6  * buxton is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1
9  * of the License, or (at your option) any later version.
10  */
11
12 /**
13  * \file lbuxton.c Buxton library implementation
14  */
15 #ifdef HAVE_CONFIG_H
16         #include "config.h"
17 #endif
18
19 #include <assert.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <sys/socket.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <sys/un.h>
29 #include <dirent.h>
30 #include <string.h>
31 #include <stdint.h>
32
33 #include "buxton.h"
34 #include "buxtonclient.h"
35 #include "buxtonkey.h"
36 #include "buxtonresponse.h"
37 #include "buxtonstring.h"
38 #include "configurator.h"
39 #include "hashmap.h"
40 #include "log.h"
41 #include "protocol.h"
42 #include "util.h"
43
44
45 int buxton_set_conf_file(char *path)
46 {
47         int r;
48         struct stat st;
49
50         r = stat(path, &st);
51         if (r == -1) {
52                 return errno;
53         } else {
54                 if (st.st_mode & S_IFDIR) {
55                         return EINVAL;
56                 }
57         }
58
59         buxton_add_cmd_line(CONFIG_CONF_FILE, path);
60
61         return 0;
62 }
63
64 int buxton_open(BuxtonClient *client)
65 {
66         _BuxtonClient **c = (_BuxtonClient **)client;
67         _BuxtonClient *cl = NULL;
68         int bx_socket, r;
69         struct sockaddr_un remote;
70         size_t sock_name_len;
71
72         if ((bx_socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
73                 return -1;
74         }
75
76         remote.sun_family = AF_UNIX;
77         sock_name_len = strlen(buxton_socket()) + 1;
78         if (sock_name_len >= sizeof(remote.sun_path)) {
79                 buxton_log("Provided socket name: %s is too long, maximum allowed length is %d bytes\n",
80                            buxton_socket(), sizeof(remote.sun_path));
81                 return -1;
82         }
83
84         strncpy(remote.sun_path, buxton_socket(), sock_name_len);
85         r = connect(bx_socket, (struct sockaddr *)&remote, sizeof(remote));
86         if ( r == -1) {
87                 close(bx_socket);
88                 return -1;
89         }
90
91         if (fcntl(bx_socket, F_SETFL, O_NONBLOCK)) {
92                 close(bx_socket);
93                 return -1;
94         }
95
96         if (!setup_callbacks()) {
97                 close(bx_socket);
98                 return -1;
99         }
100
101         cl = malloc0(sizeof(_BuxtonClient));
102         if (!cl) {
103                 close(bx_socket);
104                 return -1;
105         }
106
107         cl->fd = bx_socket;
108         *c = cl;
109
110         return bx_socket;
111 }
112
113 void buxton_close(BuxtonClient client)
114 {
115         _BuxtonClient *c;
116         if (!client) {
117                 return;
118         }
119
120         c = (_BuxtonClient *)client;
121
122         cleanup_callbacks();
123         close(c->fd);
124         c->direct = 0;
125         c->fd = -1;
126         free(c);
127 }
128
129 int buxton_get_value(BuxtonClient client,
130                      BuxtonKey key,
131                      BuxtonCallback callback,
132                      void *data,
133                      bool sync)
134 {
135         bool r;
136         int ret = 0;
137         _BuxtonKey *k = (_BuxtonKey *)key;
138
139         if (!k || !(k->group.value) || !(k->name.value) ||
140             k->type <= BUXTON_TYPE_MIN || k->type >= BUXTON_TYPE_MAX) {
141                 return EINVAL;
142         }
143
144         r = buxton_wire_get_value((_BuxtonClient *)client, k, callback, data);
145         if (!r) {
146                 return -1;
147         }
148
149         if (sync) {
150                 ret = buxton_wire_get_response(client);
151                 if (ret <= 0) {
152                         ret = -1;
153                 } else {
154                         ret = 0;
155                 }
156         }
157
158         return ret;
159 }
160
161 int buxton_register_notification(BuxtonClient client,
162                                  BuxtonKey key,
163                                  BuxtonCallback callback,
164                                  void *data,
165                                  bool sync)
166 {
167         bool r;
168         int ret = 0;
169         _BuxtonKey *k = (_BuxtonKey *)key;
170
171         if (!k || !k->group.value || !k->name.value ||
172             k->type <= BUXTON_TYPE_MIN || k->type >= BUXTON_TYPE_MAX) {
173                 return EINVAL;
174         }
175
176         r = buxton_wire_register_notification((_BuxtonClient *)client, k,
177                                               callback, data);
178         if (!r) {
179                 return -1;
180         }
181
182         if (sync) {
183                 ret = buxton_wire_get_response(client);
184                 if (ret <= 0) {
185                         ret = -1;
186                 } else {
187                         ret = 0;
188                 }
189         }
190
191         return ret;
192 }
193
194 int buxton_unregister_notification(BuxtonClient client,
195                                    BuxtonKey key,
196                                    BuxtonCallback callback,
197                                    void *data,
198                                    bool sync)
199 {
200         bool r;
201         int ret = 0;
202         _BuxtonKey *k = (_BuxtonKey *)key;
203
204         if (!k || !k->group.value || !k->name.value ||
205             k->type <= BUXTON_TYPE_MIN || k->type >= BUXTON_TYPE_MAX) {
206                 return EINVAL;
207         }
208
209         r = buxton_wire_unregister_notification((_BuxtonClient *)client, k,
210                                                 callback, data);
211         if (!r) {
212                 return -1;
213         }
214
215         if (sync) {
216                 ret = buxton_wire_get_response(client);
217                 if (ret <= 0) {
218                         ret = -1;
219                 } else {
220                         ret = 0;
221                 }
222         }
223
224         return ret;
225 }
226
227 int buxton_set_value(BuxtonClient client,
228                      BuxtonKey key,
229                      void *value,
230                      BuxtonCallback callback,
231                      void *data,
232                      bool sync)
233 {
234         bool r;
235         int ret = 0;
236         _BuxtonKey *k = (_BuxtonKey *)key;
237
238         if (!k || !k->group.value || !k->name.value || !k->layer.value ||
239             k->type <= BUXTON_TYPE_MIN || k->type >= BUXTON_TYPE_MAX || !value) {
240                 return EINVAL;
241         }
242
243         r = buxton_wire_set_value((_BuxtonClient *)client, k, value, callback,
244                                   data);
245         if (!r) {
246                 return -1;
247         }
248
249         if (sync) {
250                 ret = buxton_wire_get_response(client);
251                 if (ret <= 0) {
252                         ret = -1;
253                 } else {
254                         ret = 0;
255                 }
256         }
257
258         return ret;
259 }
260
261 int buxton_set_label(BuxtonClient client,
262                      BuxtonKey key,
263                      char *value,
264                      BuxtonCallback callback,
265                      void *data,
266                      bool sync)
267 {
268         bool r;
269         int ret = 0;
270         BuxtonString v;
271         _BuxtonKey *k = (_BuxtonKey *)key;
272
273         if (!k || !k->group.value || !k->layer.value || !value) {
274                 return EINVAL;
275         }
276
277         k->type = STRING;
278         v = buxton_string_pack(value);
279
280         r = buxton_wire_set_label((_BuxtonClient *)client, k, &v, callback,
281                                   data);
282         if (!r) {
283                 return -1;
284         }
285
286         if (sync) {
287                 ret = buxton_wire_get_response(client);
288                 if (ret <= 0) {
289                         ret = -1;
290                 } else {
291                         ret = 0;
292                 }
293         }
294
295         return ret;
296 }
297
298 int buxton_create_group(BuxtonClient client,
299                         BuxtonKey key,
300                         BuxtonCallback callback,
301                         void *data,
302                         bool sync)
303 {
304         bool r;
305         int ret = 0;
306         _BuxtonKey *k = (_BuxtonKey *)key;
307
308         /* We require the key name to be NULL, since it is not used for groups */
309         if (!k || !k->group.value || k->name.value || !k->layer.value) {
310                 return EINVAL;
311         }
312
313         k->type = STRING;
314         r = buxton_wire_create_group((_BuxtonClient *)client, k, callback, data);
315         if (!r) {
316                 return -1;
317         }
318
319         if (sync) {
320                 ret = buxton_wire_get_response(client);
321                 if (ret <= 0) {
322                         ret = -1;
323                 } else {
324                         ret = 0;
325                 }
326         }
327
328         return ret;
329 }
330
331 int buxton_remove_group(BuxtonClient client,
332                         BuxtonKey key,
333                         BuxtonCallback callback,
334                         void *data,
335                         bool sync)
336 {
337         bool r;
338         int ret = 0;
339         _BuxtonKey *k = (_BuxtonKey *)key;
340
341         /* We require the key name to be NULL, since it is not used for groups */
342         if (!k || !k->group.value || k->name.value || !k->layer.value) {
343                 return EINVAL;
344         }
345
346         k->type = STRING;
347         r = buxton_wire_remove_group((_BuxtonClient *)client, k, callback, data);
348         if (!r) {
349                 return -1;
350         }
351
352         if (sync) {
353                 ret = buxton_wire_get_response(client);
354                 if (ret <= 0) {
355                         ret = -1;
356                 } else {
357                         ret = 0;
358                 }
359         }
360
361         return ret;
362 }
363
364 int buxton_client_list_keys(BuxtonClient client,
365                             char *layer_name,
366                             BuxtonCallback callback,
367                             void *data,
368                             bool sync)
369 {
370         bool r;
371         int ret = 0;
372         BuxtonString l;
373
374         if (!layer_name) {
375                 return EINVAL;
376         }
377
378         l = buxton_string_pack(layer_name);
379
380         r = buxton_wire_list_keys((_BuxtonClient *)client, &l, callback, data);
381         if (!r) {
382                 return -1;
383         }
384
385         if (sync) {
386                 ret = buxton_wire_get_response(client);
387                 if (ret <= 0) {
388                         ret = -1;
389                 } else {
390                         ret = 0;
391                 }
392         }
393
394         return ret;
395 }
396
397 int buxton_unset_value(BuxtonClient client,
398                        BuxtonKey key,
399                        BuxtonCallback callback,
400                        void *data,
401                        bool sync)
402 {
403         bool r;
404         int ret = 0;
405         _BuxtonKey *k = (_BuxtonKey *)key;
406
407         if (!k || !k->group.value || !k->name.value || !k->layer.value ||
408             k->type <= BUXTON_TYPE_MIN || k->type >= BUXTON_TYPE_MAX) {
409                 return EINVAL;
410         }
411
412         r = buxton_wire_unset_value((_BuxtonClient *)client, k, callback, data);
413         if (!r) {
414                 return -1;
415         }
416
417         if (sync) {
418                 ret = buxton_wire_get_response(client);
419                 if (ret <= 0) {
420                         ret = -1;
421                 } else {
422                         ret = 0;
423                 }
424         }
425
426         return ret;
427 }
428
429 BuxtonKey buxton_key_create(char *group, char *name, char *layer,
430                           BuxtonDataType type)
431 {
432         _BuxtonKey *key = NULL;
433         char *g = NULL;
434         char *n = NULL;
435         char *l = NULL;
436
437         if (!group) {
438                 goto fail;
439         }
440
441         if (type <= BUXTON_TYPE_MIN || type >= BUXTON_TYPE_MAX) {
442                 goto fail;
443         }
444
445         g = strdup(group);
446         if (!g) {
447                 goto fail;
448         }
449
450         if (name) {
451                 n = strdup(name);
452                 if (!n) {
453                         goto fail;
454                 }
455         }
456
457         if (layer) {
458                 l = strdup(layer);
459                 if (!l) {
460                         goto fail;
461                 }
462         }
463
464         key = malloc0(sizeof(_BuxtonKey));
465         if (!key) {
466                 goto fail;
467         }
468
469         key->group.value = g;
470         key->group.length = (uint32_t)strlen(g) + 1;
471         if (name) {
472                 key->name.value = n;
473                 key->name.length = (uint32_t)strlen(n) + 1;
474         } else {
475                 key->name.value = NULL;
476                 key->name.length = 0;
477         }
478         if (layer) {
479                 key->layer.value = l;
480                 key->layer.length = (uint32_t)strlen(l) + 1;
481         } else {
482                 key->layer.value = NULL;
483                 key->layer.length = 0;
484         }
485         key->type = type;
486
487         return (BuxtonKey)key;
488
489 fail:
490         free(g);
491         free(n);
492         free(l);
493         return NULL;
494 }
495
496 char *buxton_key_get_group(BuxtonKey key)
497 {
498         _BuxtonKey *k = (_BuxtonKey *)key;
499
500         if (!key) {
501                 return NULL;
502         }
503
504         return get_group(k);
505 }
506
507 char *buxton_key_get_name(BuxtonKey key)
508 {
509         _BuxtonKey *k = (_BuxtonKey *)key;
510
511         if (!key) {
512                 return NULL;
513         }
514
515         return get_name(k);
516 }
517
518 char *buxton_key_get_layer(BuxtonKey key)
519 {
520         _BuxtonKey *k = (_BuxtonKey *)key;
521
522         if (!key) {
523                 return NULL;
524         }
525
526         return get_layer(k);
527 }
528
529 BuxtonDataType buxton_key_get_type(BuxtonKey key)
530 {
531         _BuxtonKey *k = (_BuxtonKey *)key;
532
533         if (!key) {
534                 return -1;
535         }
536
537         return k->type;
538 }
539
540 void buxton_key_free(BuxtonKey key)
541 {
542         _BuxtonKey *k = (_BuxtonKey *)key;
543
544         if (!k) {
545                 return;
546         }
547
548         free(k->group.value);
549         free(k->name.value);
550         free(k->layer.value);
551         free(k);
552 }
553
554 ssize_t buxton_client_handle_response(BuxtonClient client)
555 {
556         return buxton_wire_handle_response((_BuxtonClient *)client);
557 }
558
559 BuxtonControlMessage buxton_response_type(BuxtonResponse response)
560 {
561         _BuxtonResponse *r = (_BuxtonResponse *)response;
562
563         if (!response) {
564                 return -1;
565         }
566
567         return r->type;
568 }
569
570 int32_t buxton_response_status(BuxtonResponse response)
571 {
572         BuxtonData *d;
573         _BuxtonResponse *r = (_BuxtonResponse *)response;
574
575         if (!response) {
576                 return -1;
577         }
578
579         if (buxton_response_type(response) == BUXTON_CONTROL_CHANGED) {
580                 return 0;
581         }
582
583         d = buxton_array_get(r->data, 0);
584
585         if (d) {
586                 return d->store.d_int32;
587         }
588
589         return -1;
590 }
591
592 BuxtonKey buxton_response_key(BuxtonResponse response)
593 {
594         _BuxtonKey *key = NULL;
595         _BuxtonResponse *r = (_BuxtonResponse *)response;
596
597         if (!response) {
598                 return NULL;
599         }
600
601         if (buxton_response_type(response) == BUXTON_CONTROL_LIST) {
602                 return NULL;
603         }
604
605         key = malloc0(sizeof(_BuxtonKey));
606         if (!key) {
607                 return NULL;
608         }
609
610         if (!buxton_key_copy(r->key, key)) {
611                 free(key);
612                 return NULL;
613         }
614
615         return (BuxtonKey)key;
616 }
617
618 void *buxton_response_value(BuxtonResponse response)
619 {
620         void *p = NULL;
621         BuxtonData *d = NULL;
622         _BuxtonResponse *r = (_BuxtonResponse *)response;
623         BuxtonControlMessage type;
624
625         if (!response) {
626                 return NULL;
627         }
628
629         type = buxton_response_type(response);
630         if (type == BUXTON_CONTROL_GET) {
631                 d = buxton_array_get(r->data, 1);
632         } else if (type == BUXTON_CONTROL_CHANGED) {
633                 if (r->data->len) {
634                         d = buxton_array_get(r->data, 0);
635                 }
636         } else {
637                 goto out;
638         }
639
640         if (!d) {
641                 goto out;
642         }
643
644         switch (d->type) {
645         case STRING:
646                 return strdup(d->store.d_string.value);
647         case INT32:
648                 p = malloc0(sizeof(int32_t));
649                 if (!p) {
650                         goto out;
651                 }
652                 *(int32_t *)p = (int32_t)d->store.d_int32;
653                 break;
654         case UINT32:
655                 p = malloc0(sizeof(uint32_t));
656                 if (!p) {
657                         goto out;
658                 }
659                 *(uint32_t *)p = (uint32_t)d->store.d_uint32;
660                 break;
661         case INT64:
662                 p = malloc0(sizeof(int64_t));
663                 if (!p) {
664                         goto out;
665                 }
666                 *(int64_t *)p = (int64_t)d->store.d_int64;
667                 break;
668         case UINT64:
669                 p = malloc0(sizeof(uint64_t));
670                 if (!p) {
671                         goto out;
672                 }
673                 *(uint64_t *)p = (uint64_t)d->store.d_uint64;
674                 break;
675         case FLOAT:
676                 p = malloc0(sizeof(float));
677                 if (!p) {
678                         goto out;
679                 }
680                 *(float *)p = (float)d->store.d_float;
681                 break;
682         case DOUBLE:
683                 p = malloc0(sizeof(double));
684                 if (!p) {
685                         goto out;
686                 }
687                 *(double *)p = (double)d->store.d_double;
688                 break;
689         case BOOLEAN:
690                 p = malloc0(sizeof(bool));
691                 if (!p) {
692                         goto out;
693                 }
694                 *(bool *)p = (bool)d->store.d_boolean;
695                 break;
696         default:
697                 break;
698         }
699
700 out:
701         return p;
702 }
703
704 /*
705  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
706  *
707  * Local variables:
708  * c-basic-offset: 8
709  * tab-width: 8
710  * indent-tabs-mode: t
711  * End:
712  *
713  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
714  * :indentSize=8:tabSize=8:noTabs=false:
715  */