1 /* Copyright (C) 2005 Red Hat, Inc. */
2 
3 #include <semanage/handle.h>
4 #include "semanage_store.h"
5 #include "semanage_conf.h"
6 #include "database.h"
7 #include "debug.h"
8 
assert_init(semanage_handle_t * handle,dbase_config_t * dconfig)9 static int assert_init(semanage_handle_t * handle, dbase_config_t * dconfig)
10 {
11 
12 	if (dconfig->dtable == NULL) {
13 
14 		ERR(handle,
15 		    "A direct or server connection is needed "
16 		    "to use this function - please call "
17 		    "the corresponding connect() method");
18 		return STATUS_ERR;
19 	}
20 
21 	return STATUS_SUCCESS;
22 }
23 
enter_ro(semanage_handle_t * handle,dbase_config_t * dconfig)24 static int enter_ro(semanage_handle_t * handle, dbase_config_t * dconfig)
25 {
26 
27 	if (assert_init(handle, dconfig) < 0)
28 		goto err;
29 
30 	if (!handle->is_in_transaction &&
31 	    handle->conf->store_type == SEMANAGE_CON_DIRECT) {
32 
33 		if (semanage_get_active_lock(handle) < 0) {
34 			ERR(handle, "could not get the active lock");
35 			goto err;
36 		}
37 	}
38 
39 	if (dconfig->dtable->cache(handle, dconfig->dbase) < 0)
40 		goto err;
41 
42 	return STATUS_SUCCESS;
43 
44       err:
45 	ERR(handle, "could not enter read-only section");
46 	return STATUS_ERR;
47 }
48 
exit_ro(semanage_handle_t * handle)49 static inline int exit_ro(semanage_handle_t * handle)
50 {
51 
52 	int commit_num = handle->funcs->get_serial(handle);
53 
54 	if (!handle->is_in_transaction &&
55 	    handle->conf->store_type == SEMANAGE_CON_DIRECT)
56 		semanage_release_active_lock(handle);
57 
58 	return commit_num;
59 }
60 
enter_rw(semanage_handle_t * handle,dbase_config_t * dconfig)61 static int enter_rw(semanage_handle_t * handle, dbase_config_t * dconfig)
62 {
63 
64 	if (assert_init(handle, dconfig) < 0)
65 		goto err;
66 
67 	if (!handle->is_in_transaction) {
68 		ERR(handle, "this operation requires a transaction");
69 		goto err;
70 	}
71 
72 	if (dconfig->dtable->cache(handle, dconfig->dbase) < 0)
73 		goto err;
74 
75 	return STATUS_SUCCESS;
76 
77       err:
78 	ERR(handle, "could not enter read-write section");
79 	return STATUS_ERR;
80 }
81 
dbase_modify(semanage_handle_t * handle,dbase_config_t * dconfig,const record_key_t * key,const record_t * data)82 int dbase_modify(semanage_handle_t * handle,
83 		 dbase_config_t * dconfig,
84 		 const record_key_t * key, const record_t * data)
85 {
86 
87 	if (enter_rw(handle, dconfig) < 0)
88 		return STATUS_ERR;
89 
90 	if (dconfig->dtable->modify(handle, dconfig->dbase, key, data) < 0)
91 		return STATUS_ERR;
92 
93 	return STATUS_SUCCESS;
94 }
95 
dbase_set(semanage_handle_t * handle,dbase_config_t * dconfig,const record_key_t * key,const record_t * data)96 int dbase_set(semanage_handle_t * handle,
97 	      dbase_config_t * dconfig,
98 	      const record_key_t * key, const record_t * data)
99 {
100 
101 	if (enter_rw(handle, dconfig) < 0)
102 		return STATUS_ERR;
103 
104 	if (dconfig->dtable->set(handle, dconfig->dbase, key, data) < 0)
105 		return STATUS_ERR;
106 
107 	return STATUS_SUCCESS;
108 }
109 
dbase_del(semanage_handle_t * handle,dbase_config_t * dconfig,const record_key_t * key)110 int dbase_del(semanage_handle_t * handle,
111 	      dbase_config_t * dconfig, const record_key_t * key)
112 {
113 
114 	if (enter_rw(handle, dconfig) < 0)
115 		return STATUS_ERR;
116 
117 	if (dconfig->dtable->del(handle, dconfig->dbase, key) < 0)
118 		return STATUS_ERR;
119 
120 	return STATUS_SUCCESS;
121 }
122 
dbase_query(semanage_handle_t * handle,dbase_config_t * dconfig,const record_key_t * key,record_t ** response)123 int dbase_query(semanage_handle_t * handle,
124 		dbase_config_t * dconfig,
125 		const record_key_t * key, record_t ** response)
126 {
127 
128 	if (enter_ro(handle, dconfig) < 0)
129 		return STATUS_ERR;
130 
131 	if (dconfig->dtable->query(handle, dconfig->dbase, key, response) < 0) {
132 		exit_ro(handle);
133 		return STATUS_ERR;
134 	}
135 
136 	return exit_ro(handle);
137 }
138 
dbase_exists(semanage_handle_t * handle,dbase_config_t * dconfig,const record_key_t * key,int * response)139 int dbase_exists(semanage_handle_t * handle,
140 		 dbase_config_t * dconfig,
141 		 const record_key_t * key, int *response)
142 {
143 
144 	if (enter_ro(handle, dconfig) < 0)
145 		return STATUS_ERR;
146 
147 	if (dconfig->dtable->exists(handle, dconfig->dbase, key, response) < 0) {
148 		exit_ro(handle);
149 		return STATUS_ERR;
150 	}
151 
152 	return exit_ro(handle);
153 }
154 
dbase_count(semanage_handle_t * handle,dbase_config_t * dconfig,unsigned int * response)155 int dbase_count(semanage_handle_t * handle,
156 		dbase_config_t * dconfig, unsigned int *response)
157 {
158 
159 	if (enter_ro(handle, dconfig) < 0)
160 		return STATUS_ERR;
161 
162 	if (dconfig->dtable->count(handle, dconfig->dbase, response) < 0) {
163 		exit_ro(handle);
164 		return STATUS_ERR;
165 	}
166 
167 	return exit_ro(handle);
168 }
169 
dbase_iterate(semanage_handle_t * handle,dbase_config_t * dconfig,int (* fn)(const record_t * record,void * fn_arg),void * fn_arg)170 int dbase_iterate(semanage_handle_t * handle,
171 		  dbase_config_t * dconfig,
172 		  int (*fn) (const record_t * record,
173 			     void *fn_arg), void *fn_arg)
174 {
175 
176 	if (enter_ro(handle, dconfig) < 0)
177 		return STATUS_ERR;
178 
179 	if (dconfig->dtable->iterate(handle, dconfig->dbase, fn, fn_arg) < 0) {
180 		exit_ro(handle);
181 		return STATUS_ERR;
182 	}
183 
184 	return exit_ro(handle);
185 }
186 
dbase_list(semanage_handle_t * handle,dbase_config_t * dconfig,record_t *** records,unsigned int * count)187 int dbase_list(semanage_handle_t * handle,
188 	       dbase_config_t * dconfig,
189 	       record_t *** records, unsigned int *count)
190 {
191 
192 	if (enter_ro(handle, dconfig) < 0)
193 		return STATUS_ERR;
194 
195 	if (dconfig->dtable->list(handle, dconfig->dbase, records, count) < 0) {
196 		exit_ro(handle);
197 		return STATUS_ERR;
198 	}
199 
200 	return exit_ro(handle);
201 }
202