Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Utility functions for the dbwrap API
4 : Copyright (C) Volker Lendecke 2007
5 : Copyright (C) Michael Adam 2009
6 : Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2006
7 :
8 : Major code contributions from Aleksey Fedoseev (fedoseev@ru.ibm.com)
9 :
10 : This program is free software; you can redistribute it and/or modify
11 : it under the terms of the GNU General Public License as published by
12 : the Free Software Foundation; either version 2 of the License, or
13 : (at your option) any later version.
14 :
15 : This program is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : GNU General Public License for more details.
19 :
20 : You should have received a copy of the GNU General Public License
21 : along with this program; if not, write to the Free Software
22 : Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 : */
24 :
25 : #include "includes.h"
26 : #include "dbwrap.h"
27 : #include "lib/util/util_tdb.h"
28 :
29 : struct dbwrap_fetch_int32_state {
30 : NTSTATUS status;
31 : int32_t result;
32 : };
33 :
34 5159 : static void dbwrap_fetch_int32_parser(TDB_DATA key, TDB_DATA data,
35 : void *private_data)
36 : {
37 5159 : struct dbwrap_fetch_int32_state *state =
38 : (struct dbwrap_fetch_int32_state *)private_data;
39 :
40 5159 : if (data.dsize != sizeof(state->result)) {
41 0 : state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
42 0 : return;
43 : }
44 5159 : state->result = IVAL(data.dptr, 0);
45 5159 : state->status = NT_STATUS_OK;
46 : }
47 :
48 6452 : NTSTATUS dbwrap_fetch_int32(struct db_context *db, TDB_DATA key,
49 : int32_t *result)
50 : {
51 : struct dbwrap_fetch_int32_state state;
52 : NTSTATUS status;
53 :
54 6452 : if (result == NULL) {
55 0 : return NT_STATUS_INVALID_PARAMETER;
56 : }
57 :
58 6452 : state.status = NT_STATUS_INTERNAL_ERROR;
59 :
60 6452 : status = dbwrap_parse_record(db, key, dbwrap_fetch_int32_parser, &state);
61 6452 : if (!NT_STATUS_IS_OK(status)) {
62 1293 : return status;
63 : }
64 :
65 5159 : if (NT_STATUS_IS_OK(state.status)) {
66 5159 : *result = state.result;
67 : }
68 5159 : return state.status;
69 : }
70 :
71 5413 : NTSTATUS dbwrap_fetch_int32_bystring(struct db_context *db, const char *keystr,
72 : int32_t *result)
73 : {
74 5413 : return dbwrap_fetch_int32(db, string_term_tdb_data(keystr), result);
75 : }
76 :
77 196 : NTSTATUS dbwrap_store_int32_bystring(struct db_context *db, const char *keystr,
78 : int32_t v)
79 : {
80 : uint8_t v_store[sizeof(int32_t)];
81 196 : TDB_DATA data = { .dptr = v_store, .dsize = sizeof(v_store) };
82 : NTSTATUS status;
83 :
84 196 : SIVAL(v_store, 0, v);
85 :
86 196 : status = dbwrap_store(db, string_term_tdb_data(keystr), data,
87 : TDB_REPLACE);
88 196 : return status;
89 : }
90 :
91 : struct dbwrap_fetch_uint32_state {
92 : NTSTATUS status;
93 : uint32_t result;
94 : };
95 :
96 9125 : static void dbwrap_fetch_uint32_parser(TDB_DATA key, TDB_DATA data,
97 : void *private_data)
98 : {
99 9125 : struct dbwrap_fetch_uint32_state *state =
100 : (struct dbwrap_fetch_uint32_state *)private_data;
101 :
102 9125 : if (data.dsize != sizeof(state->result)) {
103 0 : state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
104 0 : return;
105 : }
106 9125 : state->result = IVAL(data.dptr, 0);
107 9125 : state->status = NT_STATUS_OK;
108 : }
109 :
110 10126 : NTSTATUS dbwrap_fetch_uint32_bystring(struct db_context *db,
111 : const char *keystr, uint32_t *val)
112 : {
113 : struct dbwrap_fetch_uint32_state state;
114 : NTSTATUS status;
115 :
116 10126 : if (val == NULL) {
117 0 : return NT_STATUS_INVALID_PARAMETER;
118 : }
119 :
120 10126 : state.status = NT_STATUS_INTERNAL_ERROR;
121 :
122 10126 : status = dbwrap_parse_record(db, string_term_tdb_data(keystr),
123 : dbwrap_fetch_uint32_parser, &state);
124 10126 : if (!NT_STATUS_IS_OK(status)) {
125 1001 : return status;
126 : }
127 9125 : if (NT_STATUS_IS_OK(state.status)) {
128 9125 : *val = state.result;
129 : }
130 9125 : return state.status;
131 : }
132 :
133 110 : NTSTATUS dbwrap_store_uint32_bystring(struct db_context *db,
134 : const char *keystr, uint32_t v)
135 : {
136 : uint8_t v_store[sizeof(uint32_t)];
137 110 : TDB_DATA data = { .dptr = v_store, .dsize = sizeof(v_store) };
138 : NTSTATUS status;
139 :
140 110 : SIVAL(v_store, 0, v);
141 :
142 110 : status = dbwrap_store(db, string_term_tdb_data(keystr), data,
143 : TDB_REPLACE);
144 110 : return status;
145 : }
146 :
147 : /**
148 : * Atomic unsigned integer change (addition):
149 : *
150 : * if value does not exist yet in the db, use *oldval as initial old value.
151 : * return old value in *oldval.
152 : * store *oldval + change_val to db.
153 : */
154 :
155 : struct dbwrap_change_uint32_atomic_context {
156 : const char *keystr;
157 : uint32_t *oldval;
158 : uint32_t change_val;
159 : };
160 :
161 293 : static NTSTATUS dbwrap_change_uint32_atomic_action(struct db_context *db,
162 : void *private_data)
163 : {
164 : struct db_record *rec;
165 293 : uint32_t val = (uint32_t)-1;
166 : uint32_t v_store;
167 : NTSTATUS ret;
168 : struct dbwrap_change_uint32_atomic_context *state;
169 : TDB_DATA value;
170 :
171 293 : state = (struct dbwrap_change_uint32_atomic_context *)private_data;
172 :
173 293 : rec = dbwrap_fetch_locked(db, talloc_tos(),
174 : string_term_tdb_data(state->keystr));
175 293 : if (!rec) {
176 0 : return NT_STATUS_UNSUCCESSFUL;
177 : }
178 :
179 293 : value = dbwrap_record_get_value(rec);
180 :
181 293 : if (value.dptr == NULL) {
182 0 : val = *(state->oldval);
183 293 : } else if (value.dsize == sizeof(val)) {
184 293 : val = IVAL(value.dptr, 0);
185 293 : *(state->oldval) = val;
186 : } else {
187 0 : ret = NT_STATUS_UNSUCCESSFUL;
188 0 : goto done;
189 : }
190 :
191 293 : val += state->change_val;
192 :
193 293 : SIVAL(&v_store, 0, val);
194 :
195 293 : ret = dbwrap_record_store(rec,
196 : make_tdb_data((const uint8_t *)&v_store,
197 : sizeof(v_store)),
198 : TDB_REPLACE);
199 :
200 293 : done:
201 293 : TALLOC_FREE(rec);
202 293 : return ret;
203 : }
204 :
205 0 : NTSTATUS dbwrap_change_uint32_atomic_bystring(struct db_context *db,
206 : const char *keystr,
207 : uint32_t *oldval,
208 : uint32_t change_val)
209 : {
210 : NTSTATUS ret;
211 : struct dbwrap_change_uint32_atomic_context state;
212 :
213 0 : state.keystr = keystr;
214 0 : state.oldval = oldval;
215 0 : state.change_val = change_val;
216 :
217 0 : ret = dbwrap_change_uint32_atomic_action(db, &state);
218 :
219 0 : return ret;
220 : }
221 :
222 293 : NTSTATUS dbwrap_trans_change_uint32_atomic_bystring(struct db_context *db,
223 : const char *keystr,
224 : uint32_t *oldval,
225 : uint32_t change_val)
226 : {
227 : NTSTATUS ret;
228 : struct dbwrap_change_uint32_atomic_context state;
229 :
230 293 : state.keystr = keystr;
231 293 : state.oldval = oldval;
232 293 : state.change_val = change_val;
233 :
234 293 : ret = dbwrap_trans_do(db, dbwrap_change_uint32_atomic_action, &state);
235 :
236 293 : return ret;
237 : }
238 :
239 : /**
240 : * Atomic integer change (addition):
241 : *
242 : * if value does not exist yet in the db, use *oldval as initial old value.
243 : * return old value in *oldval.
244 : * store *oldval + change_val to db.
245 : */
246 :
247 : struct dbwrap_change_int32_atomic_context {
248 : TDB_DATA key;
249 : int32_t *oldval;
250 : int32_t change_val;
251 : };
252 :
253 10 : static NTSTATUS dbwrap_change_int32_atomic_action(struct db_context *db,
254 : void *private_data)
255 : {
256 : struct db_record *rec;
257 10 : int32_t val = -1;
258 : int32_t v_store;
259 : NTSTATUS ret;
260 : struct dbwrap_change_int32_atomic_context *state;
261 : TDB_DATA value;
262 :
263 10 : state = (struct dbwrap_change_int32_atomic_context *)private_data;
264 :
265 10 : rec = dbwrap_fetch_locked(db, talloc_tos(), state->key);
266 10 : if (!rec) {
267 0 : return NT_STATUS_UNSUCCESSFUL;
268 : }
269 :
270 10 : value = dbwrap_record_get_value(rec);
271 :
272 10 : if (value.dptr == NULL) {
273 5 : val = *(state->oldval);
274 5 : } else if (value.dsize == sizeof(val)) {
275 5 : val = IVAL(value.dptr, 0);
276 5 : *(state->oldval) = val;
277 : } else {
278 0 : ret = NT_STATUS_UNSUCCESSFUL;
279 0 : goto done;
280 : }
281 :
282 10 : val += state->change_val;
283 :
284 10 : SIVAL(&v_store, 0, val);
285 :
286 10 : ret = dbwrap_record_store(rec,
287 : make_tdb_data((const uint8_t *)&v_store,
288 : sizeof(v_store)),
289 : TDB_REPLACE);
290 :
291 10 : done:
292 10 : TALLOC_FREE(rec);
293 10 : return ret;
294 : }
295 :
296 10 : NTSTATUS dbwrap_change_int32_atomic(struct db_context *db,
297 : TDB_DATA key,
298 : int32_t *oldval,
299 : int32_t change_val)
300 : {
301 : NTSTATUS ret;
302 : struct dbwrap_change_int32_atomic_context state;
303 :
304 10 : state.key = key;
305 10 : state.oldval = oldval;
306 10 : state.change_val = change_val;
307 :
308 10 : ret = dbwrap_change_int32_atomic_action(db, &state);
309 :
310 10 : return ret;
311 : }
312 :
313 0 : NTSTATUS dbwrap_change_int32_atomic_bystring(struct db_context *db,
314 : const char *keystr,
315 : int32_t *oldval,
316 : int32_t change_val)
317 : {
318 0 : return dbwrap_change_int32_atomic(db, string_term_tdb_data(keystr),
319 : oldval, change_val);
320 : }
321 :
322 0 : NTSTATUS dbwrap_trans_change_int32_atomic_bystring(struct db_context *db,
323 : const char *keystr,
324 : int32_t *oldval,
325 : int32_t change_val)
326 : {
327 : NTSTATUS ret;
328 : struct dbwrap_change_int32_atomic_context state;
329 :
330 0 : state.key = string_term_tdb_data(keystr);
331 0 : state.oldval = oldval;
332 0 : state.change_val = change_val;
333 :
334 0 : ret = dbwrap_trans_do(db, dbwrap_change_int32_atomic_action, &state);
335 :
336 0 : return ret;
337 : }
338 :
339 : struct dbwrap_store_context {
340 : TDB_DATA *key;
341 : TDB_DATA *dbuf;
342 : int flag;
343 : };
344 :
345 3317 : static NTSTATUS dbwrap_store_action(struct db_context *db, void *private_data)
346 : {
347 : NTSTATUS status;
348 : struct dbwrap_store_context *store_ctx;
349 :
350 3317 : store_ctx = (struct dbwrap_store_context *)private_data;
351 :
352 3317 : status = dbwrap_store(db, *(store_ctx->key), *(store_ctx->dbuf),
353 : store_ctx->flag);
354 3317 : if (!NT_STATUS_IS_OK(status)) {
355 0 : DEBUG(5, ("store returned %s\n", nt_errstr(status)));
356 : }
357 :
358 3317 : return status;
359 : }
360 :
361 3317 : NTSTATUS dbwrap_trans_store(struct db_context *db, TDB_DATA key, TDB_DATA dbuf,
362 : int flag)
363 : {
364 : NTSTATUS status;
365 : struct dbwrap_store_context store_ctx;
366 :
367 3317 : store_ctx.key = &key;
368 3317 : store_ctx.dbuf = &dbuf;
369 3317 : store_ctx.flag = flag;
370 :
371 3317 : status = dbwrap_trans_do(db, dbwrap_store_action, &store_ctx);
372 :
373 3317 : return status;
374 : }
375 :
376 105 : static NTSTATUS dbwrap_delete_action(struct db_context * db, void *private_data)
377 : {
378 : NTSTATUS status;
379 105 : TDB_DATA *key = (TDB_DATA *)private_data;
380 :
381 105 : status = dbwrap_delete(db, *key);
382 105 : if (!NT_STATUS_IS_OK(status)) {
383 1 : DBG_INFO("dbwrap_record_delete returned %s\n",
384 : nt_errstr(status));
385 : }
386 105 : return status;
387 : }
388 :
389 105 : NTSTATUS dbwrap_trans_delete(struct db_context *db, TDB_DATA key)
390 : {
391 : NTSTATUS status;
392 :
393 105 : status = dbwrap_trans_do(db, dbwrap_delete_action, &key);
394 :
395 105 : return status;
396 : }
397 :
398 38 : NTSTATUS dbwrap_trans_store_int32_bystring(struct db_context *db,
399 : const char *keystr,
400 : int32_t v)
401 : {
402 : int32_t v_store;
403 :
404 38 : SIVAL(&v_store, 0, v);
405 :
406 38 : return dbwrap_trans_store(db, string_term_tdb_data(keystr),
407 : make_tdb_data((const uint8_t *)&v_store,
408 : sizeof(v_store)),
409 : TDB_REPLACE);
410 : }
411 :
412 810 : NTSTATUS dbwrap_trans_store_uint32_bystring(struct db_context *db,
413 : const char *keystr,
414 : uint32_t v)
415 : {
416 : uint32_t v_store;
417 :
418 810 : SIVAL(&v_store, 0, v);
419 :
420 810 : return dbwrap_trans_store(db, string_term_tdb_data(keystr),
421 : make_tdb_data((const uint8_t *)&v_store,
422 : sizeof(v_store)),
423 : TDB_REPLACE);
424 : }
425 :
426 888 : NTSTATUS dbwrap_trans_store_bystring(struct db_context *db, const char *key,
427 : TDB_DATA data, int flags)
428 : {
429 888 : return dbwrap_trans_store(db, string_term_tdb_data(key), data, flags);
430 : }
431 :
432 0 : NTSTATUS dbwrap_trans_delete_bystring(struct db_context *db, const char *key)
433 : {
434 0 : return dbwrap_trans_delete(db, string_term_tdb_data(key));
435 : }
436 :
437 : /**
438 : * Wrap db action(s) into a transaction.
439 : */
440 7916 : NTSTATUS dbwrap_trans_do(struct db_context *db,
441 : NTSTATUS (*action)(struct db_context *, void *),
442 : void *private_data)
443 : {
444 : int res;
445 : NTSTATUS status;
446 :
447 7916 : res = dbwrap_transaction_start(db);
448 7916 : if (res != 0) {
449 0 : DEBUG(5, ("transaction_start failed\n"));
450 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
451 : }
452 :
453 7916 : status = action(db, private_data);
454 7916 : if (!NT_STATUS_IS_OK(status)) {
455 1 : if (dbwrap_transaction_cancel(db) != 0) {
456 0 : smb_panic("Cancelling transaction failed");
457 : }
458 1 : return status;
459 : }
460 :
461 7915 : res = dbwrap_transaction_commit(db);
462 7915 : if (res == 0) {
463 7915 : return NT_STATUS_OK;
464 : }
465 :
466 0 : DEBUG(2, ("transaction_commit failed\n"));
467 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
468 : }
469 :
470 : struct dbwrap_trans_traverse_action_ctx {
471 : int (*f)(struct db_record* rec, void* private_data);
472 : void* private_data;
473 : };
474 :
475 :
476 0 : static NTSTATUS dbwrap_trans_traverse_action(struct db_context* db, void* private_data)
477 : {
478 0 : struct dbwrap_trans_traverse_action_ctx* ctx =
479 : (struct dbwrap_trans_traverse_action_ctx*)private_data;
480 :
481 0 : NTSTATUS status = dbwrap_traverse(db, ctx->f, ctx->private_data, NULL);
482 :
483 0 : return status;
484 : }
485 :
486 0 : NTSTATUS dbwrap_trans_traverse(struct db_context *db,
487 : int (*f)(struct db_record*, void*),
488 : void *private_data)
489 : {
490 0 : struct dbwrap_trans_traverse_action_ctx ctx = {
491 : .f = f,
492 : .private_data = private_data,
493 : };
494 0 : return dbwrap_trans_do(db, dbwrap_trans_traverse_action, &ctx);
495 : }
496 :
497 291 : NTSTATUS dbwrap_purge(struct db_context *db, TDB_DATA key)
498 : {
499 : NTSTATUS status;
500 :
501 291 : status = dbwrap_delete(db, key);
502 291 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
503 161 : status = NT_STATUS_OK;
504 : }
505 :
506 291 : return status;
507 : }
508 :
509 255 : NTSTATUS dbwrap_purge_bystring(struct db_context *db, const char *key)
510 : {
511 255 : return dbwrap_purge(db, string_term_tdb_data(key));
512 : }
513 :
514 29877 : NTSTATUS dbwrap_delete_bystring(struct db_context *db, const char *key)
515 : {
516 29877 : return dbwrap_delete(db, string_term_tdb_data(key));
517 : }
518 :
519 75691 : NTSTATUS dbwrap_store_bystring(struct db_context *db, const char *key,
520 : TDB_DATA data, int flags)
521 : {
522 75691 : return dbwrap_store(db, string_term_tdb_data(key), data, flags);
523 : }
524 :
525 576474 : NTSTATUS dbwrap_fetch_bystring(struct db_context *db, TALLOC_CTX *mem_ctx,
526 : const char *key, TDB_DATA *value)
527 : {
528 576474 : return dbwrap_fetch(db, mem_ctx, string_term_tdb_data(key), value);
529 : }
530 :
531 :
532 :
533 67 : NTSTATUS dbwrap_delete_bystring_upper(struct db_context *db, const char *key)
534 : {
535 : char *key_upper;
536 : NTSTATUS status;
537 :
538 67 : key_upper = talloc_strdup_upper(talloc_tos(), key);
539 67 : if (key_upper == NULL) {
540 0 : return NT_STATUS_NO_MEMORY;
541 : }
542 :
543 67 : status = dbwrap_delete_bystring(db, key_upper);
544 :
545 67 : talloc_free(key_upper);
546 67 : return status;
547 : }
548 :
549 15869 : NTSTATUS dbwrap_store_bystring_upper(struct db_context *db, const char *key,
550 : TDB_DATA data, int flags)
551 : {
552 : char *key_upper;
553 : NTSTATUS status;
554 :
555 15869 : key_upper = talloc_strdup_upper(talloc_tos(), key);
556 15869 : if (key_upper == NULL) {
557 0 : return NT_STATUS_NO_MEMORY;
558 : }
559 :
560 15869 : status = dbwrap_store_bystring(db, key_upper, data, flags);
561 :
562 15869 : talloc_free(key_upper);
563 15869 : return status;
564 : }
565 :
566 10979 : NTSTATUS dbwrap_fetch_bystring_upper(struct db_context *db, TALLOC_CTX *mem_ctx,
567 : const char *key, TDB_DATA *value)
568 : {
569 : char *key_upper;
570 : NTSTATUS status;
571 :
572 10979 : key_upper = talloc_strdup_upper(talloc_tos(), key);
573 10979 : if (key_upper == NULL) {
574 0 : return NT_STATUS_NO_MEMORY;
575 : }
576 :
577 10979 : status = dbwrap_fetch_bystring(db, mem_ctx, key_upper, value);
578 :
579 10979 : talloc_free(key_upper);
580 10979 : return status;
581 : }
582 :
583 : struct dbwrap_marshall_state {
584 : uint8_t *buf;
585 : size_t bufsize;
586 : size_t dbsize;
587 : };
588 :
589 0 : static int dbwrap_marshall_fn(struct db_record *rec, void *private_data)
590 : {
591 0 : struct dbwrap_marshall_state *state = private_data;
592 : TDB_DATA key, value;
593 : size_t new_dbsize;
594 :
595 0 : key = dbwrap_record_get_key(rec);
596 0 : value = dbwrap_record_get_value(rec);
597 :
598 0 : new_dbsize = state->dbsize;
599 0 : new_dbsize += 8 + key.dsize;
600 0 : new_dbsize += 8 + value.dsize;
601 :
602 0 : if (new_dbsize <= state->bufsize) {
603 0 : uint8_t *p = state->buf + state->dbsize;
604 :
605 0 : SBVAL(p, 0, key.dsize);
606 0 : p += 8;
607 0 : memcpy(p, key.dptr, key.dsize);
608 0 : p += key.dsize;
609 :
610 0 : SBVAL(p, 0, value.dsize);
611 0 : p += 8;
612 0 : memcpy(p, value.dptr, value.dsize);
613 : }
614 0 : state->dbsize = new_dbsize;
615 0 : return 0;
616 : }
617 :
618 0 : size_t dbwrap_marshall(struct db_context *db, uint8_t *buf, size_t bufsize)
619 : {
620 : struct dbwrap_marshall_state state;
621 :
622 0 : state.bufsize = bufsize;
623 0 : state.buf = buf;
624 0 : state.dbsize = 0;
625 :
626 0 : dbwrap_traverse_read(db, dbwrap_marshall_fn, &state, NULL);
627 :
628 0 : return state.dbsize;
629 : }
630 :
631 0 : static ssize_t dbwrap_unmarshall_get_data(const uint8_t *buf, size_t buflen,
632 : size_t ofs, TDB_DATA *pdata)
633 : {
634 : uint64_t space, len;
635 : const uint8_t *p;
636 :
637 0 : if (ofs == buflen) {
638 0 : return 0;
639 : }
640 0 : if (ofs > buflen) {
641 0 : return -1;
642 : }
643 :
644 0 : space = buflen - ofs;
645 0 : if (space < 8) {
646 0 : return -1;
647 : }
648 :
649 0 : p = buf + ofs;
650 0 : len = BVAL(p, 0);
651 :
652 0 : p += 8;
653 0 : space -= 8;
654 :
655 0 : if (len > space) {
656 0 : return -1;
657 : }
658 :
659 0 : *pdata = (TDB_DATA) { .dptr = discard_const_p(uint8_t, p),
660 : .dsize = len };
661 0 : return len + 8;
662 : }
663 :
664 0 : NTSTATUS dbwrap_parse_marshall_buf(const uint8_t *buf, size_t buflen,
665 : bool (*fn)(TDB_DATA key, TDB_DATA value,
666 : void *private_data),
667 : void *private_data)
668 : {
669 0 : size_t ofs = 0;
670 :
671 0 : while (true) {
672 : ssize_t len;
673 : TDB_DATA key, value;
674 : bool ok;
675 :
676 0 : len = dbwrap_unmarshall_get_data(buf, buflen, ofs, &key);
677 0 : if (len == 0) {
678 0 : break;
679 : }
680 0 : if (len == -1) {
681 0 : return NT_STATUS_INVALID_PARAMETER;
682 : }
683 0 : ofs += len;
684 :
685 0 : len = dbwrap_unmarshall_get_data(buf, buflen, ofs, &value);
686 0 : if (len == 0) {
687 0 : break;
688 : }
689 0 : if (len == -1) {
690 0 : return NT_STATUS_INVALID_PARAMETER;
691 : }
692 0 : ofs += len;
693 :
694 0 : ok = fn(key, value, private_data);
695 0 : if (!ok) {
696 0 : break;
697 : }
698 : }
699 :
700 0 : return NT_STATUS_OK;
701 : }
702 :
703 : struct dbwrap_unmarshall_state {
704 : struct db_context *db;
705 : NTSTATUS ret;
706 : };
707 :
708 0 : static bool dbwrap_unmarshall_fn(TDB_DATA key, TDB_DATA value,
709 : void *private_data)
710 : {
711 0 : struct dbwrap_unmarshall_state *state = private_data;
712 : NTSTATUS status;
713 :
714 0 : status = dbwrap_store(state->db, key, value, 0);
715 0 : if (!NT_STATUS_IS_OK(status)) {
716 0 : DBG_DEBUG("dbwrap_record_store failed: %s\n",
717 : nt_errstr(status));
718 0 : state->ret = status;
719 0 : return false;
720 : }
721 :
722 0 : return true;
723 : }
724 :
725 0 : NTSTATUS dbwrap_unmarshall(struct db_context *db, const uint8_t *buf,
726 : size_t buflen)
727 : {
728 0 : struct dbwrap_unmarshall_state state = { .db = db };
729 : NTSTATUS status;
730 :
731 0 : status = dbwrap_parse_marshall_buf(buf, buflen,
732 : dbwrap_unmarshall_fn, &state);
733 0 : if (!NT_STATUS_IS_OK(status)) {
734 0 : return status;
735 : }
736 0 : return state.ret;
737 : }
|