a806c6add92ae6c43792af78d232f01d5e0ac1c2
[kai/samba.git] / source3 / lib / dbwrap / dbwrap.c
1 /*
2    Unix SMB/CIFS implementation.
3    Database interface wrapper
4    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2006
5
6    Major code contributions from Aleksey Fedoseev (fedoseev@ru.ibm.com)
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "dbwrap/dbwrap.h"
24 #include "dbwrap/dbwrap_private.h"
25 #include "util_tdb.h"
26
27 /*
28  * Fall back using fetch_locked if no genuine fetch operation is provided
29  */
30
31 static NTSTATUS dbwrap_fallback_fetch(struct db_context *db,
32                                       TALLOC_CTX *mem_ctx,
33                                       TDB_DATA key, TDB_DATA *data)
34 {
35         struct db_record *rec;
36
37         rec = dbwrap_fetch_locked(db, mem_ctx, key);
38         if (rec == NULL) {
39                 return NT_STATUS_UNSUCCESSFUL;
40         }
41
42         data->dsize = rec->value.dsize;
43         data->dptr = talloc_move(mem_ctx, &rec->value.dptr);
44         TALLOC_FREE(rec);
45         return NT_STATUS_OK;
46 }
47
48 /*
49  * Fall back using fetch if no genuine exists operation is provided
50  */
51
52 static int dbwrap_fallback_exists(struct db_context *db, TDB_DATA key)
53 {
54         int res = dbwrap_parse_record(db, key, NULL, NULL);
55         return  ( res == -1) ? 0 : 1;
56 }
57
58 /*
59  * Fall back using fetch if no genuine parse operation is provided
60  */
61
62 static int dbwrap_fallback_parse_record(struct db_context *db, TDB_DATA key,
63                                         int (*parser)(TDB_DATA key,
64                                                       TDB_DATA data,
65                                                       void *private_data),
66                                         void *private_data)
67 {
68         TDB_DATA data;
69         int res;
70         NTSTATUS status;
71
72         status = dbwrap_fetch(db, talloc_tos(), key, &data);
73         if (!NT_STATUS_IS_OK(status)) {
74                 return -1;
75         }
76
77         res = parser(key, data, private_data);
78         TALLOC_FREE(data.dptr);
79         return res;
80 }
81
82
83 static int delete_record(struct db_record *rec, void *data)
84 {
85         NTSTATUS status = dbwrap_record_delete(rec);
86         return NT_STATUS_IS_OK(status) ? 0 : -1;
87 }
88
89 /*
90  * Fallback wipe implementation using traverse and delete if no genuine
91  * wipe operation is provided
92  */
93 static int dbwrap_fallback_wipe(struct db_context *db)
94 {
95         NTSTATUS status = dbwrap_trans_traverse(db, delete_record, NULL);
96         return NT_STATUS_IS_OK(status) ? 0 : -1;
97 }
98
99
100 /*
101  * Wrapper functions for the backend methods
102  */
103
104 TDB_DATA dbwrap_record_get_key(const struct db_record *rec)
105 {
106         return rec->key;
107 }
108
109 TDB_DATA dbwrap_record_get_value(const struct db_record *rec)
110 {
111         return rec->value;
112 }
113
114 NTSTATUS dbwrap_record_store(struct db_record *rec, TDB_DATA data, int flags)
115 {
116         return rec->store(rec, data, flags);
117 }
118
119 NTSTATUS dbwrap_record_delete(struct db_record *rec)
120 {
121         return rec->delete_rec(rec);
122 }
123
124 struct db_record *dbwrap_fetch_locked(struct db_context *db,
125                                       TALLOC_CTX *mem_ctx,
126                                       TDB_DATA key)
127 {
128         return db->fetch_locked(db, mem_ctx, key);
129 }
130
131 NTSTATUS dbwrap_fetch(struct db_context *db, TALLOC_CTX *mem_ctx,
132                       TDB_DATA key, TDB_DATA *value)
133 {
134         if (value == NULL) {
135                 return NT_STATUS_INVALID_PARAMETER;
136         }
137         if (db->fetch == NULL) {
138                 return dbwrap_fallback_fetch(db, mem_ctx, key, value);
139         }
140         return db->fetch(db, mem_ctx, key, value);
141 }
142
143 bool dbwrap_exists(struct db_context *db, TDB_DATA key)
144 {
145         int result;
146         if (db->exists != NULL) {
147                 result = db->exists(db, key);
148         } else {
149                 result = dbwrap_fallback_exists(db,key);
150         }
151         return (result == 1);
152 }
153
154 NTSTATUS dbwrap_store(struct db_context *db, TDB_DATA key,
155                       TDB_DATA data, int flags)
156 {
157         struct db_record *rec;
158         NTSTATUS status;
159
160         rec = dbwrap_fetch_locked(db, talloc_tos(), key);
161         if (rec == NULL) {
162                 return NT_STATUS_NO_MEMORY;
163         }
164
165         status = dbwrap_record_store(rec, data, flags);
166         TALLOC_FREE(rec);
167         return status;
168 }
169
170 NTSTATUS dbwrap_delete(struct db_context *db, TDB_DATA key)
171 {
172         struct db_record *rec;
173         NTSTATUS status;
174
175         rec = dbwrap_fetch_locked(db, talloc_tos(), key);
176         if (rec == NULL) {
177                 return NT_STATUS_NO_MEMORY;
178         }
179         status = dbwrap_record_delete(rec);
180         TALLOC_FREE(rec);
181         return status;
182 }
183
184 NTSTATUS dbwrap_traverse(struct db_context *db,
185                          int (*f)(struct db_record*, void*),
186                          void *private_data,
187                          int *count)
188 {
189         int ret = db->traverse(db, f, private_data);
190
191         if (ret < 0) {
192                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
193         }
194
195         if (count != NULL) {
196                 *count = ret;
197         }
198
199         return NT_STATUS_OK;
200 }
201
202 NTSTATUS dbwrap_traverse_read(struct db_context *db,
203                               int (*f)(struct db_record*, void*),
204                               void *private_data,
205                               int *count)
206 {
207         int ret = db->traverse_read(db, f, private_data);
208
209         if (ret < 0) {
210                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
211         }
212
213         if (count != NULL) {
214                 *count = ret;
215         }
216
217         return NT_STATUS_OK;
218 }
219
220 static int dbwrap_null_parser(TDB_DATA key, TDB_DATA val, void* data)
221 {
222         return 0;
223 }
224
225 int dbwrap_parse_record(struct db_context *db, TDB_DATA key,
226                         int (*parser)(TDB_DATA key, TDB_DATA data,
227                                       void *private_data),
228                         void *private_data)
229 {
230         if (parser == NULL) {
231                 parser = dbwrap_null_parser;
232         }
233
234         if (db->parse_record == NULL) {
235                 return dbwrap_fallback_parse_record(db, key, parser,
236                                                     private_data);
237         }
238         return db->parse_record(db, key, parser, private_data);
239 }
240
241 int dbwrap_wipe(struct db_context *db)
242 {
243         if (db->wipe == NULL) {
244                 return dbwrap_fallback_wipe(db);
245         }
246         return db->wipe(db);
247 }
248
249 int dbwrap_get_seqnum(struct db_context *db)
250 {
251         return db->get_seqnum(db);
252 }
253
254 int dbwrap_get_flags(struct db_context *db)
255 {
256         return db->get_flags(db);
257 }
258
259 int dbwrap_transaction_start(struct db_context *db)
260 {
261         return db->transaction_start(db);
262 }
263
264 int dbwrap_transaction_commit(struct db_context *db)
265 {
266         return db->transaction_commit(db);
267 }
268
269 int dbwrap_transaction_cancel(struct db_context *db)
270 {
271         return db->transaction_cancel(db);
272 }