Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : simple tdb dump util
4 : Copyright (C) Andrew Tridgell 2001
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 3 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, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include "replace.h"
21 : #include "system/locale.h"
22 : #include "system/time.h"
23 : #include "system/filesys.h"
24 : #include "system/wait.h"
25 : #include "tdb.h"
26 :
27 0 : static void print_data(TDB_DATA d)
28 : {
29 0 : unsigned char *p = (unsigned char *)d.dptr;
30 0 : int len = d.dsize;
31 0 : while (len--) {
32 0 : if (isprint(*p) && !strchr("\"\\", *p)) {
33 0 : fputc(*p, stdout);
34 : } else {
35 0 : printf("\\%02X", *p);
36 : }
37 0 : p++;
38 : }
39 0 : }
40 :
41 0 : static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
42 : {
43 0 : printf("{\n");
44 0 : printf("key(%zu) = \"", key.dsize);
45 0 : print_data(key);
46 0 : printf("\"\n");
47 0 : printf("data(%zu) = \"", dbuf.dsize);
48 0 : print_data(dbuf);
49 0 : printf("\"\n");
50 0 : printf("}\n");
51 0 : return 0;
52 : }
53 :
54 : static void log_stderr(struct tdb_context *tdb, enum tdb_debug_level level,
55 : const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
56 :
57 0 : static void log_stderr(struct tdb_context *tdb, enum tdb_debug_level level,
58 : const char *fmt, ...)
59 : {
60 : va_list ap;
61 0 : const char *name = tdb_name(tdb);
62 0 : const char *prefix = "";
63 :
64 0 : if (!name)
65 0 : name = "unnamed";
66 :
67 0 : switch (level) {
68 0 : case TDB_DEBUG_ERROR:
69 0 : prefix = "ERROR: ";
70 0 : break;
71 0 : case TDB_DEBUG_WARNING:
72 0 : prefix = "WARNING: ";
73 0 : break;
74 0 : case TDB_DEBUG_TRACE:
75 0 : return;
76 :
77 0 : default:
78 : case TDB_DEBUG_FATAL:
79 0 : prefix = "FATAL: ";
80 0 : break;
81 : }
82 :
83 0 : va_start(ap, fmt);
84 0 : fprintf(stderr, "tdb(%s): %s", name, prefix);
85 0 : vfprintf(stderr, fmt, ap);
86 0 : va_end(ap);
87 : }
88 :
89 0 : static void emergency_walk(TDB_DATA key, TDB_DATA dbuf, void *keyname)
90 : {
91 0 : if (keyname) {
92 0 : if (key.dsize != strlen(keyname))
93 0 : return;
94 0 : if (memcmp(key.dptr, keyname, key.dsize) != 0)
95 0 : return;
96 : }
97 0 : traverse_fn(NULL, key, dbuf, NULL);
98 : }
99 :
100 3 : static int dump_tdb(const char *fname, const char *keyname, bool emergency)
101 : {
102 : TDB_CONTEXT *tdb;
103 : TDB_DATA key, value;
104 3 : struct tdb_logging_context logfn = {
105 : .log_fn = log_stderr,
106 : };
107 3 : int tdb_flags = TDB_DEFAULT;
108 :
109 : /*
110 : * Note: that O_RDONLY implies TDB_NOLOCK, but we want to make it
111 : * explicit as it's important when working on databases which were
112 : * created with mutex locking.
113 : */
114 3 : tdb_flags |= TDB_NOLOCK;
115 :
116 3 : tdb = tdb_open_ex(fname, 0, tdb_flags, O_RDONLY, 0, &logfn, NULL);
117 3 : if (!tdb) {
118 0 : printf("Failed to open %s\n", fname);
119 0 : return 1;
120 : }
121 :
122 3 : if (emergency) {
123 0 : return tdb_rescue(tdb, emergency_walk, discard_const(keyname)) == 0;
124 : }
125 3 : if (!keyname) {
126 3 : return tdb_traverse(tdb, traverse_fn, NULL) == -1 ? 1 : 0;
127 : } else {
128 0 : key.dptr = discard_const_p(uint8_t, keyname);
129 0 : key.dsize = strlen(keyname);
130 0 : value = tdb_fetch(tdb, key);
131 0 : if (!value.dptr) {
132 0 : return 1;
133 : } else {
134 0 : print_data(value);
135 0 : free(value.dptr);
136 : }
137 : }
138 :
139 0 : return 0;
140 : }
141 :
142 0 : static void usage( void)
143 : {
144 0 : printf( "Usage: tdbdump [options] <filename>\n\n");
145 0 : printf( " -h this help message\n");
146 0 : printf( " -k keyname dumps value of keyname\n");
147 0 : printf( " -e emergency dump, for corrupt databases\n");
148 0 : }
149 :
150 3 : int main(int argc, char *argv[])
151 : {
152 3 : char *fname, *keyname=NULL;
153 3 : bool emergency = false;
154 : int c;
155 :
156 3 : if (argc < 2) {
157 0 : printf("Usage: tdbdump <fname>\n");
158 0 : exit(1);
159 : }
160 :
161 6 : while ((c = getopt( argc, argv, "hk:e")) != -1) {
162 0 : switch (c) {
163 0 : case 'h':
164 0 : usage();
165 0 : exit( 0);
166 0 : case 'k':
167 0 : keyname = optarg;
168 0 : break;
169 0 : case 'e':
170 0 : emergency = true;
171 0 : break;
172 0 : default:
173 0 : usage();
174 0 : exit( 1);
175 : }
176 : }
177 :
178 3 : fname = argv[optind];
179 :
180 3 : return dump_tdb(fname, keyname, emergency);
181 : }
|