1struct semanage_fcontext;
2struct semanage_fcontext_key;
3typedef struct semanage_fcontext record_t;
4typedef struct semanage_fcontext_key record_key_t;
5#define DBASE_RECORD_DEFINED
6
7#include <stdlib.h>
8#include <string.h>
9#include "fcontext_internal.h"
10#include "context_internal.h"
11#include "debug.h"
12
13struct semanage_fcontext {
14
15	/* Matching expression */
16	char *expr;
17
18	/* Type of object */
19	int type;
20
21	/* Context */
22	semanage_context_t *con;
23};
24
25struct semanage_fcontext_key {
26
27	/* Matching expression */
28	char *expr;
29
30	/* Type of object */
31	int type;
32};
33
34/* Key */
35int semanage_fcontext_key_create(semanage_handle_t * handle,
36				 const char *expr,
37				 int type, semanage_fcontext_key_t ** key_ptr)
38{
39
40	semanage_fcontext_key_t *tmp_key =
41	    (semanage_fcontext_key_t *) malloc(sizeof(semanage_fcontext_key_t));
42
43	if (!tmp_key) {
44		ERR(handle, "out of memory, could not "
45		    "create file context key");
46		return STATUS_ERR;
47	}
48	tmp_key->expr = strdup(expr);
49	if (!tmp_key->expr) {
50		ERR(handle, "out of memory, could not create file context key.");
51		free(tmp_key);
52		return STATUS_ERR;
53	}
54	tmp_key->type = type;
55
56	*key_ptr = tmp_key;
57	return STATUS_SUCCESS;
58}
59
60hidden_def(semanage_fcontext_key_create)
61
62int semanage_fcontext_key_extract(semanage_handle_t * handle,
63				  const semanage_fcontext_t * fcontext,
64				  semanage_fcontext_key_t ** key_ptr)
65{
66
67	if (semanage_fcontext_key_create(handle, fcontext->expr,
68					 fcontext->type, key_ptr) < 0) {
69		ERR(handle, "could not extract key from "
70		    "file context %s (%s)", fcontext->expr,
71		    semanage_fcontext_get_type_str(fcontext->type));
72		return STATUS_ERR;
73	}
74
75	return STATUS_SUCCESS;
76}
77
78hidden_def(semanage_fcontext_key_extract)
79
80void semanage_fcontext_key_free(semanage_fcontext_key_t * key)
81{
82	free(key->expr);
83	free(key);
84}
85
86hidden_def(semanage_fcontext_key_free)
87
88int semanage_fcontext_compare(const semanage_fcontext_t * fcontext,
89			      const semanage_fcontext_key_t * key)
90{
91
92	int rv = strcmp(fcontext->expr, key->expr);
93	if (rv != 0)
94		return rv;
95	else {
96		if (fcontext->type < key->type)
97			return -1;
98
99		else if (key->type < fcontext->type)
100			return 1;
101
102		else
103			return 0;
104	}
105}
106
107hidden_def(semanage_fcontext_compare)
108
109int semanage_fcontext_compare2(const semanage_fcontext_t * fcontext,
110			       const semanage_fcontext_t * fcontext2)
111{
112
113	int rv = strcmp(fcontext->expr, fcontext2->expr);
114	if (rv != 0)
115		return rv;
116	else {
117		if (fcontext->type < fcontext2->type)
118			return -1;
119
120		else if (fcontext2->type < fcontext->type)
121			return 1;
122
123		else
124			return 0;
125	}
126}
127
128hidden_def(semanage_fcontext_compare2)
129
130static int semanage_fcontext_compare2_qsort(const semanage_fcontext_t **
131					    fcontext,
132					    const semanage_fcontext_t **
133					    fcontext2)
134{
135
136	return semanage_fcontext_compare2(*fcontext, *fcontext2);
137}
138
139/* Create */
140int semanage_fcontext_create(semanage_handle_t * handle,
141			     semanage_fcontext_t ** fcontext)
142{
143
144	semanage_fcontext_t *tmp_fcontext =
145	    (semanage_fcontext_t *) malloc(sizeof(semanage_fcontext_t));
146
147	if (!tmp_fcontext) {
148		ERR(handle, "out of memory, could not create "
149		    "file context record");
150		return STATUS_ERR;
151	}
152
153	tmp_fcontext->expr = NULL;
154	tmp_fcontext->type = SEMANAGE_FCONTEXT_ALL;
155	tmp_fcontext->con = NULL;
156	*fcontext = tmp_fcontext;
157
158	return STATUS_SUCCESS;
159}
160
161hidden_def(semanage_fcontext_create)
162
163/* Regexp */
164const char *semanage_fcontext_get_expr(const semanage_fcontext_t * fcontext)
165{
166
167	return fcontext->expr;
168}
169
170hidden_def(semanage_fcontext_get_expr)
171
172int semanage_fcontext_set_expr(semanage_handle_t * handle,
173			       semanage_fcontext_t * fcontext, const char *expr)
174{
175
176	char *tmp_expr = strdup(expr);
177	if (!tmp_expr) {
178		ERR(handle, "out of memory, " "could not set regexp string");
179		return STATUS_ERR;
180	}
181	free(fcontext->expr);
182	fcontext->expr = tmp_expr;
183	return STATUS_SUCCESS;
184}
185
186hidden_def(semanage_fcontext_set_expr)
187
188/* Type */
189int semanage_fcontext_get_type(const semanage_fcontext_t * fcontext)
190{
191
192	return fcontext->type;
193}
194
195hidden_def(semanage_fcontext_get_type)
196
197const char *semanage_fcontext_get_type_str(int type)
198{
199
200	switch (type) {
201	case SEMANAGE_FCONTEXT_ALL:
202		return "all files";
203	case SEMANAGE_FCONTEXT_REG:
204		return "regular file";
205	case SEMANAGE_FCONTEXT_DIR:
206		return "directory";
207	case SEMANAGE_FCONTEXT_CHAR:
208		return "character device";
209	case SEMANAGE_FCONTEXT_BLOCK:
210		return "block device";
211	case SEMANAGE_FCONTEXT_SOCK:
212		return "socket";
213	case SEMANAGE_FCONTEXT_LINK:
214		return "symbolic link";
215	case SEMANAGE_FCONTEXT_PIPE:
216		return "named pipe";
217	default:
218		return "????";
219	}
220}
221
222hidden_def(semanage_fcontext_get_type_str)
223
224void semanage_fcontext_set_type(semanage_fcontext_t * fcontext, int type)
225{
226
227	fcontext->type = type;
228}
229
230hidden_def(semanage_fcontext_set_type)
231
232/* Context */
233semanage_context_t *semanage_fcontext_get_con(const semanage_fcontext_t *
234					      fcontext)
235{
236
237	return fcontext->con;
238}
239
240hidden_def(semanage_fcontext_get_con)
241
242int semanage_fcontext_set_con(semanage_handle_t * handle,
243			      semanage_fcontext_t * fcontext,
244			      semanage_context_t * con)
245{
246
247	semanage_context_t *newcon;
248
249	if (semanage_context_clone(handle, con, &newcon) < 0) {
250		ERR(handle, "out of memory, could not set file context");
251		return STATUS_ERR;
252	}
253
254	semanage_context_free(fcontext->con);
255	fcontext->con = newcon;
256	return STATUS_SUCCESS;
257}
258
259hidden_def(semanage_fcontext_set_con)
260
261/* Deep copy clone */
262int semanage_fcontext_clone(semanage_handle_t * handle,
263			    const semanage_fcontext_t * fcontext,
264			    semanage_fcontext_t ** fcontext_ptr)
265{
266
267	semanage_fcontext_t *new_fcontext = NULL;
268	if (semanage_fcontext_create(handle, &new_fcontext) < 0)
269		goto err;
270
271	if (semanage_fcontext_set_expr(handle, new_fcontext, fcontext->expr) <
272	    0)
273		goto err;
274
275	new_fcontext->type = fcontext->type;
276
277	if (fcontext->con &&
278	    (semanage_context_clone(handle, fcontext->con, &new_fcontext->con) <
279	     0))
280		goto err;
281
282	*fcontext_ptr = new_fcontext;
283	return STATUS_SUCCESS;
284
285      err:
286	ERR(handle, "could not clone file context record");
287	semanage_fcontext_free(new_fcontext);
288	return STATUS_ERR;
289}
290
291hidden_def(semanage_fcontext_clone)
292
293/* Destroy */
294void semanage_fcontext_free(semanage_fcontext_t * fcontext)
295{
296
297	if (!fcontext)
298		return;
299
300	free(fcontext->expr);
301	semanage_context_free(fcontext->con);
302	free(fcontext);
303}
304
305hidden_def(semanage_fcontext_free)
306
307/* Record base functions */
308record_table_t SEMANAGE_FCONTEXT_RTABLE = {
309	.create = semanage_fcontext_create,
310	.key_extract = semanage_fcontext_key_extract,
311	.key_free = semanage_fcontext_key_free,
312	.clone = semanage_fcontext_clone,
313	.compare = semanage_fcontext_compare,
314	.compare2 = semanage_fcontext_compare2,
315	.compare2_qsort = semanage_fcontext_compare2_qsort,
316	.free = semanage_fcontext_free,
317};
318