362b1c11e7e34ab30ff755f31ec2787992a9cb3e
[src/app-framework-main.git] / src / wgtpkg-permissions.c
1 /*
2  Copyright 2015, 2016 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 unsigned int nrpermissions = 0;
36 static struct permission *permissions = NULL;
37 static unsigned int indexiter = 0;
38
39 /* retrieves the permission of name */
40 static struct permission *get_permission(const char *name)
41 {
42         unsigned int i;
43
44         for (i = 0 ; i < nrpermissions ; i++)
45                 if (0 == strcmp(permissions[i].name, name))
46                         return permissions+i;
47         return NULL;
48 }
49
50 /* add a permission of name */
51 static struct permission *add_permission(const char *name)
52 {
53         struct permission *p = get_permission(name);
54         if (!p) {
55                 p = realloc(permissions,
56                         ((nrpermissions + 8) & ~(unsigned)7) * sizeof(*p));
57                 if (p) {
58                         permissions = p;
59                         p = permissions + nrpermissions;
60                         memset(p, 0, sizeof(*p));
61                         p->name = strdup(name);
62                         if (!p->name)
63                                 p = NULL;
64                         else
65                                 nrpermissions++;
66                 }
67         }
68         return p;
69 }
70
71 /* remove any granting */
72 void reset_permissions()
73 {
74         unsigned int i;
75         for (i = 0 ; i < nrpermissions ; i++)
76                 permissions[i].granted = permissions[i].requested = 0;
77 }
78
79 /* remove any requested permission */
80 void reset_requested_permissions()
81 {
82         unsigned int i;
83         for (i = 0 ; i < nrpermissions ; i++)
84                 permissions[i].requested = 0;
85 }
86
87 /* remove any granting */
88 void crop_permissions(unsigned level)
89 {
90         unsigned int i;
91         for (i = 0 ; i < nrpermissions ; i++)
92                 if (permissions[i].level < level)
93                         permissions[i].granted = 0;
94 }
95
96 /* add permissions granted for installation */
97 int grant_permission_list(const char *list)
98 {
99         struct permission *p;
100         char *iter, c;
101         unsigned int n;
102         static const char separators[] = " \t\n\r,";
103
104         iter = strdupa(list);
105         iter += strspn(iter, separators);
106         while(*iter) {
107                 n = (unsigned)strcspn(iter, separators);
108                 c = iter[n];
109                 iter[n] = 0;
110                 p = add_permission(iter);
111                 if (!p) {
112                         errno = ENOMEM;
113                         return -1;
114                 }
115                 p->granted = 1;
116                 iter += n;
117                 *iter =c;
118                 iter += strspn(iter, separators);
119         }
120         return 0;
121 }
122
123 /* checks if the permission 'name' is recorded */
124 int permission_exists(const char *name)
125 {
126         return !!get_permission(name);
127 }
128
129 /* request the permission, returns 1 if granted or 0 otherwise */
130 int request_permission(const char *name)
131 {
132         struct permission *p = get_permission(name);
133         if (p) {
134                 p->requested = 1;
135                 if (p->granted)
136                         return 1;
137         }
138         return 0;
139 }
140
141 /* iteration over granted and requested permissions */
142 const char *first_usable_permission()
143 {
144         indexiter = 0;
145         return next_usable_permission();
146 }
147
148 const char *next_usable_permission()
149 {
150         while(indexiter < nrpermissions) {
151                 struct permission *p = &permissions[indexiter++];
152                 if (p->granted && p->requested)
153                         return p->name;
154         }
155         return NULL;
156 }
157