tdb: Allow _v variant in tdb_update_hash_cmp
[samba.git] / lib / tdb / common / tdb.c
1  /*
2    Unix SMB/CIFS implementation.
3
4    trivial database library
5
6    Copyright (C) Andrew Tridgell              1999-2005
7    Copyright (C) Paul `Rusty' Russell              2000
8    Copyright (C) Jeremy Allison                    2000-2003
9
10      ** NOTE! The following LGPL license applies to the tdb
11      ** library. This does NOT imply that all of Samba is released
12      ** under the LGPL
13
14    This library is free software; you can redistribute it and/or
15    modify it under the terms of the GNU Lesser General Public
16    License as published by the Free Software Foundation; either
17    version 3 of the License, or (at your option) any later version.
18
19    This library is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22    Lesser General Public License for more details.
23
24    You should have received a copy of the GNU Lesser General Public
25    License along with this library; if not, see <http://www.gnu.org/licenses/>.
26 */
27
28 #include "tdb_private.h"
29
30 _PUBLIC_ TDB_DATA tdb_null;
31
32 /*
33   non-blocking increment of the tdb sequence number if the tdb has been opened using
34   the TDB_SEQNUM flag
35 */
36 _PUBLIC_ void tdb_increment_seqnum_nonblock(struct tdb_context *tdb)
37 {
38         tdb_off_t seqnum=0;
39
40         if (!(tdb->flags & TDB_SEQNUM)) {
41                 return;
42         }
43
44         /* we ignore errors from this, as we have no sane way of
45            dealing with them.
46         */
47         tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
48         seqnum++;
49         tdb_ofs_write(tdb, TDB_SEQNUM_OFS, &seqnum);
50 }
51
52 /*
53   increment the tdb sequence number if the tdb has been opened using
54   the TDB_SEQNUM flag
55 */
56 static void tdb_increment_seqnum(struct tdb_context *tdb)
57 {
58         if (!(tdb->flags & TDB_SEQNUM)) {
59                 return;
60         }
61
62         if (tdb->transaction != NULL) {
63                 tdb_increment_seqnum_nonblock(tdb);
64                 return;
65         }
66
67         if (tdb_nest_lock(tdb, TDB_SEQNUM_OFS, F_WRLCK,
68                           TDB_LOCK_WAIT|TDB_LOCK_PROBE) != 0) {
69                 return;
70         }
71
72         tdb_increment_seqnum_nonblock(tdb);
73
74         tdb_nest_unlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, false);
75 }
76
77 static int tdb_key_compare(TDB_DATA key, TDB_DATA data, void *private_data)
78 {
79         return memcmp(data.dptr, key.dptr, data.dsize);
80 }
81
82 /* Returns 0 on fail.  On success, return offset of record, and fills
83    in rec */
84 static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, uint32_t hash,
85                         struct tdb_record *r)
86 {
87         tdb_off_t rec_ptr;
88
89         /* read in the hash top */
90         if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
91                 return 0;
92
93         /* keep looking until we find the right record */
94         while (rec_ptr) {
95                 if (tdb_rec_read(tdb, rec_ptr, r) == -1)
96                         return 0;
97
98                 if (!TDB_DEAD(r) && hash==r->full_hash
99                     && key.dsize==r->key_len
100                     && tdb_parse_data(tdb, key, rec_ptr + sizeof(*r),
101                                       r->key_len, tdb_key_compare,
102                                       NULL) == 0) {
103                         return rec_ptr;
104                 }
105                 /* detect tight infinite loop */
106                 if (rec_ptr == r->next) {
107                         tdb->ecode = TDB_ERR_CORRUPT;
108                         TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_find: loop detected.\n"));
109                         return 0;
110                 }
111                 rec_ptr = r->next;
112         }
113         tdb->ecode = TDB_ERR_NOEXIST;
114         return 0;
115 }
116
117 /* As tdb_find, but if you succeed, keep the lock */
118 tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, int locktype,
119                            struct tdb_record *rec)
120 {
121         uint32_t rec_ptr;
122
123         if (tdb_lock(tdb, BUCKET(hash), locktype) == -1)
124                 return 0;
125         if (!(rec_ptr = tdb_find(tdb, key, hash, rec)))
126                 tdb_unlock(tdb, BUCKET(hash), locktype);
127         return rec_ptr;
128 }
129
130 static TDB_DATA _tdb_fetch(struct tdb_context *tdb, TDB_DATA key);
131
132 struct tdb_update_hash_state {
133         const TDB_DATA *dbufs;
134         int num_dbufs;
135         tdb_len_t dbufs_len;
136 };
137
138 static int tdb_update_hash_cmp(TDB_DATA key, TDB_DATA data, void *private_data)
139 {
140         struct tdb_update_hash_state *state = private_data;
141         unsigned char *dptr = data.dptr;
142         int i;
143
144         if (state->dbufs_len != data.dsize) {
145                 return -1;
146         }
147
148         for (i=0; i<state->num_dbufs; i++) {
149                 TDB_DATA dbuf = state->dbufs[i];
150                 int ret;
151                 ret = memcmp(dptr, dbuf.dptr, dbuf.dsize);
152                 if (ret != 0) {
153                         return -1;
154                 }
155                 dptr += dbuf.dsize;
156         }
157
158         return 0;
159 }
160
161 /* update an entry in place - this only works if the new data size
162    is <= the old data size and the key exists.
163    on failure return -1.
164 */
165 static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, TDB_DATA dbuf)
166 {
167         struct tdb_record rec;
168         tdb_off_t rec_ptr;
169
170         /* find entry */
171         if (!(rec_ptr = tdb_find(tdb, key, hash, &rec)))
172                 return -1;
173
174         /* it could be an exact duplicate of what is there - this is
175          * surprisingly common (eg. with a ldb re-index). */
176         if (rec.data_len == dbuf.dsize) {
177                 struct tdb_update_hash_state state = {
178                         .dbufs = &dbuf, .num_dbufs = 1,
179                         .dbufs_len = dbuf.dsize
180                 };
181                 int ret;
182
183                 ret = tdb_parse_record(tdb, key, tdb_update_hash_cmp, &state);
184                 if (ret == 0) {
185                         return 0;
186                 }
187         }
188
189         /* must be long enough key, data and tailer */
190         if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off_t)) {
191                 tdb->ecode = TDB_SUCCESS; /* Not really an error */
192                 return -1;
193         }
194
195         if (tdb->methods->tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len,
196                       dbuf.dptr, dbuf.dsize) == -1)
197                 return -1;
198
199         if (dbuf.dsize != rec.data_len) {
200                 /* update size */
201                 rec.data_len = dbuf.dsize;
202                 return tdb_rec_write(tdb, rec_ptr, &rec);
203         }
204
205         return 0;
206 }
207
208 /* find an entry in the database given a key */
209 /* If an entry doesn't exist tdb_err will be set to
210  * TDB_ERR_NOEXIST. If a key has no data attached
211  * then the TDB_DATA will have zero length but
212  * a non-zero pointer
213  */
214 static TDB_DATA _tdb_fetch(struct tdb_context *tdb, TDB_DATA key)
215 {
216         tdb_off_t rec_ptr;
217         struct tdb_record rec;
218         TDB_DATA ret;
219         uint32_t hash;
220
221         /* find which hash bucket it is in */
222         hash = tdb->hash_fn(&key);
223         if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec)))
224                 return tdb_null;
225
226         ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len,
227                                   rec.data_len);
228         ret.dsize = rec.data_len;
229         tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
230         return ret;
231 }
232
233 _PUBLIC_ TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key)
234 {
235         TDB_DATA ret = _tdb_fetch(tdb, key);
236
237         tdb_trace_1rec_retrec(tdb, "tdb_fetch", key, ret);
238         return ret;
239 }
240
241 /*
242  * Find an entry in the database and hand the record's data to a parsing
243  * function. The parsing function is executed under the chain read lock, so it
244  * should be fast and should not block on other syscalls.
245  *
246  * DON'T CALL OTHER TDB CALLS FROM THE PARSER, THIS MIGHT LEAD TO SEGFAULTS.
247  *
248  * For mmapped tdb's that do not have a transaction open it points the parsing
249  * function directly at the mmap area, it avoids the malloc/memcpy in this
250  * case. If a transaction is open or no mmap is available, it has to do
251  * malloc/read/parse/free.
252  *
253  * This is interesting for all readers of potentially large data structures in
254  * the tdb records, ldb indexes being one example.
255  *
256  * Return -1 if the record was not found.
257  */
258
259 _PUBLIC_ int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key,
260                      int (*parser)(TDB_DATA key, TDB_DATA data,
261                                    void *private_data),
262                      void *private_data)
263 {
264         tdb_off_t rec_ptr;
265         struct tdb_record rec;
266         int ret;
267         uint32_t hash;
268
269         /* find which hash bucket it is in */
270         hash = tdb->hash_fn(&key);
271
272         if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) {
273                 /* record not found */
274                 tdb_trace_1rec_ret(tdb, "tdb_parse_record", key, -1);
275                 tdb->ecode = TDB_ERR_NOEXIST;
276                 return -1;
277         }
278         tdb_trace_1rec_ret(tdb, "tdb_parse_record", key, 0);
279
280         ret = tdb_parse_data(tdb, key, rec_ptr + sizeof(rec) + rec.key_len,
281                              rec.data_len, parser, private_data);
282
283         tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
284
285         return ret;
286 }
287
288 /* check if an entry in the database exists
289
290    note that 1 is returned if the key is found and 0 is returned if not found
291    this doesn't match the conventions in the rest of this module, but is
292    compatible with gdbm
293 */
294 static int tdb_exists_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash)
295 {
296         struct tdb_record rec;
297
298         if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0)
299                 return 0;
300         tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
301         return 1;
302 }
303
304 _PUBLIC_ int tdb_exists(struct tdb_context *tdb, TDB_DATA key)
305 {
306         uint32_t hash = tdb->hash_fn(&key);
307         int ret;
308
309         ret = tdb_exists_hash(tdb, key, hash);
310         tdb_trace_1rec_ret(tdb, "tdb_exists", key, ret);
311         return ret;
312 }
313
314 /* actually delete an entry in the database given the offset */
315 int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct tdb_record *rec)
316 {
317         tdb_off_t last_ptr, i;
318         struct tdb_record lastrec;
319
320         if (tdb->read_only || tdb->traverse_read) return -1;
321
322         if (((tdb->traverse_write != 0) && (!TDB_DEAD(rec))) ||
323             tdb_write_lock_record(tdb, rec_ptr) == -1) {
324                 /* Someone traversing here: mark it as dead */
325                 rec->magic = TDB_DEAD_MAGIC;
326                 return tdb_rec_write(tdb, rec_ptr, rec);
327         }
328         if (tdb_write_unlock_record(tdb, rec_ptr) != 0)
329                 return -1;
330
331         /* find previous record in hash chain */
332         if (tdb_ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1)
333                 return -1;
334         for (last_ptr = 0; i != rec_ptr; last_ptr = i, i = lastrec.next)
335                 if (tdb_rec_read(tdb, i, &lastrec) == -1)
336                         return -1;
337
338         /* unlink it: next ptr is at start of record. */
339         if (last_ptr == 0)
340                 last_ptr = TDB_HASH_TOP(rec->full_hash);
341         if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1)
342                 return -1;
343
344         /* recover the space */
345         if (tdb_free(tdb, rec_ptr, rec) == -1)
346                 return -1;
347         return 0;
348 }
349
350 static int tdb_count_dead(struct tdb_context *tdb, uint32_t hash)
351 {
352         int res = 0;
353         tdb_off_t rec_ptr;
354         struct tdb_record rec;
355
356         /* read in the hash top */
357         if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
358                 return 0;
359
360         while (rec_ptr) {
361                 if (tdb_rec_read(tdb, rec_ptr, &rec) == -1)
362                         return 0;
363
364                 if (rec.magic == TDB_DEAD_MAGIC) {
365                         res += 1;
366                 }
367                 rec_ptr = rec.next;
368         }
369         return res;
370 }
371
372 /*
373  * Purge all DEAD records from a hash chain
374  */
375 int tdb_purge_dead(struct tdb_context *tdb, uint32_t hash)
376 {
377         int res = -1;
378         struct tdb_record rec;
379         tdb_off_t rec_ptr;
380
381         if (tdb_lock_nonblock(tdb, -1, F_WRLCK) == -1) {
382                 /*
383                  * Don't block the freelist if not strictly necessary
384                  */
385                 return -1;
386         }
387
388         /* read in the hash top */
389         if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
390                 goto fail;
391
392         while (rec_ptr) {
393                 tdb_off_t next;
394
395                 if (tdb_rec_read(tdb, rec_ptr, &rec) == -1) {
396                         goto fail;
397                 }
398
399                 next = rec.next;
400
401                 if (rec.magic == TDB_DEAD_MAGIC
402                     && tdb_do_delete(tdb, rec_ptr, &rec) == -1) {
403                         goto fail;
404                 }
405                 rec_ptr = next;
406         }
407         res = 0;
408  fail:
409         tdb_unlock(tdb, -1, F_WRLCK);
410         return res;
411 }
412
413 /* delete an entry in the database given a key */
414 static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash)
415 {
416         tdb_off_t rec_ptr;
417         struct tdb_record rec;
418         int ret;
419
420         rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, &rec);
421         if (rec_ptr == 0) {
422                 return -1;
423         }
424
425         if (tdb->max_dead_records != 0) {
426
427                 uint32_t magic = TDB_DEAD_MAGIC;
428
429                 /*
430                  * Allow for some dead records per hash chain, mainly for
431                  * tdb's with a very high create/delete rate like locking.tdb.
432                  */
433
434                 if (tdb_count_dead(tdb, hash) >= tdb->max_dead_records) {
435                         /*
436                          * Don't let the per-chain freelist grow too large,
437                          * delete all existing dead records
438                          */
439                         tdb_purge_dead(tdb, hash);
440                 }
441
442                 /*
443                  * Just mark the record as dead.
444                  */
445                 ret = tdb_ofs_write(
446                         tdb, rec_ptr + offsetof(struct tdb_record, magic),
447                         &magic);
448         }
449         else {
450                 ret = tdb_do_delete(tdb, rec_ptr, &rec);
451         }
452
453         if (ret == 0) {
454                 tdb_increment_seqnum(tdb);
455         }
456
457         if (tdb_unlock(tdb, BUCKET(hash), F_WRLCK) != 0)
458                 TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_delete: WARNING tdb_unlock failed!\n"));
459         return ret;
460 }
461
462 _PUBLIC_ int tdb_delete(struct tdb_context *tdb, TDB_DATA key)
463 {
464         uint32_t hash = tdb->hash_fn(&key);
465         int ret;
466
467         ret = tdb_delete_hash(tdb, key, hash);
468         tdb_trace_1rec_ret(tdb, "tdb_delete", key, ret);
469         return ret;
470 }
471
472 /*
473  * See if we have a dead record around with enough space
474  */
475 tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash,
476                         struct tdb_record *r, tdb_len_t length,
477                         tdb_off_t *p_last_ptr)
478 {
479         tdb_off_t rec_ptr, last_ptr;
480         tdb_off_t best_rec_ptr = 0;
481         tdb_off_t best_last_ptr = 0;
482         struct tdb_record best = { .rec_len = UINT32_MAX };
483
484         length += sizeof(tdb_off_t); /* tailer */
485
486         last_ptr = TDB_HASH_TOP(hash);
487
488         /* read in the hash top */
489         if (tdb_ofs_read(tdb, last_ptr, &rec_ptr) == -1)
490                 return 0;
491
492         /* keep looking until we find the right record */
493         while (rec_ptr) {
494                 if (tdb_rec_read(tdb, rec_ptr, r) == -1)
495                         return 0;
496
497                 if (TDB_DEAD(r) && (r->rec_len >= length) &&
498                     (r->rec_len < best.rec_len)) {
499                         best_rec_ptr = rec_ptr;
500                         best_last_ptr = last_ptr;
501                         best = *r;
502                 }
503                 last_ptr = rec_ptr;
504                 rec_ptr = r->next;
505         }
506
507         if (best.rec_len == UINT32_MAX) {
508                 return 0;
509         }
510
511         *r = best;
512         *p_last_ptr = best_last_ptr;
513         return best_rec_ptr;
514 }
515
516 static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
517                        TDB_DATA dbuf, int flag, uint32_t hash)
518 {
519         struct tdb_record rec;
520         tdb_off_t rec_ptr;
521         tdb_len_t rec_len;
522         int ret = -1;
523
524         rec_len = key.dsize + dbuf.dsize;
525         if ((rec_len < key.dsize) || (rec_len < dbuf.dsize)) {
526                 tdb->ecode = TDB_ERR_OOM;
527                 goto fail;
528         }
529
530         /* check for it existing, on insert. */
531         if (flag == TDB_INSERT) {
532                 if (tdb_exists_hash(tdb, key, hash)) {
533                         tdb->ecode = TDB_ERR_EXISTS;
534                         goto fail;
535                 }
536         } else {
537                 /* first try in-place update, on modify or replace. */
538                 if (tdb_update_hash(tdb, key, hash, dbuf) == 0) {
539                         goto done;
540                 }
541                 if (tdb->ecode == TDB_ERR_NOEXIST &&
542                     flag == TDB_MODIFY) {
543                         /* if the record doesn't exist and we are in TDB_MODIFY mode then
544                          we should fail the store */
545                         goto fail;
546                 }
547         }
548         /* reset the error code potentially set by the tdb_update_hash() */
549         tdb->ecode = TDB_SUCCESS;
550
551         /* delete any existing record - if it doesn't exist we don't
552            care.  Doing this first reduces fragmentation, and avoids
553            coalescing with `allocated' block before it's updated. */
554         if (flag != TDB_INSERT)
555                 tdb_delete_hash(tdb, key, hash);
556
557         /* we have to allocate some space */
558         rec_ptr = tdb_allocate(tdb, hash, rec_len, &rec);
559
560         if (rec_ptr == 0) {
561                 goto fail;
562         }
563
564         /* Read hash top into next ptr */
565         if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1)
566                 goto fail;
567
568         rec.key_len = key.dsize;
569         rec.data_len = dbuf.dsize;
570         rec.full_hash = hash;
571         rec.magic = TDB_MAGIC;
572
573         /* write out and point the top of the hash chain at it */
574         if (tdb_rec_write(tdb, rec_ptr, &rec) == -1
575             || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec),
576                                        key.dptr, key.dsize) == -1
577             || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec)+key.dsize,
578                                        dbuf.dptr, dbuf.dsize) == -1
579             || tdb_ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) {
580                 /* Need to tdb_unallocate() here */
581                 goto fail;
582         }
583
584  done:
585         ret = 0;
586  fail:
587         if (ret == 0) {
588                 tdb_increment_seqnum(tdb);
589         }
590         return ret;
591 }
592
593 /* store an element in the database, replacing any existing element
594    with the same key
595
596    return 0 on success, -1 on failure
597 */
598 _PUBLIC_ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
599 {
600         uint32_t hash;
601         int ret;
602
603         if (tdb->read_only || tdb->traverse_read) {
604                 tdb->ecode = TDB_ERR_RDONLY;
605                 tdb_trace_2rec_flag_ret(tdb, "tdb_store", key, dbuf, flag, -1);
606                 return -1;
607         }
608
609         /* find which hash bucket it is in */
610         hash = tdb->hash_fn(&key);
611         if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
612                 return -1;
613
614         ret = _tdb_store(tdb, key, dbuf, flag, hash);
615         tdb_trace_2rec_flag_ret(tdb, "tdb_store", key, dbuf, flag, ret);
616         tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
617         return ret;
618 }
619
620 /* Append to an entry. Create if not exist. */
621 _PUBLIC_ int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
622 {
623         uint32_t hash;
624         TDB_DATA dbuf;
625         int ret = -1;
626
627         /* find which hash bucket it is in */
628         hash = tdb->hash_fn(&key);
629         if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
630                 return -1;
631
632         dbuf = _tdb_fetch(tdb, key);
633
634         if (dbuf.dptr == NULL) {
635                 dbuf.dptr = (unsigned char *)malloc(new_dbuf.dsize);
636         } else {
637                 unsigned int new_len = dbuf.dsize + new_dbuf.dsize;
638                 unsigned char *new_dptr;
639
640                 /* realloc '0' is special: don't do that. */
641                 if (new_len == 0)
642                         new_len = 1;
643                 new_dptr = (unsigned char *)realloc(dbuf.dptr, new_len);
644                 if (new_dptr == NULL) {
645                         free(dbuf.dptr);
646                 }
647                 dbuf.dptr = new_dptr;
648         }
649
650         if (dbuf.dptr == NULL) {
651                 tdb->ecode = TDB_ERR_OOM;
652                 goto failed;
653         }
654
655         memcpy(dbuf.dptr + dbuf.dsize, new_dbuf.dptr, new_dbuf.dsize);
656         dbuf.dsize += new_dbuf.dsize;
657
658         ret = _tdb_store(tdb, key, dbuf, 0, hash);
659         tdb_trace_2rec_retrec(tdb, "tdb_append", key, new_dbuf, dbuf);
660
661 failed:
662         tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
663         SAFE_FREE(dbuf.dptr);
664         return ret;
665 }
666
667
668 /*
669   return the name of the current tdb file
670   useful for external logging functions
671 */
672 _PUBLIC_ const char *tdb_name(struct tdb_context *tdb)
673 {
674         return tdb->name;
675 }
676
677 /*
678   return the underlying file descriptor being used by tdb, or -1
679   useful for external routines that want to check the device/inode
680   of the fd
681 */
682 _PUBLIC_ int tdb_fd(struct tdb_context *tdb)
683 {
684         return tdb->fd;
685 }
686
687 /*
688   return the current logging function
689   useful for external tdb routines that wish to log tdb errors
690 */
691 _PUBLIC_ tdb_log_func tdb_log_fn(struct tdb_context *tdb)
692 {
693         return tdb->log.log_fn;
694 }
695
696
697 /*
698   get the tdb sequence number. Only makes sense if the writers opened
699   with TDB_SEQNUM set. Note that this sequence number will wrap quite
700   quickly, so it should only be used for a 'has something changed'
701   test, not for code that relies on the count of the number of changes
702   made. If you want a counter then use a tdb record.
703
704   The aim of this sequence number is to allow for a very lightweight
705   test of a possible tdb change.
706 */
707 _PUBLIC_ int tdb_get_seqnum(struct tdb_context *tdb)
708 {
709         tdb_off_t seqnum=0;
710
711         tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
712         return seqnum;
713 }
714
715 _PUBLIC_ int tdb_hash_size(struct tdb_context *tdb)
716 {
717         return tdb->hash_size;
718 }
719
720 _PUBLIC_ size_t tdb_map_size(struct tdb_context *tdb)
721 {
722         return tdb->map_size;
723 }
724
725 _PUBLIC_ int tdb_get_flags(struct tdb_context *tdb)
726 {
727         return tdb->flags;
728 }
729
730 _PUBLIC_ void tdb_add_flags(struct tdb_context *tdb, unsigned flags)
731 {
732         if ((flags & TDB_ALLOW_NESTING) &&
733             (flags & TDB_DISALLOW_NESTING)) {
734                 tdb->ecode = TDB_ERR_NESTING;
735                 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_add_flags: "
736                         "allow_nesting and disallow_nesting are not allowed together!"));
737                 return;
738         }
739
740         if (flags & TDB_ALLOW_NESTING) {
741                 tdb->flags &= ~TDB_DISALLOW_NESTING;
742         }
743         if (flags & TDB_DISALLOW_NESTING) {
744                 tdb->flags &= ~TDB_ALLOW_NESTING;
745         }
746
747         tdb->flags |= flags;
748 }
749
750 _PUBLIC_ void tdb_remove_flags(struct tdb_context *tdb, unsigned flags)
751 {
752         if ((flags & TDB_ALLOW_NESTING) &&
753             (flags & TDB_DISALLOW_NESTING)) {
754                 tdb->ecode = TDB_ERR_NESTING;
755                 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_remove_flags: "
756                         "allow_nesting and disallow_nesting are not allowed together!"));
757                 return;
758         }
759
760         if ((flags & TDB_NOLOCK) &&
761             (tdb->feature_flags & TDB_FEATURE_FLAG_MUTEX) &&
762             (tdb->mutexes == NULL)) {
763                 tdb->ecode = TDB_ERR_LOCK;
764                 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_remove_flags: "
765                          "Can not remove NOLOCK flag on mutexed databases"));
766                 return;
767         }
768
769         if (flags & TDB_ALLOW_NESTING) {
770                 tdb->flags |= TDB_DISALLOW_NESTING;
771         }
772         if (flags & TDB_DISALLOW_NESTING) {
773                 tdb->flags |= TDB_ALLOW_NESTING;
774         }
775
776         tdb->flags &= ~flags;
777 }
778
779
780 /*
781   enable sequence number handling on an open tdb
782 */
783 _PUBLIC_ void tdb_enable_seqnum(struct tdb_context *tdb)
784 {
785         tdb->flags |= TDB_SEQNUM;
786 }
787
788
789 /*
790   add a region of the file to the freelist. Length is the size of the region in bytes,
791   which includes the free list header that needs to be added
792  */
793 static int tdb_free_region(struct tdb_context *tdb, tdb_off_t offset, ssize_t length)
794 {
795         struct tdb_record rec;
796         if (length <= sizeof(rec)) {
797                 /* the region is not worth adding */
798                 return 0;
799         }
800         if (length + offset > tdb->map_size) {
801                 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_free_region: adding region beyond end of file\n"));
802                 return -1;
803         }
804         memset(&rec,'\0',sizeof(rec));
805         rec.rec_len = length - sizeof(rec);
806         if (tdb_free(tdb, offset, &rec) == -1) {
807                 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_free_region: failed to add free record\n"));
808                 return -1;
809         }
810         return 0;
811 }
812
813 /*
814   wipe the entire database, deleting all records. This can be done
815   very fast by using a allrecord lock. The entire data portion of the
816   file becomes a single entry in the freelist.
817
818   This code carefully steps around the recovery area, leaving it alone
819  */
820 _PUBLIC_ int tdb_wipe_all(struct tdb_context *tdb)
821 {
822         uint32_t i;
823         tdb_off_t offset = 0;
824         ssize_t data_len;
825         tdb_off_t recovery_head;
826         tdb_len_t recovery_size = 0;
827
828         if (tdb_lockall(tdb) != 0) {
829                 return -1;
830         }
831
832         tdb_trace(tdb, "tdb_wipe_all");
833
834         /* see if the tdb has a recovery area, and remember its size
835            if so. We don't want to lose this as otherwise each
836            tdb_wipe_all() in a transaction will increase the size of
837            the tdb by the size of the recovery area */
838         if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) {
839                 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_wipe_all: failed to read recovery head\n"));
840                 goto failed;
841         }
842
843         if (recovery_head != 0) {
844                 struct tdb_record rec;
845                 if (tdb->methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) {
846                         TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_wipe_all: failed to read recovery record\n"));
847                         return -1;
848                 }
849                 recovery_size = rec.rec_len + sizeof(rec);
850         }
851
852         /* wipe the hashes */
853         for (i=0;i<tdb->hash_size;i++) {
854                 if (tdb_ofs_write(tdb, TDB_HASH_TOP(i), &offset) == -1) {
855                         TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_wipe_all: failed to write hash %d\n", i));
856                         goto failed;
857                 }
858         }
859
860         /* wipe the freelist */
861         if (tdb_ofs_write(tdb, FREELIST_TOP, &offset) == -1) {
862                 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_wipe_all: failed to write freelist\n"));
863                 goto failed;
864         }
865
866         /* add all the rest of the file to the freelist, possibly leaving a gap
867            for the recovery area */
868         if (recovery_size == 0) {
869                 /* the simple case - the whole file can be used as a freelist */
870                 data_len = (tdb->map_size - TDB_DATA_START(tdb->hash_size));
871                 if (tdb_free_region(tdb, TDB_DATA_START(tdb->hash_size), data_len) != 0) {
872                         goto failed;
873                 }
874         } else {
875                 /* we need to add two freelist entries - one on either
876                    side of the recovery area
877
878                    Note that we cannot shift the recovery area during
879                    this operation. Only the transaction.c code may
880                    move the recovery area or we risk subtle data
881                    corruption
882                 */
883                 data_len = (recovery_head - TDB_DATA_START(tdb->hash_size));
884                 if (tdb_free_region(tdb, TDB_DATA_START(tdb->hash_size), data_len) != 0) {
885                         goto failed;
886                 }
887                 /* and the 2nd free list entry after the recovery area - if any */
888                 data_len = tdb->map_size - (recovery_head+recovery_size);
889                 if (tdb_free_region(tdb, recovery_head+recovery_size, data_len) != 0) {
890                         goto failed;
891                 }
892         }
893
894         tdb_increment_seqnum_nonblock(tdb);
895
896         if (tdb_unlockall(tdb) != 0) {
897                 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_wipe_all: failed to unlock\n"));
898                 goto failed;
899         }
900
901         return 0;
902
903 failed:
904         tdb_unlockall(tdb);
905         return -1;
906 }
907
908 struct traverse_state {
909         bool error;
910         struct tdb_context *dest_db;
911 };
912
913 /*
914   traverse function for repacking
915  */
916 static int repack_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private_data)
917 {
918         struct traverse_state *state = (struct traverse_state *)private_data;
919         if (tdb_store(state->dest_db, key, data, TDB_INSERT) != 0) {
920                 state->error = true;
921                 return -1;
922         }
923         return 0;
924 }
925
926 /*
927   repack a tdb
928  */
929 _PUBLIC_ int tdb_repack(struct tdb_context *tdb)
930 {
931         struct tdb_context *tmp_db;
932         struct traverse_state state;
933
934         tdb_trace(tdb, "tdb_repack");
935
936         if (tdb_transaction_start(tdb) != 0) {
937                 TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to start transaction\n"));
938                 return -1;
939         }
940
941         tmp_db = tdb_open("tmpdb", tdb_hash_size(tdb), TDB_INTERNAL, O_RDWR|O_CREAT, 0);
942         if (tmp_db == NULL) {
943                 TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to create tmp_db\n"));
944                 tdb_transaction_cancel(tdb);
945                 return -1;
946         }
947
948         state.error = false;
949         state.dest_db = tmp_db;
950
951         if (tdb_traverse_read(tdb, repack_traverse, &state) == -1) {
952                 TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to traverse copying out\n"));
953                 tdb_transaction_cancel(tdb);
954                 tdb_close(tmp_db);
955                 return -1;
956         }
957
958         if (state.error) {
959                 TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Error during traversal\n"));
960                 tdb_transaction_cancel(tdb);
961                 tdb_close(tmp_db);
962                 return -1;
963         }
964
965         if (tdb_wipe_all(tdb) != 0) {
966                 TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to wipe database\n"));
967                 tdb_transaction_cancel(tdb);
968                 tdb_close(tmp_db);
969                 return -1;
970         }
971
972         state.error = false;
973         state.dest_db = tdb;
974
975         if (tdb_traverse_read(tmp_db, repack_traverse, &state) == -1) {
976                 TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to traverse copying back\n"));
977                 tdb_transaction_cancel(tdb);
978                 tdb_close(tmp_db);
979                 return -1;
980         }
981
982         if (state.error) {
983                 TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Error during second traversal\n"));
984                 tdb_transaction_cancel(tdb);
985                 tdb_close(tmp_db);
986                 return -1;
987         }
988
989         tdb_close(tmp_db);
990
991         if (tdb_transaction_commit(tdb) != 0) {
992                 TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to commit\n"));
993                 return -1;
994         }
995
996         return 0;
997 }
998
999 /* Even on files, we can get partial writes due to signals. */
1000 bool tdb_write_all(int fd, const void *buf, size_t count)
1001 {
1002         while (count) {
1003                 ssize_t ret;
1004                 ret = write(fd, buf, count);
1005                 if (ret < 0)
1006                         return false;
1007                 buf = (const char *)buf + ret;
1008                 count -= ret;
1009         }
1010         return true;
1011 }
1012
1013 bool tdb_add_off_t(tdb_off_t a, tdb_off_t b, tdb_off_t *pret)
1014 {
1015         tdb_off_t ret = a + b;
1016
1017         if ((ret < a) || (ret < b)) {
1018                 return false;
1019         }
1020         *pret = ret;
1021         return true;
1022 }
1023
1024 #ifdef TDB_TRACE
1025 static void tdb_trace_write(struct tdb_context *tdb, const char *str)
1026 {
1027         if (!tdb_write_all(tdb->tracefd, str, strlen(str))) {
1028                 close(tdb->tracefd);
1029                 tdb->tracefd = -1;
1030         }
1031 }
1032
1033 static void tdb_trace_start(struct tdb_context *tdb)
1034 {
1035         tdb_off_t seqnum=0;
1036         char msg[sizeof(tdb_off_t) * 4 + 1];
1037
1038         tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
1039         snprintf(msg, sizeof(msg), "%u ", seqnum);
1040         tdb_trace_write(tdb, msg);
1041 }
1042
1043 static void tdb_trace_end(struct tdb_context *tdb)
1044 {
1045         tdb_trace_write(tdb, "\n");
1046 }
1047
1048 static void tdb_trace_end_ret(struct tdb_context *tdb, int ret)
1049 {
1050         char msg[sizeof(ret) * 4 + 4];
1051         snprintf(msg, sizeof(msg), " = %i\n", ret);
1052         tdb_trace_write(tdb, msg);
1053 }
1054
1055 static void tdb_trace_record(struct tdb_context *tdb, TDB_DATA rec)
1056 {
1057         char msg[20 + rec.dsize*2], *p;
1058         unsigned int i;
1059
1060         /* We differentiate zero-length records from non-existent ones. */
1061         if (rec.dptr == NULL) {
1062                 tdb_trace_write(tdb, " NULL");
1063                 return;
1064         }
1065
1066         /* snprintf here is purely cargo-cult programming. */
1067         p = msg;
1068         p += snprintf(p, sizeof(msg), " %zu:", rec.dsize);
1069         for (i = 0; i < rec.dsize; i++)
1070                 p += snprintf(p, 2, "%02x", rec.dptr[i]);
1071
1072         tdb_trace_write(tdb, msg);
1073 }
1074
1075 void tdb_trace(struct tdb_context *tdb, const char *op)
1076 {
1077         tdb_trace_start(tdb);
1078         tdb_trace_write(tdb, op);
1079         tdb_trace_end(tdb);
1080 }
1081
1082 void tdb_trace_seqnum(struct tdb_context *tdb, uint32_t seqnum, const char *op)
1083 {
1084         char msg[sizeof(tdb_off_t) * 4 + 1];
1085
1086         snprintf(msg, sizeof(msg), "%u ", seqnum);
1087         tdb_trace_write(tdb, msg);
1088         tdb_trace_write(tdb, op);
1089         tdb_trace_end(tdb);
1090 }
1091
1092 void tdb_trace_open(struct tdb_context *tdb, const char *op,
1093                     unsigned hash_size, unsigned tdb_flags, unsigned open_flags)
1094 {
1095         char msg[128];
1096
1097         snprintf(msg, sizeof(msg),
1098                  "%s %u 0x%x 0x%x", op, hash_size, tdb_flags, open_flags);
1099         tdb_trace_start(tdb);
1100         tdb_trace_write(tdb, msg);
1101         tdb_trace_end(tdb);
1102 }
1103
1104 void tdb_trace_ret(struct tdb_context *tdb, const char *op, int ret)
1105 {
1106         tdb_trace_start(tdb);
1107         tdb_trace_write(tdb, op);
1108         tdb_trace_end_ret(tdb, ret);
1109 }
1110
1111 void tdb_trace_retrec(struct tdb_context *tdb, const char *op, TDB_DATA ret)
1112 {
1113         tdb_trace_start(tdb);
1114         tdb_trace_write(tdb, op);
1115         tdb_trace_write(tdb, " =");
1116         tdb_trace_record(tdb, ret);
1117         tdb_trace_end(tdb);
1118 }
1119
1120 void tdb_trace_1rec(struct tdb_context *tdb, const char *op,
1121                     TDB_DATA rec)
1122 {
1123         tdb_trace_start(tdb);
1124         tdb_trace_write(tdb, op);
1125         tdb_trace_record(tdb, rec);
1126         tdb_trace_end(tdb);
1127 }
1128
1129 void tdb_trace_1rec_ret(struct tdb_context *tdb, const char *op,
1130                         TDB_DATA rec, int ret)
1131 {
1132         tdb_trace_start(tdb);
1133         tdb_trace_write(tdb, op);
1134         tdb_trace_record(tdb, rec);
1135         tdb_trace_end_ret(tdb, ret);
1136 }
1137
1138 void tdb_trace_1rec_retrec(struct tdb_context *tdb, const char *op,
1139                            TDB_DATA rec, TDB_DATA ret)
1140 {
1141         tdb_trace_start(tdb);
1142         tdb_trace_write(tdb, op);
1143         tdb_trace_record(tdb, rec);
1144         tdb_trace_write(tdb, " =");
1145         tdb_trace_record(tdb, ret);
1146         tdb_trace_end(tdb);
1147 }
1148
1149 void tdb_trace_2rec_flag_ret(struct tdb_context *tdb, const char *op,
1150                              TDB_DATA rec1, TDB_DATA rec2, unsigned flag,
1151                              int ret)
1152 {
1153         char msg[1 + sizeof(ret) * 4];
1154
1155         snprintf(msg, sizeof(msg), " %#x", flag);
1156         tdb_trace_start(tdb);
1157         tdb_trace_write(tdb, op);
1158         tdb_trace_record(tdb, rec1);
1159         tdb_trace_record(tdb, rec2);
1160         tdb_trace_write(tdb, msg);
1161         tdb_trace_end_ret(tdb, ret);
1162 }
1163
1164 void tdb_trace_2rec_retrec(struct tdb_context *tdb, const char *op,
1165                            TDB_DATA rec1, TDB_DATA rec2, TDB_DATA ret)
1166 {
1167         tdb_trace_start(tdb);
1168         tdb_trace_write(tdb, op);
1169         tdb_trace_record(tdb, rec1);
1170         tdb_trace_record(tdb, rec2);
1171         tdb_trace_write(tdb, " =");
1172         tdb_trace_record(tdb, ret);
1173         tdb_trace_end(tdb);
1174 }
1175 #endif