| 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 | static tdb_off_t tdb_dump_record(struct tdb_context *tdb, int hash,
 | 
|---|
| 31 |                                  tdb_off_t offset)
 | 
|---|
| 32 | {
 | 
|---|
| 33 |         struct tdb_record rec;
 | 
|---|
| 34 |         tdb_off_t tailer_ofs, tailer;
 | 
|---|
| 35 | 
 | 
|---|
| 36 |         if (tdb->methods->tdb_read(tdb, offset, (char *)&rec, 
 | 
|---|
| 37 |                                    sizeof(rec), DOCONV()) == -1) {
 | 
|---|
| 38 |                 printf("ERROR: failed to read record at %u\n", offset);
 | 
|---|
| 39 |                 return 0;
 | 
|---|
| 40 |         }
 | 
|---|
| 41 | 
 | 
|---|
| 42 |         printf(" rec: hash=%d offset=0x%08x next=0x%08x rec_len=%d "
 | 
|---|
| 43 |                "key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n",
 | 
|---|
| 44 |                hash, offset, rec.next, rec.rec_len, rec.key_len, rec.data_len,
 | 
|---|
| 45 |                rec.full_hash, rec.magic);
 | 
|---|
| 46 | 
 | 
|---|
| 47 |         tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off_t);
 | 
|---|
| 48 | 
 | 
|---|
| 49 |         if (tdb_ofs_read(tdb, tailer_ofs, &tailer) == -1) {
 | 
|---|
| 50 |                 printf("ERROR: failed to read tailer at %u\n", tailer_ofs);
 | 
|---|
| 51 |                 return rec.next;
 | 
|---|
| 52 |         }
 | 
|---|
| 53 | 
 | 
|---|
| 54 |         if (tailer != rec.rec_len + sizeof(rec)) {
 | 
|---|
| 55 |                 printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n",
 | 
|---|
| 56 |                                 (unsigned int)tailer, (unsigned int)(rec.rec_len + sizeof(rec)));
 | 
|---|
| 57 |         }
 | 
|---|
| 58 |         return rec.next;
 | 
|---|
| 59 | }
 | 
|---|
| 60 | 
 | 
|---|
| 61 | static int tdb_dump_chain(struct tdb_context *tdb, int i)
 | 
|---|
| 62 | {
 | 
|---|
| 63 |         tdb_off_t rec_ptr, top;
 | 
|---|
| 64 | 
 | 
|---|
| 65 |         top = TDB_HASH_TOP(i);
 | 
|---|
| 66 | 
 | 
|---|
| 67 |         if (tdb_lock(tdb, i, F_WRLCK) != 0)
 | 
|---|
| 68 |                 return -1;
 | 
|---|
| 69 | 
 | 
|---|
| 70 |         if (tdb_ofs_read(tdb, top, &rec_ptr) == -1)
 | 
|---|
| 71 |                 return tdb_unlock(tdb, i, F_WRLCK);
 | 
|---|
| 72 | 
 | 
|---|
| 73 |         if (rec_ptr)
 | 
|---|
| 74 |                 printf("hash=%d\n", i);
 | 
|---|
| 75 | 
 | 
|---|
| 76 |         while (rec_ptr) {
 | 
|---|
| 77 |                 rec_ptr = tdb_dump_record(tdb, i, rec_ptr);
 | 
|---|
| 78 |         }
 | 
|---|
| 79 | 
 | 
|---|
| 80 |         return tdb_unlock(tdb, i, F_WRLCK);
 | 
|---|
| 81 | }
 | 
|---|
| 82 | 
 | 
|---|
| 83 | void tdb_dump_all(struct tdb_context *tdb)
 | 
|---|
| 84 | {
 | 
|---|
| 85 |         int i;
 | 
|---|
| 86 |         for (i=0;i<tdb->header.hash_size;i++) {
 | 
|---|
| 87 |                 tdb_dump_chain(tdb, i);
 | 
|---|
| 88 |         }
 | 
|---|
| 89 |         printf("freelist:\n");
 | 
|---|
| 90 |         tdb_dump_chain(tdb, -1);
 | 
|---|
| 91 | }
 | 
|---|
| 92 | 
 | 
|---|
| 93 | int tdb_printfreelist(struct tdb_context *tdb)
 | 
|---|
| 94 | {
 | 
|---|
| 95 |         int ret;
 | 
|---|
| 96 |         long total_free = 0;
 | 
|---|
| 97 |         tdb_off_t offset, rec_ptr;
 | 
|---|
| 98 |         struct tdb_record rec;
 | 
|---|
| 99 | 
 | 
|---|
| 100 |         if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0)
 | 
|---|
| 101 |                 return ret;
 | 
|---|
| 102 | 
 | 
|---|
| 103 |         offset = FREELIST_TOP;
 | 
|---|
| 104 | 
 | 
|---|
| 105 |         /* read in the freelist top */
 | 
|---|
| 106 |         if (tdb_ofs_read(tdb, offset, &rec_ptr) == -1) {
 | 
|---|
| 107 |                 tdb_unlock(tdb, -1, F_WRLCK);
 | 
|---|
| 108 |                 return 0;
 | 
|---|
| 109 |         }
 | 
|---|
| 110 | 
 | 
|---|
| 111 |         printf("freelist top=[0x%08x]\n", rec_ptr );
 | 
|---|
| 112 |         while (rec_ptr) {
 | 
|---|
| 113 |                 if (tdb->methods->tdb_read(tdb, rec_ptr, (char *)&rec, 
 | 
|---|
| 114 |                                            sizeof(rec), DOCONV()) == -1) {
 | 
|---|
| 115 |                         tdb_unlock(tdb, -1, F_WRLCK);
 | 
|---|
| 116 |                         return -1;
 | 
|---|
| 117 |                 }
 | 
|---|
| 118 | 
 | 
|---|
| 119 |                 if (rec.magic != TDB_FREE_MAGIC) {
 | 
|---|
| 120 |                         printf("bad magic 0x%08x in free list\n", rec.magic);
 | 
|---|
| 121 |                         tdb_unlock(tdb, -1, F_WRLCK);
 | 
|---|
| 122 |                         return -1;
 | 
|---|
| 123 |                 }
 | 
|---|
| 124 | 
 | 
|---|
| 125 |                 printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)] (end = 0x%08x)\n", 
 | 
|---|
| 126 |                        rec_ptr, rec.rec_len, rec.rec_len, rec_ptr + rec.rec_len);
 | 
|---|
| 127 |                 total_free += rec.rec_len;
 | 
|---|
| 128 | 
 | 
|---|
| 129 |                 /* move to the next record */
 | 
|---|
| 130 |                 rec_ptr = rec.next;
 | 
|---|
| 131 |         }
 | 
|---|
| 132 |         printf("total rec_len = [0x%08x (%d)]\n", (int)total_free, 
 | 
|---|
| 133 |                (int)total_free);
 | 
|---|
| 134 | 
 | 
|---|
| 135 |         return tdb_unlock(tdb, -1, F_WRLCK);
 | 
|---|
| 136 | }
 | 
|---|
| 137 | 
 | 
|---|