source: branches/samba-3.0/source/tdb/tools/tdbtool.c

Last change on this file was 392, checked in by Silvan Scherrer, 16 years ago

fixed ticket 112 in 3.0

File size: 16.4 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 Samba database functions
4 Copyright (C) Andrew Tridgell 1999-2000
5 Copyright (C) Paul `Rusty' Russell 2000
6 Copyright (C) Jeremy Allison 2000
7 Copyright (C) Andrew Esh 2001
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/
23
24#include <errno.h>
25#include <stdlib.h>
26#include <stdio.h>
27#include <fcntl.h>
28#include <unistd.h>
29#include <string.h>
30#include <fcntl.h>
31#include <time.h>
32#include <sys/mman.h>
33#include <sys/stat.h>
34#include <sys/time.h>
35#include <ctype.h>
36#include <signal.h>
37#include "tdb.h"
38#include "pstring.h"
39
40static int do_command(void);
41char *cmdname, *arg1, *arg2;
42size_t arg1len, arg2len;
43int do_connections;
44int bIterate = 0;
45char *line;
46TDB_DATA iterate_kbuf;
47char cmdline[1024];
48
49#ifdef __OS2__
50static int createDbCmd;
51#endif
52
53enum commands {
54 CMD_CREATE_TDB,
55 CMD_OPEN_TDB,
56 CMD_ERASE,
57 CMD_DUMP,
58 CMD_CDUMP,
59 CMD_INSERT,
60 CMD_MOVE,
61 CMD_STORE,
62 CMD_SHOW,
63 CMD_KEYS,
64 CMD_HEXKEYS,
65 CMD_DELETE,
66 CMD_LIST_HASH_FREE,
67 CMD_LIST_FREE,
68 CMD_INFO,
69 CMD_FIRST,
70 CMD_NEXT,
71 CMD_SYSTEM,
72 CMD_QUIT,
73 CMD_HELP
74};
75
76typedef struct {
77 const char *name;
78 enum commands cmd;
79} COMMAND_TABLE;
80
81COMMAND_TABLE cmd_table[] = {
82 {"create", CMD_CREATE_TDB},
83 {"open", CMD_OPEN_TDB},
84 {"erase", CMD_ERASE},
85 {"dump", CMD_DUMP},
86 {"cdump", CMD_CDUMP},
87 {"insert", CMD_INSERT},
88 {"move", CMD_MOVE},
89 {"store", CMD_STORE},
90 {"show", CMD_SHOW},
91 {"keys", CMD_KEYS},
92 {"hexkeys", CMD_HEXKEYS},
93 {"delete", CMD_DELETE},
94 {"list", CMD_LIST_HASH_FREE},
95 {"free", CMD_LIST_FREE},
96 {"info", CMD_INFO},
97 {"first", CMD_FIRST},
98 {"1", CMD_FIRST},
99 {"next", CMD_NEXT},
100 {"n", CMD_NEXT},
101 {"quit", CMD_QUIT},
102 {"q", CMD_QUIT},
103 {"!", CMD_SYSTEM},
104 {NULL, CMD_HELP}
105};
106
107/* a tdb tool for manipulating a tdb database */
108
109/* these are taken from smb.h - make sure they are in sync */
110
111typedef struct connections_key {
112 pid_t pid;
113 int cnum;
114 fstring name;
115} connections_key;
116
117typedef struct connections_data {
118 int magic;
119 pid_t pid;
120 int cnum;
121 uid_t uid;
122 gid_t gid;
123 char servicename[FSTRING_LEN];
124 char addr[24];
125 char machine[FSTRING_LEN];
126 time_t start;
127 unsigned bcast_msg_flags;
128} connections_data;
129
130static TDB_CONTEXT *tdb;
131
132static int print_crec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
133static int print_arec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
134static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
135static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
136static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
137
138static void print_asc(const char *buf,int len)
139{
140 int i;
141
142 /* We're probably printing ASCII strings so don't try to display
143 the trailing NULL character. */
144
145 if (buf[len - 1] == 0)
146 len--;
147
148 for (i=0;i<len;i++)
149 printf("%c",isprint(buf[i])?buf[i]:'.');
150}
151
152static void print_data(const char *buf,int len)
153{
154 int i=0;
155 if (len<=0) return;
156 printf("[%03X] ",i);
157 for (i=0;i<len;) {
158 printf("%02X ",(int)((unsigned char)buf[i]));
159 i++;
160 if (i%8 == 0) printf(" ");
161 if (i%16 == 0) {
162 print_asc(&buf[i-16],8); printf(" ");
163 print_asc(&buf[i-8],8); printf("\n");
164 if (i<len) printf("[%03X] ",i);
165 }
166 }
167 if (i%16) {
168 int n;
169
170 n = 16 - (i%16);
171 printf(" ");
172 if (n>8) printf(" ");
173 while (n--) printf(" ");
174
175 n = i%16;
176 if (n > 8) n = 8;
177 print_asc(&buf[i-(i%16)],n); printf(" ");
178 n = (i%16) - n;
179 if (n>0) print_asc(&buf[i-n],n);
180 printf("\n");
181 }
182}
183
184static void help(void)
185{
186 printf("\n"
187"tdbtool: \n"
188" create dbname : create a database\n"
189" open dbname : open an existing database\n"
190" erase : erase the database\n"
191" dump : dump the database as strings\n"
192" cdump : dump the database as connection records\n"
193" keys : dump the database keys as strings\n"
194" hexkeys : dump the database keys as hex values\n"
195" info : print summary info about the database\n"
196" insert key data : insert a record\n"
197" move key file : move a record to a destination tdb\n"
198" store key data : store a record (replace)\n"
199" show key : show a record by key\n"
200" delete key : delete a record by key\n"
201" list : print the database hash table and freelist\n"
202" free : print the database freelist\n"
203" ! command : execute system command\n"
204" 1 | first : print the first record\n"
205" n | next : print the next record\n"
206" q | quit : terminate\n"
207" \\n : repeat 'next' command\n"
208"\n");
209}
210
211static void terror(const char *why)
212{
213 printf("%s\n", why);
214}
215
216static void create_tdb(char * tdbname)
217{
218 if (tdb) tdb_close(tdb);
219 tdb = tdb_open(tdbname, 0, TDB_CLEAR_IF_FIRST,
220 O_RDWR | O_CREAT | O_TRUNC, 0600);
221#ifdef __OS2__
222 if (!tdb && !createDbCmd) {
223#else
224 if (!tdb) {
225#endif
226 printf("Could not create %s: %s\n", tdbname, strerror(errno));
227 }
228}
229
230static void open_tdb(char *tdbname)
231{
232 if (tdb) tdb_close(tdb);
233 tdb = tdb_open(tdbname, 0, 0, O_RDWR, 0600);
234 if (!tdb) {
235 printf("Could not open %s: %s\n", tdbname, strerror(errno));
236 }
237}
238
239static void insert_tdb(char *keyname, size_t keylen, char* data, size_t datalen)
240{
241 TDB_DATA key, dbuf;
242
243 if ((keyname == NULL) || (keylen == 0)) {
244 terror("need key");
245 return;
246 }
247
248 key.dptr = keyname;
249 key.dsize = keylen;
250 dbuf.dptr = data;
251 dbuf.dsize = datalen;
252
253 if (tdb_store(tdb, key, dbuf, TDB_INSERT) == -1) {
254 terror("insert failed");
255 }
256}
257
258static void store_tdb(char *keyname, size_t keylen, char* data, size_t datalen)
259{
260 TDB_DATA key, dbuf;
261
262 if ((keyname == NULL) || (keylen == 0)) {
263 terror("need key");
264 return;
265 }
266
267 if ((data == NULL) || (datalen == 0)) {
268 terror("need data");
269 return;
270 }
271
272 key.dptr = keyname;
273 key.dsize = keylen;
274 dbuf.dptr = data;
275 dbuf.dsize = datalen;
276
277 printf("Storing key:\n");
278 print_rec(tdb, key, dbuf, NULL);
279
280 if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) {
281 terror("store failed");
282 }
283}
284
285static void show_tdb(char *keyname, size_t keylen)
286{
287 TDB_DATA key, dbuf;
288
289 if ((keyname == NULL) || (keylen == 0)) {
290 terror("need key");
291 return;
292 }
293
294 key.dptr = keyname;
295 key.dsize = keylen;
296
297 dbuf = tdb_fetch(tdb, key);
298 if (!dbuf.dptr) {
299 terror("fetch failed");
300 return;
301 }
302
303 print_rec(tdb, key, dbuf, NULL);
304
305 free( dbuf.dptr );
306
307 return;
308}
309
310static void delete_tdb(char *keyname, size_t keylen)
311{
312 TDB_DATA key;
313
314 if ((keyname == NULL) || (keylen == 0)) {
315 terror("need key");
316 return;
317 }
318
319 key.dptr = keyname;
320 key.dsize = keylen;
321
322 if (tdb_delete(tdb, key) != 0) {
323 terror("delete failed");
324 }
325}
326
327static void move_rec(char *keyname, size_t keylen, char* tdbname)
328{
329 TDB_DATA key, dbuf;
330 TDB_CONTEXT *dst_tdb;
331
332 if ((keyname == NULL) || (keylen == 0)) {
333 terror("need key");
334 return;
335 }
336
337 if ( !tdbname ) {
338 terror("need destination tdb name");
339 return;
340 }
341
342 key.dptr = keyname;
343 key.dsize = keylen;
344
345 dbuf = tdb_fetch(tdb, key);
346 if (!dbuf.dptr) {
347 terror("fetch failed");
348 return;
349 }
350
351 print_rec(tdb, key, dbuf, NULL);
352
353 dst_tdb = tdb_open(tdbname, 0, 0, O_RDWR, 0600);
354 if ( !dst_tdb ) {
355 terror("unable to open destination tdb");
356 return;
357 }
358
359 if ( tdb_store( dst_tdb, key, dbuf, TDB_REPLACE ) == -1 ) {
360 terror("failed to move record");
361 }
362 else
363 printf("record moved\n");
364
365 tdb_close( dst_tdb );
366
367 return;
368}
369
370static int print_conn_key(TDB_DATA key)
371{
372 printf( "\nkey %d bytes\n", (int)key.dsize);
373 printf( "pid =%5d ", ((connections_key*)key.dptr)->pid);
374 printf( "cnum =%10d ", ((connections_key*)key.dptr)->cnum);
375 printf( "name =[%s]\n", ((connections_key*)key.dptr)->name);
376 return 0;
377}
378
379static int print_conn_data(TDB_DATA dbuf)
380{
381 printf( "\ndata %d bytes\n", (int)dbuf.dsize);
382 printf( "pid =%5d ", ((connections_data*)dbuf.dptr)->pid);
383 printf( "cnum =%10d ", ((connections_data*)dbuf.dptr)->cnum);
384 printf( "name =[%s]\n", ((connections_data*)dbuf.dptr)->servicename);
385
386 printf( "uid =%5d ", ((connections_data*)dbuf.dptr)->uid);
387 printf( "addr =[%s]\n", ((connections_data*)dbuf.dptr)->addr);
388 printf( "gid =%5d ", ((connections_data*)dbuf.dptr)->gid);
389 printf( "machine=[%s]\n", ((connections_data*)dbuf.dptr)->machine);
390 printf( "start = %s\n", ctime(&((connections_data*)dbuf.dptr)->start));
391 printf( "magic = 0x%x ", ((connections_data*)dbuf.dptr)->magic);
392 printf( "flags = 0x%x\n", ((connections_data*)dbuf.dptr)->bcast_msg_flags);
393 return 0;
394}
395
396static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
397{
398 if (do_connections && (dbuf.dsize == sizeof(connections_data)))
399 print_crec(the_tdb, key, dbuf, state);
400 else
401 print_arec(the_tdb, key, dbuf, state);
402 return 0;
403}
404
405static int print_crec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
406{
407 print_conn_key(key);
408 print_conn_data(dbuf);
409 return 0;
410}
411
412static int print_arec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
413{
414 printf("\nkey %d bytes\n", (int)key.dsize);
415 print_asc(key.dptr, key.dsize);
416 printf("\ndata %d bytes\n", (int)dbuf.dsize);
417 print_data(dbuf.dptr, dbuf.dsize);
418 return 0;
419}
420
421static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
422{
423 printf("key %d bytes: ", (int)key.dsize);
424 print_asc(key.dptr, key.dsize);
425 printf("\n");
426 return 0;
427}
428
429static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
430{
431 printf("key %d bytes\n", (int)key.dsize);
432 print_data(key.dptr, key.dsize);
433 printf("\n");
434 return 0;
435}
436
437static int total_bytes;
438
439static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
440{
441 total_bytes += dbuf.dsize;
442 return 0;
443}
444
445static void info_tdb(void)
446{
447 int count;
448 total_bytes = 0;
449 if ((count = tdb_traverse(tdb, traverse_fn, NULL)) == -1)
450 printf("Error = %s\n", tdb_errorstr(tdb));
451 else
452 printf("%d records totalling %d bytes\n", count, total_bytes);
453}
454
455static char *tdb_getline(const char *prompt)
456{
457 static char thisline[1024];
458 char *p;
459 fputs(prompt, stdout);
460 thisline[0] = 0;
461 p = fgets(thisline, sizeof(thisline)-1, stdin);
462 if (p) p = strchr(p, '\n');
463 if (p) *p = 0;
464 return p?thisline:NULL;
465}
466
467static int do_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf,
468 void *state)
469{
470 return tdb_delete(the_tdb, key);
471}
472
473static void first_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey)
474{
475 TDB_DATA dbuf;
476 *pkey = tdb_firstkey(the_tdb);
477
478 dbuf = tdb_fetch(the_tdb, *pkey);
479 if (!dbuf.dptr) terror("fetch failed");
480 else {
481 print_rec(the_tdb, *pkey, dbuf, NULL);
482 }
483}
484
485static void next_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey)
486{
487 TDB_DATA dbuf;
488 *pkey = tdb_nextkey(the_tdb, *pkey);
489
490 dbuf = tdb_fetch(the_tdb, *pkey);
491 if (!dbuf.dptr)
492 terror("fetch failed");
493 else
494 print_rec(the_tdb, *pkey, dbuf, NULL);
495}
496
497static int do_command(void)
498{
499 COMMAND_TABLE *ctp = cmd_table;
500 enum commands mycmd = CMD_HELP;
501 int cmd_len;
502
503 do_connections = 0;
504
505#ifdef __OS2__
506 if (cmdname) {
507#endif
508
509 if (cmdname && strlen(cmdname) == 0) {
510 mycmd = CMD_NEXT;
511 } else {
512 while (ctp->name) {
513 cmd_len = strlen(ctp->name);
514 if (strncmp(ctp->name,cmdname,cmd_len) == 0) {
515 mycmd = ctp->cmd;
516 break;
517 }
518 ctp++;
519 }
520 }
521
522#ifdef __OS2__
523 }
524#endif
525
526 switch (mycmd) {
527 case CMD_CREATE_TDB:
528 bIterate = 0;
529 create_tdb(arg1);
530 return 0;
531 case CMD_OPEN_TDB:
532 bIterate = 0;
533 open_tdb(arg1);
534 return 0;
535 case CMD_SYSTEM:
536 /* Shell command */
537 system(arg1);
538 return 0;
539 case CMD_QUIT:
540 return 1;
541 default:
542 /* all the rest require a open database */
543 if (!tdb) {
544 bIterate = 0;
545 terror("database not open");
546 help();
547 return 0;
548 }
549 switch (mycmd) {
550 case CMD_ERASE:
551 bIterate = 0;
552 tdb_traverse(tdb, do_delete_fn, NULL);
553 return 0;
554 case CMD_DUMP:
555 bIterate = 0;
556 tdb_traverse(tdb, print_rec, NULL);
557 return 0;
558 case CMD_CDUMP:
559 do_connections = 1;
560 bIterate = 0;
561 tdb_traverse(tdb, print_rec, NULL);
562 return 0;
563 case CMD_INSERT:
564 bIterate = 0;
565 insert_tdb(arg1, arg1len,arg2,arg2len);
566 return 0;
567 case CMD_MOVE:
568 bIterate = 0;
569 move_rec(arg1,arg1len,arg2);
570 return 0;
571 case CMD_STORE:
572 bIterate = 0;
573 store_tdb(arg1,arg1len,arg2,arg2len);
574 return 0;
575 case CMD_SHOW:
576 bIterate = 0;
577 show_tdb(arg1, arg1len);
578 return 0;
579 case CMD_KEYS:
580 tdb_traverse(tdb, print_key, NULL);
581 return 0;
582 case CMD_HEXKEYS:
583 tdb_traverse(tdb, print_hexkey, NULL);
584 return 0;
585 case CMD_DELETE:
586 bIterate = 0;
587 delete_tdb(arg1,arg1len);
588 return 0;
589 case CMD_LIST_HASH_FREE:
590 tdb_dump_all(tdb);
591 return 0;
592 case CMD_LIST_FREE:
593 tdb_printfreelist(tdb);
594 return 0;
595 case CMD_INFO:
596 info_tdb();
597 return 0;
598 case CMD_FIRST:
599 bIterate = 1;
600 first_record(tdb, &iterate_kbuf);
601 return 0;
602 case CMD_NEXT:
603 if (bIterate)
604 next_record(tdb, &iterate_kbuf);
605 return 0;
606 case CMD_HELP:
607 help();
608 return 0;
609 case CMD_CREATE_TDB:
610 case CMD_OPEN_TDB:
611 case CMD_SYSTEM:
612 case CMD_QUIT:
613 /*
614 * unhandled commands. cases included here to avoid compiler
615 * warnings.
616 */
617 return 0;
618 }
619 }
620
621 return 0;
622}
623
624static char *convert_string(char *instring, size_t *sizep)
625{
626 size_t length = 0;
627 char *outp, *inp;
628 char temp[3];
629
630
631 outp = inp = instring;
632
633 while (*inp) {
634 if (*inp == '\\') {
635 inp++;
636 if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) {
637 temp[0] = *inp++;
638 temp[1] = '\0';
639 if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) {
640 temp[1] = *inp++;
641 temp[2] = '\0';
642 }
643 *outp++ = (char)strtol((const char *)temp,NULL,16);
644 } else {
645 *outp++ = *inp++;
646 }
647 } else {
648 *outp++ = *inp++;
649 }
650 length++;
651 }
652 *sizep = length;
653 return instring;
654}
655
656int main(int argc, char *argv[])
657{
658 cmdname = (char *) "";
659 arg1 = NULL;
660 arg1len = 0;
661 arg2 = NULL;
662 arg2len = 0;
663
664#ifdef __OS2__
665 int cnt = 1;
666 createDbCmd = 0;
667 while (argv[cnt]) {
668 if (strncmp("create",argv[cnt],6) == 0) {
669 createDbCmd = 1;
670 break;
671 }
672 cnt++;
673 }
674#endif
675
676 if (argv[1]) {
677 cmdname = (char *) "open";
678 arg1 = argv[1];
679 do_command();
680 cmdname = (char *) "";
681 arg1 = NULL;
682 }
683
684 switch (argc) {
685 case 1:
686 case 2:
687 /* Interactive mode */
688 while ((cmdname = tdb_getline("tdb> "))) {
689 arg2 = arg1 = NULL;
690 if ((arg1 = strchr((const char *)cmdname,' ')) != NULL) {
691 arg1++;
692 arg2 = arg1;
693 while (*arg2) {
694 if (*arg2 == ' ') {
695 *arg2++ = '\0';
696 break;
697 }
698 if ((*arg2++ == '\\') && (*arg2 == ' ')) {
699 arg2++;
700 }
701 }
702 }
703 if (arg1) arg1 = convert_string(arg1,&arg1len);
704 if (arg2) arg2 = convert_string(arg2,&arg2len);
705 if (do_command()) break;
706 }
707 break;
708 case 5:
709 arg2 = convert_string(argv[4],&arg2len);
710 case 4:
711 arg1 = convert_string(argv[3],&arg1len);
712 case 3:
713 cmdname = argv[2];
714 default:
715#ifdef __OS2__
716 if (argc == 3) {
717 arg1 = convert_string(argv[1], &arg1len);
718 }
719#endif
720 do_command();
721 break;
722 }
723
724 if (tdb) tdb_close(tdb);
725
726 return 0;
727}
Note: See TracBrowser for help on using the repository browser.