Fix installation of more than one widget
[src/app-framework-main.git] / src / wgtpkg-permissions.c
1 /*
2  Copyright 2015 IoT.bzh
3
4  author: José Bollo <jose.bollo@iot.bzh>
5
6  Licensed under the Apache License, Version 2.0 (the "License");
7  you may not use this file except in compliance with the License.
8  You may obtain a copy of the License at
9
10      http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  See the License for the specific language governing permissions and
16  limitations under the License.
17 */
18
19 #define _GNU_SOURCE
20
21 #include <errno.h>
22 #include <string.h>
23 #include <stdlib.h>
24
25 #include "verbose.h"
26 #include "wgtpkg-permissions.h"
27
28 struct permission {
29         char *name;
30         unsigned granted: 1;
31         unsigned requested: 1;
32         unsigned level: 3;
33 };
34
35 static const char prefix_of_permissions[] = FWK_PREFIX_PERMISSION;
36
37 static unsigned int nrpermissions = 0;
38 static struct permission *permissions = NULL;
39 static unsigned int indexiter = 0;
40
41 /* check is the name has the correct prefix for permissions */
42 int is_standard_permission(const char *name)
43 {
44         return 0 == memcmp(name, prefix_of_permissions, sizeof(prefix_of_permissions) - 1);
45 }
46
47 /* retrieves the permission of name */
48 static struct permission *get_permission(const char *name)
49 {
50         unsigned int i;
51
52         for (i = 0 ; i < nrpermissions ; i++)
53                 if (0 == strcmp(permissions[i].name, name))
54                         return permissions+i;
55         return NULL;
56 }
57
58 /* add a permission of name */
59 static struct permission *add_permission(const char *name)
60 {
61         struct permission *p = get_permission(name);
62         if (!p) {
63                 p = realloc(permissions,
64                         ((nrpermissions + 8) & ~(unsigned)7) * sizeof(*p));
65                 if (p) {
66                         permissions = p;
67                         p = permissions + nrpermissions;
68                         memset(p, 0, sizeof(*p));
69                         p->name = strdup(name);
70                         if (!p->name)
71                                 p = NULL;
72                         else
73                                 nrpermissions++;
74                 }
75         }
76         return p;
77 }
78
79 /* remove any granting */
80 void reset_permissions()
81 {
82         unsigned int i;
83         for (i = 0 ; i < nrpermissions ; i++)
84                 permissions[i].granted = permissions[i].requested = 0;
85 }
86
87 /* remove any requested permission */
88 void reset_requested_permissions()
89 {
90         unsigned int i;
91         for (i = 0 ; i < nrpermissions ; i++)
92                 permissions[i].requested = 0;
93 }
94
95 /* remove any granting */
96 void crop_permissions(unsigned level)
97 {
98         unsigned int i;
99         for (i = 0 ; i < nrpermissions ; i++)
100                 if (permissions[i].level < level)
101                         permissions[i].granted = 0;
102 }
103
104 /* add permissions granted for installation */
105 int grant_permission_list(const char *list)
106 {
107         struct permission *p;
108         char *iter, c;
109         unsigned int n;
110         static const char separators[] = " \t\n\r,";
111
112         iter = strdupa(list);
113         iter += strspn(iter, separators);
114         while(*iter) {
115                 n = (unsigned)strcspn(iter, separators);
116                 c = iter[n];
117                 iter[n] = 0;
118                 p = add_permission(iter);
119                 if (!p) {
120                         errno = ENOMEM;
121                         return -1;
122                 }
123                 p->granted = 1;
124                 iter += n;
125                 *iter =c;
126                 iter += strspn(iter, separators);
127         }
128         return 0;
129 }
130
131 /* checks if the permission 'name' is recorded */
132 int permission_exists(const char *name)
133 {
134         return !!get_permission(name);
135 }
136
137 /* request the permission, returns 1 if granted or 0 otherwise */
138 int request_permission(const char *name)
139 {
140         struct permission *p = get_permission(name);
141         if (p) {
142                 p->requested = 1;
143                 if (p->granted)
144                         return 1;
145         }
146         return 0;
147 }
148
149 /* iteration over granted and requested permissions */
150 const char *first_usable_permission()
151 {
152         indexiter = 0;
153         return next_usable_permission();
154 }
155
156 const char *next_usable_permission()
157 {
158         while(indexiter < nrpermissions) {
159                 struct permission *p = &permissions[indexiter++];
160                 if (p->granted && p->requested)
161                         return p->name;
162         }
163         return NULL;
164 }
165