271 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			271 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * 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;
 | 
						|
}
 |