diff options
Diffstat (limited to 'amend/permissions.c')
-rw-r--r-- | amend/permissions.c | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/amend/permissions.c b/amend/permissions.c new file mode 100644 index 000000000..a642d0bb2 --- /dev/null +++ b/amend/permissions.c @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> +#include <string.h> +#include "permissions.h" + +int +initPermissionRequestList(PermissionRequestList *list) +{ + if (list != NULL) { + list->requests = NULL; + list->numRequests = 0; + list->requestsAllocated = 0; + return 0; + } + return -1; +} + +int +addPermissionRequestToList(PermissionRequestList *list, + const char *path, bool recursive, unsigned int permissions) +{ + if (list == NULL || list->numRequests < 0 || + list->requestsAllocated < list->numRequests || path == NULL) + { + return -1; + } + + if (list->numRequests == list->requestsAllocated) { + int newSize; + PermissionRequest *newRequests; + + newSize = list->requestsAllocated * 2; + if (newSize < 16) { + newSize = 16; + } + newRequests = (PermissionRequest *)realloc(list->requests, + newSize * sizeof(PermissionRequest)); + if (newRequests == NULL) { + return -2; + } + list->requests = newRequests; + list->requestsAllocated = newSize; + } + + PermissionRequest *req; + req = &list->requests[list->numRequests++]; + req->path = strdup(path); + if (req->path == NULL) { + list->numRequests--; + return -3; + } + req->recursive = recursive; + req->requested = permissions; + req->allowed = 0; + + return 0; +} + +void +freePermissionRequestListElements(PermissionRequestList *list) +{ + if (list != NULL && list->numRequests >= 0 && + list->requestsAllocated >= list->numRequests) + { + int i; + for (i = 0; i < list->numRequests; i++) { + free((void *)list->requests[i].path); + } + free(list->requests); + initPermissionRequestList(list); + } +} + +/* + * Global permission table + */ + +static struct { + Permission *permissions; + int numPermissionEntries; + int allocatedPermissionEntries; + bool permissionStateInitialized; +} gPermissionState = { +#if 1 + NULL, 0, 0, false +#else + .permissions = NULL, + .numPermissionEntries = 0, + .allocatedPermissionEntries = 0, + .permissionStateInitialized = false +#endif +}; + +int +permissionInit() +{ + if (gPermissionState.permissionStateInitialized) { + return -1; + } + gPermissionState.permissions = NULL; + gPermissionState.numPermissionEntries = 0; + gPermissionState.allocatedPermissionEntries = 0; + gPermissionState.permissionStateInitialized = true; +//xxx maybe add an "namespace root gets no permissions" fallback by default + return 0; +} + +void +permissionCleanup() +{ + if (gPermissionState.permissionStateInitialized) { + gPermissionState.permissionStateInitialized = false; + if (gPermissionState.permissions != NULL) { + int i; + for (i = 0; i < gPermissionState.numPermissionEntries; i++) { + free((void *)gPermissionState.permissions[i].path); + } + free(gPermissionState.permissions); + } + } +} + +int +getPermissionCount() +{ + if (gPermissionState.permissionStateInitialized) { + return gPermissionState.numPermissionEntries; + } + return -1; +} + +const Permission * +getPermissionAt(int index) +{ + if (!gPermissionState.permissionStateInitialized) { + return NULL; + } + if (index < 0 || index >= gPermissionState.numPermissionEntries) { + return NULL; + } + return &gPermissionState.permissions[index]; +} + +int +getAllowedPermissions(const char *path, bool recursive, + unsigned int *outAllowed) +{ + if (!gPermissionState.permissionStateInitialized) { + return -2; + } + if (outAllowed == NULL) { + return -1; + } + *outAllowed = 0; + if (path == NULL) { + return -1; + } + //TODO: implement this for real. + recursive = false; + *outAllowed = PERMSET_ALL; + return 0; +} + +int +countPermissionConflicts(PermissionRequestList *requests, bool updateAllowed) +{ + if (!gPermissionState.permissionStateInitialized) { + return -2; + } + if (requests == NULL || requests->requests == NULL || + requests->numRequests < 0 || + requests->requestsAllocated < requests->numRequests) + { + return -1; + } + int conflicts = 0; + int i; + for (i = 0; i < requests->numRequests; i++) { + PermissionRequest *req; + unsigned int allowed; + int ret; + + req = &requests->requests[i]; + ret = getAllowedPermissions(req->path, req->recursive, &allowed); + if (ret < 0) { + return ret; + } + if ((req->requested & ~allowed) != 0) { + conflicts++; + } + if (updateAllowed) { + req->allowed = allowed; + } + } + return conflicts; +} + +int +registerPermissionSet(int count, Permission *set) +{ + if (!gPermissionState.permissionStateInitialized) { + return -2; + } + if (count < 0 || (count > 0 && set == NULL)) { + return -1; + } + if (count == 0) { + return 0; + } + + if (gPermissionState.numPermissionEntries + count >= + gPermissionState.allocatedPermissionEntries) + { + Permission *newList; + int newSize; + + newSize = (gPermissionState.allocatedPermissionEntries + count) * 2; + if (newSize < 16) { + newSize = 16; + } + newList = (Permission *)realloc(gPermissionState.permissions, + newSize * sizeof(Permission)); + if (newList == NULL) { + return -3; + } + gPermissionState.permissions = newList; + gPermissionState.allocatedPermissionEntries = newSize; + } + + Permission *p = &gPermissionState.permissions[ + gPermissionState.numPermissionEntries]; + int i; + for (i = 0; i < count; i++) { + *p = set[i]; + //TODO: cache the strlen of the path + //TODO: normalize; strip off trailing / + p->path = strdup(p->path); + if (p->path == NULL) { + /* If we can't add all of the entries, we don't + * add any of them. + */ + Permission *pp = &gPermissionState.permissions[ + gPermissionState.numPermissionEntries]; + while (pp != p) { + free((void *)pp->path); + pp++; + } + return -4; + } + p++; + } + gPermissionState.numPermissionEntries += count; + + return 0; +} |