/src/selinux/libsepol/cil/src/cil_strpool.c
Line | Count | Source |
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 | 0 | #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 | 0 | { |
50 | 0 | unsigned int hash = 5381; |
51 | 0 | unsigned char c; |
52 | |
|
53 | 0 | while ((c = *(unsigned const char *)key++)) |
54 | 0 | hash = ((hash << 5) + hash) ^ c; |
55 | |
|
56 | 0 | return hash & (h->size - 1); |
57 | 0 | } |
58 | | |
59 | | static int cil_strpool_compare(hashtab_t h __attribute__((unused)), |
60 | | const_hashtab_key_t key1, |
61 | | const_hashtab_key_t key2) |
62 | 0 | { |
63 | 0 | return strcmp(key1, key2); |
64 | 0 | } |
65 | | |
66 | | char *cil_strpool_add(const char *str) |
67 | 0 | { |
68 | 0 | struct cil_strpool_entry *strpool_ref = NULL; |
69 | |
|
70 | 0 | pthread_mutex_lock(&cil_strpool_mutex); |
71 | |
|
72 | 0 | strpool_ref = hashtab_search(cil_strpool_tab, str); |
73 | 0 | if (strpool_ref == NULL) { |
74 | 0 | int rc; |
75 | 0 | strpool_ref = cil_malloc(sizeof(*strpool_ref)); |
76 | 0 | strpool_ref->str = cil_strdup(str); |
77 | 0 | rc = hashtab_insert(cil_strpool_tab, strpool_ref->str, |
78 | 0 | strpool_ref); |
79 | 0 | if (rc != SEPOL_OK) { |
80 | 0 | pthread_mutex_unlock(&cil_strpool_mutex); |
81 | 0 | cil_log(CIL_ERR, "Failed to allocate memory\n"); |
82 | 0 | exit(1); |
83 | 0 | } |
84 | 0 | } |
85 | | |
86 | 0 | pthread_mutex_unlock(&cil_strpool_mutex); |
87 | 0 | return strpool_ref->str; |
88 | 0 | } |
89 | | |
90 | | static int cil_strpool_entry_destroy(hashtab_key_t k __attribute__((unused)), |
91 | | hashtab_datum_t d, |
92 | | void *args __attribute__((unused))) |
93 | 0 | { |
94 | 0 | struct cil_strpool_entry *strpool_ref = (struct cil_strpool_entry *)d; |
95 | 0 | free(strpool_ref->str); |
96 | 0 | free(strpool_ref); |
97 | 0 | return SEPOL_OK; |
98 | 0 | } |
99 | | |
100 | | void cil_strpool_init(void) |
101 | 0 | { |
102 | 0 | pthread_mutex_lock(&cil_strpool_mutex); |
103 | 0 | if (cil_strpool_tab == NULL) { |
104 | 0 | cil_strpool_tab = hashtab_create(cil_strpool_hash, |
105 | 0 | cil_strpool_compare, |
106 | 0 | CIL_STRPOOL_TABLE_SIZE); |
107 | 0 | if (cil_strpool_tab == NULL) { |
108 | 0 | pthread_mutex_unlock(&cil_strpool_mutex); |
109 | 0 | cil_log(CIL_ERR, "Failed to allocate memory\n"); |
110 | 0 | exit(1); |
111 | 0 | } |
112 | 0 | } |
113 | 0 | cil_strpool_readers++; |
114 | 0 | pthread_mutex_unlock(&cil_strpool_mutex); |
115 | 0 | } |
116 | | |
117 | | void cil_strpool_destroy(void) |
118 | 0 | { |
119 | 0 | pthread_mutex_lock(&cil_strpool_mutex); |
120 | 0 | cil_strpool_readers--; |
121 | 0 | if (cil_strpool_readers == 0) { |
122 | 0 | hashtab_map(cil_strpool_tab, cil_strpool_entry_destroy, NULL); |
123 | 0 | hashtab_destroy(cil_strpool_tab); |
124 | | cil_strpool_tab = NULL; |
125 | 0 | } |
126 | 0 | pthread_mutex_unlock(&cil_strpool_mutex); |
127 | 0 | } |