/* * Copyright 2014 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include <pthread.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include "cil_mem.h" #include "cil_strpool.h" #include "cil_log.h" #define CIL_STRPOOL_TABLE_SIZE 1 << 15 struct cil_strpool_entry { char *str; }; static pthread_mutex_t cil_strpool_mutex = PTHREAD_MUTEX_INITIALIZER; static unsigned int cil_strpool_readers = 0; static hashtab_t cil_strpool_tab = NULL; static unsigned int cil_strpool_hash(hashtab_t h, const_hashtab_key_t key) { const char *p, *keyp; size_t size; unsigned int val; val = 0; keyp = (const char*)key; size = strlen(keyp); for (p = keyp; ((size_t) (p - keyp)) < size; p++) val = (val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p); return val & (h->size - 1); } static int cil_strpool_compare(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2) { const char *keyp1 = (const char*)key1; const char *keyp2 = (const char*)key2; return strcmp(keyp1, keyp2); } char *cil_strpool_add(const char *str) { struct cil_strpool_entry *strpool_ref = NULL; pthread_mutex_lock(&cil_strpool_mutex); strpool_ref = hashtab_search(cil_strpool_tab, (hashtab_key_t)str); if (strpool_ref == NULL) { strpool_ref = cil_malloc(sizeof(*strpool_ref)); strpool_ref->str = cil_strdup(str); int rc = hashtab_insert(cil_strpool_tab, (hashtab_key_t)strpool_ref->str, strpool_ref); if (rc != SEPOL_OK) { pthread_mutex_unlock(&cil_strpool_mutex); (*cil_mem_error_handler)(); pthread_mutex_lock(&cil_strpool_mutex); } } pthread_mutex_unlock(&cil_strpool_mutex); return strpool_ref->str; } static int cil_strpool_entry_destroy(hashtab_key_t k __attribute__ ((unused)), hashtab_datum_t d, void *args __attribute__ ((unused))) { struct cil_strpool_entry *strpool_ref = (struct cil_strpool_entry*)d; free(strpool_ref->str); free(strpool_ref); return SEPOL_OK; } void cil_strpool_init(void) { pthread_mutex_lock(&cil_strpool_mutex); if (cil_strpool_tab == NULL) { cil_strpool_tab = hashtab_create(cil_strpool_hash, cil_strpool_compare, CIL_STRPOOL_TABLE_SIZE); if (cil_strpool_tab == NULL) { pthread_mutex_unlock(&cil_strpool_mutex); (*cil_mem_error_handler)(); return; } } cil_strpool_readers++; pthread_mutex_unlock(&cil_strpool_mutex); } void cil_strpool_destroy(void) { pthread_mutex_lock(&cil_strpool_mutex); cil_strpool_readers--; if (cil_strpool_readers == 0) { hashtab_map(cil_strpool_tab, cil_strpool_entry_destroy, NULL); hashtab_destroy(cil_strpool_tab); } pthread_mutex_unlock(&cil_strpool_mutex); }