Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : trivial database library
5 :
6 : Copyright (C) Jeremy Allison 2006
7 :
8 : ** NOTE! The following LGPL license applies to the tdb
9 : ** library. This does NOT imply that all of Samba is released
10 : ** under the LGPL
11 :
12 : This library is free software; you can redistribute it and/or
13 : modify it under the terms of the GNU Lesser General Public
14 : License as published by the Free Software Foundation; either
15 : version 3 of the License, or (at your option) any later version.
16 :
17 : This library is distributed in the hope that it will be useful,
18 : but WITHOUT ANY WARRANTY; without even the implied warranty of
19 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 : Lesser General Public License for more details.
21 :
22 : You should have received a copy of the GNU Lesser General Public
23 : License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 : */
25 :
26 : #include "tdb_private.h"
27 :
28 : /* Check the freelist is good and contains no loops.
29 : Very memory intensive - only do this as a consistency
30 : checker. Heh heh - uses an in memory tdb as the storage
31 : for the "seen" record list. For some reason this strikes
32 : me as extremely clever as I don't have to write another tree
33 : data structure implementation :-).
34 : */
35 :
36 24 : static int seen_insert(struct tdb_context *mem_tdb, tdb_off_t rec_ptr)
37 : {
38 : TDB_DATA key;
39 :
40 24 : key.dptr = (unsigned char *)&rec_ptr;
41 24 : key.dsize = sizeof(rec_ptr);
42 24 : return tdb_store(mem_tdb, key, tdb_null, TDB_INSERT);
43 : }
44 :
45 12 : _PUBLIC_ int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries)
46 : {
47 12 : struct tdb_context *mem_tdb = NULL;
48 : struct tdb_record rec;
49 : tdb_off_t rec_ptr, last_ptr;
50 12 : int ret = -1;
51 :
52 12 : *pnum_entries = 0;
53 :
54 12 : mem_tdb = tdb_open("flval", tdb->hash_size,
55 : TDB_INTERNAL, O_RDWR, 0600);
56 12 : if (!mem_tdb) {
57 0 : return -1;
58 : }
59 :
60 12 : if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
61 0 : tdb_close(mem_tdb);
62 0 : return 0;
63 : }
64 :
65 12 : last_ptr = FREELIST_TOP;
66 :
67 : /* Store the FREELIST_TOP record. */
68 12 : if (seen_insert(mem_tdb, last_ptr) == -1) {
69 0 : tdb->ecode = TDB_ERR_CORRUPT;
70 0 : ret = -1;
71 0 : goto fail;
72 : }
73 :
74 : /* read in the freelist top */
75 12 : if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) {
76 0 : goto fail;
77 : }
78 :
79 30 : while (rec_ptr) {
80 :
81 : /* If we can't store this record (we've seen it
82 : before) then the free list has a loop and must
83 : be corrupt. */
84 :
85 12 : if (seen_insert(mem_tdb, rec_ptr)) {
86 0 : tdb->ecode = TDB_ERR_CORRUPT;
87 0 : ret = -1;
88 0 : goto fail;
89 : }
90 :
91 12 : if (tdb_rec_free_read(tdb, rec_ptr, &rec) == -1) {
92 0 : goto fail;
93 : }
94 :
95 : /* move to the next record */
96 12 : rec_ptr = rec.next;
97 12 : *pnum_entries += 1;
98 : }
99 :
100 12 : ret = 0;
101 :
102 12 : fail:
103 :
104 12 : tdb_close(mem_tdb);
105 12 : tdb_unlock(tdb, -1, F_WRLCK);
106 12 : return ret;
107 : }
|