summaryrefslogtreecommitdiffstats
path: root/amend/permissions.c
diff options
context:
space:
mode:
Diffstat (limited to 'amend/permissions.c')
-rw-r--r--amend/permissions.c270
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;
+}