Add dbwrap_trans_*_bystring
[abartlet/samba.git/.git] / source3 / lib / dbwrap_util.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Utility functions for the dbwrap API
4    Copyright (C) Volker Lendecke 2007
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 int32_t dbwrap_fetch_int32(struct db_context *db, const char *keystr)
24 {
25         TDB_DATA dbuf;
26         int32 ret;
27
28         if (db->fetch(db, NULL, string_term_tdb_data(keystr), &dbuf) != 0) {
29                 return -1;
30         }
31
32         if ((dbuf.dptr == NULL) || (dbuf.dsize != sizeof(int32_t))) {
33                 TALLOC_FREE(dbuf.dptr);
34                 return -1;
35         }
36
37         ret = IVAL(dbuf.dptr, 0);
38         TALLOC_FREE(dbuf.dptr);
39         return ret;
40 }
41
42 int dbwrap_store_int32(struct db_context *db, const char *keystr, int32_t v)
43 {
44         struct db_record *rec;
45         int32 v_store;
46         NTSTATUS status;
47
48         rec = db->fetch_locked(db, NULL, string_term_tdb_data(keystr));
49         if (rec == NULL) {
50                 return -1;
51         }
52
53         SIVAL(&v_store, 0, v);
54
55         status = rec->store(rec, make_tdb_data((const uint8 *)&v_store,
56                                                sizeof(v_store)),
57                             TDB_REPLACE);
58         TALLOC_FREE(rec);
59         return NT_STATUS_IS_OK(status) ? 0 : -1;
60 }
61
62 bool dbwrap_fetch_uint32(struct db_context *db, const char *keystr,
63                          uint32_t *val)
64 {
65         TDB_DATA dbuf;
66
67         if (db->fetch(db, NULL, string_term_tdb_data(keystr), &dbuf) != 0) {
68                 return false;
69         }
70
71         if ((dbuf.dptr == NULL) || (dbuf.dsize != sizeof(uint32_t))) {
72                 TALLOC_FREE(dbuf.dptr);
73                 return false;
74         }
75
76         *val = IVAL(dbuf.dptr, 0);
77         TALLOC_FREE(dbuf.dptr);
78         return true;
79 }
80
81 bool dbwrap_store_uint32(struct db_context *db, const char *keystr, uint32_t v)
82 {
83         struct db_record *rec;
84         uint32 v_store;
85         NTSTATUS status;
86
87         rec = db->fetch_locked(db, NULL, string_term_tdb_data(keystr));
88         if (rec == NULL) {
89                 return false;
90         }
91
92         SIVAL(&v_store, 0, v);
93
94         status = rec->store(rec, make_tdb_data((const uint8 *)&v_store,
95                                                sizeof(v_store)),
96                             TDB_REPLACE);
97         TALLOC_FREE(rec);
98         return NT_STATUS_IS_OK(status) ? 0 : -1;
99 }
100
101 uint32_t dbwrap_change_uint32_atomic(struct db_context *db, const char *keystr,
102                                      uint32_t *oldval, uint32_t change_val)
103 {
104         struct db_record *rec;
105         uint32 val = -1;
106         TDB_DATA data;
107
108         if (!(rec = db->fetch_locked(db, NULL,
109                                      string_term_tdb_data(keystr)))) {
110                 return -1;
111         }
112
113         if ((rec->value.dptr != NULL)
114             && (rec->value.dsize == sizeof(val))) {
115                 val = IVAL(rec->value.dptr, 0);
116         }
117
118         val += change_val;
119
120         data.dsize = sizeof(val);
121         data.dptr = (uint8 *)&val;
122
123         rec->store(rec, data, TDB_REPLACE);
124
125         TALLOC_FREE(rec);
126
127         return 0;
128 }
129
130 int32 dbwrap_change_int32_atomic(struct db_context *db, const char *keystr,
131                                  int32 *oldval, int32 change_val)
132 {
133         struct db_record *rec;
134         int32 val = -1;
135         TDB_DATA data;
136
137         if (!(rec = db->fetch_locked(db, NULL,
138                                      string_term_tdb_data(keystr)))) {
139                 return -1;
140         }
141
142         if ((rec->value.dptr != NULL)
143             && (rec->value.dsize == sizeof(val))) {
144                 val = IVAL(rec->value.dptr, 0);
145         }
146
147         val += change_val;
148
149         data.dsize = sizeof(val);
150         data.dptr = (uint8 *)&val;
151
152         rec->store(rec, data, TDB_REPLACE);
153
154         TALLOC_FREE(rec);
155
156         return 0;
157 }
158
159 NTSTATUS dbwrap_trans_store(struct db_context *db, TDB_DATA key, TDB_DATA dbuf,
160                             int flag)
161 {
162         int res;
163         struct db_record *rec;
164         NTSTATUS status;
165
166         res = db->transaction_start(db);
167         if (res != 0) {
168                 DEBUG(5, ("transaction_start failed\n"));
169                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
170         }
171
172         rec = db->fetch_locked(db, talloc_tos(), key);
173         if (rec == NULL) {
174                 DEBUG(5, ("fetch_locked failed\n"));
175                 status = NT_STATUS_NO_MEMORY;
176                 goto cancel;
177         }
178
179         status = rec->store(rec, dbuf, flag);
180         if (!NT_STATUS_IS_OK(status)) {
181                 DEBUG(5, ("store returned %s\n", nt_errstr(status)));
182                 goto cancel;
183         }
184
185         TALLOC_FREE(rec);
186
187         res = db->transaction_commit(db);
188         if (res != 0) {
189                 DEBUG(5, ("tdb_transaction_commit failed\n"));
190                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
191                 goto cancel;
192         }
193
194         return NT_STATUS_OK;
195
196  cancel:
197         if (db->transaction_cancel(db) != 0) {
198                 smb_panic("Cancelling transaction failed");
199         }
200         return status;
201 }
202
203 NTSTATUS dbwrap_trans_delete(struct db_context *db, TDB_DATA key)
204 {
205         int res;
206         struct db_record *rec;
207         NTSTATUS status;
208
209         res = db->transaction_start(db);
210         if (res != 0) {
211                 DEBUG(5, ("transaction_start failed\n"));
212                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
213         }
214
215         rec = db->fetch_locked(db, talloc_tos(), key);
216         if (rec == NULL) {
217                 DEBUG(5, ("fetch_locked failed\n"));
218                 status = NT_STATUS_NO_MEMORY;
219                 goto cancel;
220         }
221
222         status = rec->delete_rec(rec);
223         if (!NT_STATUS_IS_OK(status)) {
224                 DEBUG(5, ("delete_rec returned %s\n", nt_errstr(status)));
225                 goto cancel;
226         }
227
228         TALLOC_FREE(rec);
229
230         res = db->transaction_commit(db);
231         if (res != 0) {
232                 DEBUG(5, ("tdb_transaction_commit failed\n"));
233                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
234                 goto cancel;
235         }
236
237         return NT_STATUS_OK;
238
239  cancel:
240         if (db->transaction_cancel(db) != 0) {
241                 smb_panic("Cancelling transaction failed");
242         }
243         return status;
244 }
245
246 NTSTATUS dbwrap_trans_store_int32(struct db_context *db, const char *keystr,
247                                   int32_t v)
248 {
249         int32 v_store;
250
251         SIVAL(&v_store, 0, v);
252
253         return dbwrap_trans_store(db, string_term_tdb_data(keystr),
254                                   make_tdb_data((const uint8 *)&v_store,
255                                                 sizeof(v_store)),
256                                   TDB_REPLACE);
257 }
258
259 NTSTATUS dbwrap_trans_store_bystring(struct db_context *db, const char *key,
260                                      TDB_DATA data, int flags)
261 {
262         return dbwrap_trans_store(db, string_term_tdb_data(key), data, flags);
263 }
264
265 NTSTATUS dbwrap_trans_delete_bystring(struct db_context *db, const char *key)
266 {
267         return dbwrap_trans_delete(db, string_term_tdb_data(key));
268 }