Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright 2014 Tresys Technology, LLC. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are met:
      6  *
      7  *    1. Redistributions of source code must retain the above copyright notice,
      8  *       this list of conditions and the following disclaimer.
      9  *
     10  *    2. Redistributions in binary form must reproduce the above copyright notice,
     11  *       this list of conditions and the following disclaimer in the documentation
     12  *       and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
     15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     16  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
     17  * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     18  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     22  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  *
     25  * The views and conclusions contained in the software and documentation are those
     26  * of the authors and should not be interpreted as representing official policies,
     27  * either expressed or implied, of Tresys Technology, LLC.
     28  */
     29 
     30 #include <pthread.h>
     31 #include <stdlib.h>
     32 #include <stdio.h>
     33 #include <string.h>
     34 #include "cil_mem.h"
     35 #include "cil_strpool.h"
     36 
     37 #include "cil_log.h"
     38 #define CIL_STRPOOL_TABLE_SIZE 1 << 15
     39 
     40 struct cil_strpool_entry {
     41 	char *str;
     42 };
     43 
     44 static pthread_mutex_t cil_strpool_mutex = PTHREAD_MUTEX_INITIALIZER;
     45 static unsigned int cil_strpool_readers = 0;
     46 static hashtab_t cil_strpool_tab = NULL;
     47 
     48 static unsigned int cil_strpool_hash(hashtab_t h, const_hashtab_key_t key)
     49 {
     50 	const char *p, *keyp;
     51 	size_t size;
     52 	unsigned int val;
     53 
     54 	val = 0;
     55 	keyp = (const char*)key;
     56 	size = strlen(keyp);
     57 	for (p = keyp; ((size_t) (p - keyp)) < size; p++)
     58 		val =
     59 		    (val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p);
     60 	return val & (h->size - 1);
     61 }
     62 
     63 static int cil_strpool_compare(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2)
     64 {
     65 	const char *keyp1 = (const char*)key1;
     66 	const char *keyp2 = (const char*)key2;
     67 	return strcmp(keyp1, keyp2);
     68 }
     69 
     70 char *cil_strpool_add(const char *str)
     71 {
     72 	struct cil_strpool_entry *strpool_ref = NULL;
     73 
     74 	pthread_mutex_lock(&cil_strpool_mutex);
     75 
     76 	strpool_ref = hashtab_search(cil_strpool_tab, (hashtab_key_t)str);
     77 	if (strpool_ref == NULL) {
     78 		strpool_ref = cil_malloc(sizeof(*strpool_ref));
     79 		strpool_ref->str = cil_strdup(str);
     80 		int rc = hashtab_insert(cil_strpool_tab, (hashtab_key_t)strpool_ref->str, strpool_ref);
     81 		if (rc != SEPOL_OK) {
     82 			pthread_mutex_unlock(&cil_strpool_mutex);
     83 			(*cil_mem_error_handler)();
     84 			pthread_mutex_lock(&cil_strpool_mutex);
     85 		}
     86 	}
     87 
     88 	pthread_mutex_unlock(&cil_strpool_mutex);
     89 	return strpool_ref->str;
     90 }
     91 
     92 static int cil_strpool_entry_destroy(hashtab_key_t k __attribute__ ((unused)), hashtab_datum_t d, void *args __attribute__ ((unused)))
     93 {
     94 	struct cil_strpool_entry *strpool_ref = (struct cil_strpool_entry*)d;
     95 	free(strpool_ref->str);
     96 	free(strpool_ref);
     97 	return SEPOL_OK;
     98 }
     99 
    100 void cil_strpool_init(void)
    101 {
    102 	pthread_mutex_lock(&cil_strpool_mutex);
    103 	if (cil_strpool_tab == NULL) {
    104 		cil_strpool_tab = hashtab_create(cil_strpool_hash, cil_strpool_compare, CIL_STRPOOL_TABLE_SIZE);
    105 		if (cil_strpool_tab == NULL) {
    106 			pthread_mutex_unlock(&cil_strpool_mutex);
    107 			(*cil_mem_error_handler)();
    108 			return;
    109 		}
    110 	}
    111 	cil_strpool_readers++;
    112 	pthread_mutex_unlock(&cil_strpool_mutex);
    113 }
    114 
    115 void cil_strpool_destroy(void)
    116 {
    117 	pthread_mutex_lock(&cil_strpool_mutex);
    118 	cil_strpool_readers--;
    119 	if (cil_strpool_readers == 0) {
    120 		hashtab_map(cil_strpool_tab, cil_strpool_entry_destroy, NULL);
    121 		hashtab_destroy(cil_strpool_tab);
    122 	}
    123 	pthread_mutex_unlock(&cil_strpool_mutex);
    124 }
    125