blob: a642d0bb281e9dbb87293f40ba4f7985a45694b3 [file] [log] [blame]
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdlib.h>
18#include <string.h>
19#include "permissions.h"
20
21int
22initPermissionRequestList(PermissionRequestList *list)
23{
24 if (list != NULL) {
25 list->requests = NULL;
26 list->numRequests = 0;
27 list->requestsAllocated = 0;
28 return 0;
29 }
30 return -1;
31}
32
33int
34addPermissionRequestToList(PermissionRequestList *list,
35 const char *path, bool recursive, unsigned int permissions)
36{
37 if (list == NULL || list->numRequests < 0 ||
38 list->requestsAllocated < list->numRequests || path == NULL)
39 {
40 return -1;
41 }
42
43 if (list->numRequests == list->requestsAllocated) {
44 int newSize;
45 PermissionRequest *newRequests;
46
47 newSize = list->requestsAllocated * 2;
48 if (newSize < 16) {
49 newSize = 16;
50 }
51 newRequests = (PermissionRequest *)realloc(list->requests,
52 newSize * sizeof(PermissionRequest));
53 if (newRequests == NULL) {
54 return -2;
55 }
56 list->requests = newRequests;
57 list->requestsAllocated = newSize;
58 }
59
60 PermissionRequest *req;
61 req = &list->requests[list->numRequests++];
62 req->path = strdup(path);
63 if (req->path == NULL) {
64 list->numRequests--;
65 return -3;
66 }
67 req->recursive = recursive;
68 req->requested = permissions;
69 req->allowed = 0;
70
71 return 0;
72}
73
74void
75freePermissionRequestListElements(PermissionRequestList *list)
76{
77 if (list != NULL && list->numRequests >= 0 &&
78 list->requestsAllocated >= list->numRequests)
79 {
80 int i;
81 for (i = 0; i < list->numRequests; i++) {
82 free((void *)list->requests[i].path);
83 }
84 free(list->requests);
85 initPermissionRequestList(list);
86 }
87}
88
89/*
90 * Global permission table
91 */
92
93static struct {
94 Permission *permissions;
95 int numPermissionEntries;
96 int allocatedPermissionEntries;
97 bool permissionStateInitialized;
98} gPermissionState = {
99#if 1
100 NULL, 0, 0, false
101#else
102 .permissions = NULL,
103 .numPermissionEntries = 0,
104 .allocatedPermissionEntries = 0,
105 .permissionStateInitialized = false
106#endif
107};
108
109int
110permissionInit()
111{
112 if (gPermissionState.permissionStateInitialized) {
113 return -1;
114 }
115 gPermissionState.permissions = NULL;
116 gPermissionState.numPermissionEntries = 0;
117 gPermissionState.allocatedPermissionEntries = 0;
118 gPermissionState.permissionStateInitialized = true;
119//xxx maybe add an "namespace root gets no permissions" fallback by default
120 return 0;
121}
122
123void
124permissionCleanup()
125{
126 if (gPermissionState.permissionStateInitialized) {
127 gPermissionState.permissionStateInitialized = false;
128 if (gPermissionState.permissions != NULL) {
129 int i;
130 for (i = 0; i < gPermissionState.numPermissionEntries; i++) {
131 free((void *)gPermissionState.permissions[i].path);
132 }
133 free(gPermissionState.permissions);
134 }
135 }
136}
137
138int
139getPermissionCount()
140{
141 if (gPermissionState.permissionStateInitialized) {
142 return gPermissionState.numPermissionEntries;
143 }
144 return -1;
145}
146
147const Permission *
148getPermissionAt(int index)
149{
150 if (!gPermissionState.permissionStateInitialized) {
151 return NULL;
152 }
153 if (index < 0 || index >= gPermissionState.numPermissionEntries) {
154 return NULL;
155 }
156 return &gPermissionState.permissions[index];
157}
158
159int
160getAllowedPermissions(const char *path, bool recursive,
161 unsigned int *outAllowed)
162{
163 if (!gPermissionState.permissionStateInitialized) {
164 return -2;
165 }
166 if (outAllowed == NULL) {
167 return -1;
168 }
169 *outAllowed = 0;
170 if (path == NULL) {
171 return -1;
172 }
173 //TODO: implement this for real.
174 recursive = false;
175 *outAllowed = PERMSET_ALL;
176 return 0;
177}
178
179int
180countPermissionConflicts(PermissionRequestList *requests, bool updateAllowed)
181{
182 if (!gPermissionState.permissionStateInitialized) {
183 return -2;
184 }
185 if (requests == NULL || requests->requests == NULL ||
186 requests->numRequests < 0 ||
187 requests->requestsAllocated < requests->numRequests)
188 {
189 return -1;
190 }
191 int conflicts = 0;
192 int i;
193 for (i = 0; i < requests->numRequests; i++) {
194 PermissionRequest *req;
195 unsigned int allowed;
196 int ret;
197
198 req = &requests->requests[i];
199 ret = getAllowedPermissions(req->path, req->recursive, &allowed);
200 if (ret < 0) {
201 return ret;
202 }
203 if ((req->requested & ~allowed) != 0) {
204 conflicts++;
205 }
206 if (updateAllowed) {
207 req->allowed = allowed;
208 }
209 }
210 return conflicts;
211}
212
213int
214registerPermissionSet(int count, Permission *set)
215{
216 if (!gPermissionState.permissionStateInitialized) {
217 return -2;
218 }
219 if (count < 0 || (count > 0 && set == NULL)) {
220 return -1;
221 }
222 if (count == 0) {
223 return 0;
224 }
225
226 if (gPermissionState.numPermissionEntries + count >=
227 gPermissionState.allocatedPermissionEntries)
228 {
229 Permission *newList;
230 int newSize;
231
232 newSize = (gPermissionState.allocatedPermissionEntries + count) * 2;
233 if (newSize < 16) {
234 newSize = 16;
235 }
236 newList = (Permission *)realloc(gPermissionState.permissions,
237 newSize * sizeof(Permission));
238 if (newList == NULL) {
239 return -3;
240 }
241 gPermissionState.permissions = newList;
242 gPermissionState.allocatedPermissionEntries = newSize;
243 }
244
245 Permission *p = &gPermissionState.permissions[
246 gPermissionState.numPermissionEntries];
247 int i;
248 for (i = 0; i < count; i++) {
249 *p = set[i];
250 //TODO: cache the strlen of the path
251 //TODO: normalize; strip off trailing /
252 p->path = strdup(p->path);
253 if (p->path == NULL) {
254 /* If we can't add all of the entries, we don't
255 * add any of them.
256 */
257 Permission *pp = &gPermissionState.permissions[
258 gPermissionState.numPermissionEntries];
259 while (pp != p) {
260 free((void *)pp->path);
261 pp++;
262 }
263 return -4;
264 }
265 p++;
266 }
267 gPermissionState.numPermissionEntries += count;
268
269 return 0;
270}