1/* Copyright (C) 2005 Red Hat, Inc. */
2
3/* Object: dbase_activedb_t (Active/Kernel)
4 * Extends: dbase_llist_t (Linked List)
5 * Implements: dbase_t (Database)
6 */
7
8struct dbase_activedb;
9typedef struct dbase_activedb dbase_t;
10#define DBASE_DEFINED
11
12#include <stdlib.h>
13#include <string.h>
14#include <errno.h>
15#include "debug.h"
16#include "handle.h"
17#include "database_activedb.h"
18#include "database_llist.h"
19
20/* ACTIVEDB dbase */
21struct dbase_activedb {
22
23	/* Parent object - must always be
24	 * the first field - here we are using
25	 * a linked list to store the records */
26	dbase_llist_t llist;
27
28	/* ACTIVEDB extension */
29	record_activedb_table_t *ratable;
30};
31
32static int dbase_activedb_cache(semanage_handle_t * handle,
33				dbase_activedb_t * dbase)
34{
35
36	record_table_t *rtable = dbase_llist_get_rtable(&dbase->llist);
37	record_activedb_table_t *ratable = dbase->ratable;
38
39	record_t **records = NULL;
40	unsigned int rcount = 0;
41	unsigned int i = 0;
42
43	/* Already cached */
44	if (!dbase_llist_needs_resync(handle, &dbase->llist))
45		return STATUS_SUCCESS;
46
47	/* Update cache serial */
48	dbase_llist_cache_init(&dbase->llist);
49	if (dbase_llist_set_serial(handle, &dbase->llist) < 0)
50		goto err;
51
52	/* Fetch the entire list */
53	if (ratable->read_list(handle, &records, &rcount) < 0)
54		goto err;
55
56	/* Add records one by one */
57	for (; i < rcount; i++) {
58		if (dbase_llist_cache_prepend(handle, &dbase->llist, records[i])
59		    < 0)
60			goto err;
61		rtable->free(records[i]);
62	}
63
64	free(records);
65	return STATUS_SUCCESS;
66
67      err:
68	ERR(handle, "could not cache active database");
69	for (; i < rcount; i++)
70		rtable->free(records[i]);
71	dbase_llist_drop_cache(&dbase->llist);
72	free(records);
73	return STATUS_ERR;
74}
75
76static int dbase_activedb_flush(semanage_handle_t * handle,
77				dbase_activedb_t * dbase)
78{
79
80	record_table_t *rtable = dbase_llist_get_rtable(&dbase->llist);
81	record_activedb_table_t *ratable = dbase->ratable;
82
83	record_t **records = NULL;
84	unsigned int rcount = 0;
85	unsigned int i;
86
87	/* Not cached, or not modified - flush is not necessary */
88	if (!dbase_llist_is_modified(&dbase->llist))
89		return STATUS_SUCCESS;
90
91	/* Fetch list */
92	if (dbase_llist_list(handle, &dbase->llist, &records, &rcount) < 0)
93		goto err;
94
95	/* Commit */
96	if (ratable->commit_list(handle, records, rcount) < 0)
97		goto err;
98
99	for (i = 0; i < rcount; i++)
100		rtable->free(records[i]);
101	free(records);
102	dbase_llist_set_modified(&dbase->llist, 0);
103	return STATUS_SUCCESS;
104
105      err:
106	for (i = 0; i < rcount; i++)
107		rtable->free(records[i]);
108	free(records);
109	ERR(handle, "could not flush active database");
110	return STATUS_ERR;
111}
112
113int dbase_activedb_init(semanage_handle_t * handle,
114			record_table_t * rtable,
115			record_activedb_table_t * ratable,
116			dbase_activedb_t ** dbase)
117{
118
119	dbase_activedb_t *tmp_dbase =
120	    (dbase_activedb_t *) malloc(sizeof(dbase_activedb_t));
121
122	if (!tmp_dbase)
123		goto omem;
124
125	tmp_dbase->ratable = ratable;
126	dbase_llist_init(&tmp_dbase->llist, rtable, &SEMANAGE_ACTIVEDB_DTABLE);
127
128	*dbase = tmp_dbase;
129
130	return STATUS_SUCCESS;
131
132      omem:
133	ERR(handle, "out of memory, could not initialize active database");
134	free(tmp_dbase);
135	return STATUS_ERR;
136}
137
138/* Release dbase resources */
139void dbase_activedb_release(dbase_activedb_t * dbase)
140{
141
142	dbase_llist_drop_cache(&dbase->llist);
143	free(dbase);
144}
145
146/* ACTIVEDB dbase - method table implementation */
147dbase_table_t SEMANAGE_ACTIVEDB_DTABLE = {
148
149	/* Cache/Transactions */
150	.cache = dbase_activedb_cache,
151	.drop_cache = (void *)dbase_llist_drop_cache,
152	.flush = dbase_activedb_flush,
153	.is_modified = (void *)dbase_llist_is_modified,
154
155	/* Database API */
156	.iterate = (void *)dbase_llist_iterate,
157	.exists = (void *)dbase_llist_exists,
158	.list = (void *)dbase_llist_list,
159	.add = (void *)dbase_llist_add,
160	.set = (void *)dbase_llist_set,
161	.del = (void *)dbase_llist_del,
162	.clear = (void *)dbase_llist_clear,
163	.modify = (void *)dbase_llist_modify,
164	.query = (void *)dbase_llist_query,
165	.count = (void *)dbase_llist_count,
166
167	/* Polymorphism */
168	.get_rtable = (void *)dbase_llist_get_rtable
169};
170