/* * 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 #include #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; }