31ecd17a0c100ce471e75d6b1133a40d497a6e2f
[jra/samba/.git] / source3 / tdb / tdbtool.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    Samba database functions
5    Copyright (C) Andrew Tridgell              1999-2000
6    Copyright (C) Paul `Rusty' Russell              2000
7    Copyright (C) Jeremy Allison                    2000
8    Copyright (C) Andrew Esh                        2001
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include <errno.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <fcntl.h>
32 #include <sys/mman.h>
33 #include <sys/stat.h>
34 #include <sys/time.h>
35 #include <ctype.h>
36 #include "tdb.h"
37
38 /* a tdb tool for manipulating a tdb database */
39
40 #define FSTRING_LEN 256
41 typedef char fstring[FSTRING_LEN];
42
43 typedef struct connections_key {
44         pid_t pid;
45         int cnum;
46         fstring name;
47 } connections_key;
48
49 typedef struct connections_data {
50         int magic;
51         pid_t pid;
52         int cnum;
53         uid_t uid;
54         gid_t gid;
55         char name[24];
56         char addr[24];
57         char machine[128];
58         time_t start;
59 } connections_data;
60
61 static TDB_CONTEXT *tdb;
62
63 static int print_rec(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
64
65 static void print_asc(unsigned char *buf,int len)
66 {
67         int i;
68
69         /* We're probably printing ASCII strings so don't try to display
70            the trailing NULL character. */
71
72         if (buf[len - 1] == 0)
73                 len--;
74
75         for (i=0;i<len;i++)
76                 printf("%c",isprint(buf[i])?buf[i]:'.');
77 }
78
79 static void print_data(unsigned char *buf,int len)
80 {
81         int i=0;
82         if (len<=0) return;
83         printf("[%03X] ",i);
84         for (i=0;i<len;) {
85                 printf("%02X ",(int)buf[i]);
86                 i++;
87                 if (i%8 == 0) printf(" ");
88                 if (i%16 == 0) {      
89                         print_asc(&buf[i-16],8); printf(" ");
90                         print_asc(&buf[i-8],8); printf("\n");
91                         if (i<len) printf("[%03X] ",i);
92                 }
93         }
94         if (i%16) {
95                 int n;
96                 
97                 n = 16 - (i%16);
98                 printf(" ");
99                 if (n>8) printf(" ");
100                 while (n--) printf("   ");
101                 
102                 n = i%16;
103                 if (n > 8) n = 8;
104                 print_asc(&buf[i-(i%16)],n); printf(" ");
105                 n = (i%16) - n;
106                 if (n>0) print_asc(&buf[i-n],n); 
107                 printf("\n");    
108         }
109 }
110
111 static void help(void)
112 {
113         printf("
114 tdbtool: 
115   create    dbname     : create a database
116   open      dbname     : open an existing database
117   erase                : erase the database
118   dump                 : dump the database as strings
119   insert    key  data  : insert a record
120   store     key  data  : store a record (replace)
121   show      key        : show a record by key
122   delete    key        : delete a record by key
123   list                 : print the database hash table and freelist
124   free                 : print the database freelist
125   1 | first            : print the first record
126   n | next             : print the next record
127   q | quit             : terminate
128   \\n                   : repeat 'next' command
129 ");
130 }
131
132 static void terror(char *why)
133 {
134         printf("%s\n", why);
135 }
136
137 static char *get_token(int startover)
138 {
139         static char tmp[1024];
140         static char *cont = NULL;
141         char *insert, *start;
142         char *k = strtok(NULL, " ");
143
144         if (!k)
145           return NULL;
146
147         if (startover)
148           start = tmp;
149         else
150           start = cont;
151
152         strcpy(start, k);
153         insert = start + strlen(start) - 1;
154         while (*insert == '\\') {
155           *insert++ = ' ';
156           k = strtok(NULL, " ");
157           if (!k)
158             break;
159           strcpy(insert, k);
160           insert = start + strlen(start) - 1;
161         }
162
163         /* Get ready for next call */
164         cont = start + strlen(start) + 1;
165         return start;
166 }
167
168 static void create_tdb(void)
169 {
170         char *tok = get_token(1);
171         if (!tok) {
172                 help();
173                 return;
174         }
175         if (tdb) tdb_close(tdb);
176         tdb = tdb_open(tok, 0, TDB_CLEAR_IF_FIRST,
177                        O_RDWR | O_CREAT | O_TRUNC, 0600);
178         if (!tdb) {
179                 printf("Could not create %s: %s\n", tok, strerror(errno));
180         }
181 }
182
183 static void open_tdb(void)
184 {
185         char *tok = get_token(1);
186         if (!tok) {
187                 help();
188                 return;
189         }
190         if (tdb) tdb_close(tdb);
191         tdb = tdb_open(tok, 0, 0, O_RDWR, 0600);
192         if (!tdb) {
193                 printf("Could not open %s: %s\n", tok, strerror(errno));
194         }
195 }
196
197 static void insert_tdb(void)
198 {
199         char *k = get_token(1);
200         char *d = get_token(0);
201         TDB_DATA key, dbuf;
202
203         if (!k || !d) {
204                 help();
205                 return;
206         }
207
208         key.dptr = k;
209         key.dsize = strlen(k)+1;
210         dbuf.dptr = d;
211         dbuf.dsize = strlen(d)+1;
212
213         if (tdb_store(tdb, key, dbuf, TDB_INSERT) == -1) {
214                 terror("insert failed");
215         }
216 }
217
218 static void store_tdb(void)
219 {
220         char *k = get_token(1);
221         char *d = get_token(0);
222         TDB_DATA key, dbuf;
223
224         if (!k || !d) {
225                 help();
226                 return;
227         }
228
229         key.dptr = k;
230         key.dsize = strlen(k)+1;
231         dbuf.dptr = d;
232         dbuf.dsize = strlen(d)+1;
233
234         printf("Storing key:\n");
235         print_rec(tdb, key, dbuf, NULL);
236
237         if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) {
238                 terror("store failed");
239         }
240 }
241
242 static void show_tdb(void)
243 {
244         char *k = get_token(1);
245         TDB_DATA key, dbuf;
246
247         if (!k) {
248                 help();
249                 return;
250         }
251
252         key.dptr = k;
253         key.dsize = strlen(k)+1;
254
255         dbuf = tdb_fetch(tdb, key);
256         if (!dbuf.dptr) {
257                 terror("fetch failed");
258                 return;
259         }
260         /* printf("%s : %*.*s\n", k, (int)dbuf.dsize, (int)dbuf.dsize, dbuf.dptr); */
261         print_rec(tdb, key, dbuf, NULL);
262 }
263
264 static void delete_tdb(void)
265 {
266         char *k = get_token(1);
267         TDB_DATA key;
268
269         if (!k) {
270                 help();
271                 return;
272         }
273
274         key.dptr = k;
275         key.dsize = strlen(k)+1;
276
277         if (tdb_delete(tdb, key) != 0) {
278                 terror("delete failed");
279         }
280 }
281
282 static int print_conn_key(TDB_DATA key)
283 {
284         printf( "pid    =%5d   ", ((connections_key*)key.dptr)->pid);
285         printf( "cnum   =%10d  ", ((connections_key*)key.dptr)->cnum);
286         printf( "name   =[%s]\n", ((connections_key*)key.dptr)->name);
287         return 0;
288 }
289
290 static int print_conn_data(TDB_DATA dbuf)
291 {
292         printf( "pid    =%5d   ", ((connections_data*)dbuf.dptr)->pid);
293         printf( "cnum   =%10d  ", ((connections_data*)dbuf.dptr)->cnum);
294         printf( "name   =[%s]\n", ((connections_data*)dbuf.dptr)->name);
295         
296         printf( "uid    =%5d   ",  ((connections_data*)dbuf.dptr)->uid);
297         printf( "addr   =[%s]\n", ((connections_data*)dbuf.dptr)->addr);
298         printf( "gid    =%5d   ",  ((connections_data*)dbuf.dptr)->gid);
299         printf( "machine=[%s]\n", ((connections_data*)dbuf.dptr)->machine);
300         printf( "start  = %s\n",   ctime(&((connections_data*)dbuf.dptr)->start));
301         return 0;
302 }
303
304 static int print_rec(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
305 {
306 #if 0
307         print_conn_key(key);
308         print_conn_data(dbuf);
309         return 0;
310 #else
311         printf("\nkey %d bytes\n", key.dsize);
312         print_asc(key.dptr, key.dsize);
313         printf("data %d bytes\n", dbuf.dsize);
314         print_data(dbuf.dptr, dbuf.dsize);
315         return 0;
316 #endif
317 }
318
319 static int print_key(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
320 {
321         print_asc(key.dptr, key.dsize);
322         printf("\n");
323         return 0;
324 }
325
326 static int total_bytes;
327
328 static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
329 {
330         total_bytes += dbuf.dsize;
331         return 0;
332 }
333
334 static void info_tdb(void)
335 {
336         int count;
337         total_bytes = 0;
338         if ((count = tdb_traverse(tdb, traverse_fn, NULL) == -1))
339                 printf("Error = %s\n", tdb_errorstr(tdb));
340         else
341                 printf("%d records totalling %d bytes\n", count, total_bytes);
342 }
343
344 static char *tdb_getline(char *prompt)
345 {
346         static char line[1024];
347         char *p;
348         fputs(prompt, stdout);
349         line[0] = 0;
350         p = fgets(line, sizeof(line)-1, stdin);
351         if (p) p = strchr(p, '\n');
352         if (p) *p = 0;
353         return p?line:NULL;
354 }
355
356 static int do_delete_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf,
357                      void *state)
358 {
359     return tdb_delete(tdb, key);
360 }
361
362 static void first_record(TDB_CONTEXT *tdb, TDB_DATA *pkey)
363 {
364         TDB_DATA dbuf;
365         *pkey = tdb_firstkey(tdb);
366         
367         dbuf = tdb_fetch(tdb, *pkey);
368         if (!dbuf.dptr) terror("fetch failed");
369         /* printf("%s : %*.*s\n", k, (int)dbuf.dsize, (int)dbuf.dsize, dbuf.dptr); */
370         print_rec(tdb, *pkey, dbuf, NULL);
371 }
372
373 static void next_record(TDB_CONTEXT *tdb, TDB_DATA *pkey)
374 {
375         TDB_DATA dbuf;
376         *pkey = tdb_nextkey(tdb, *pkey);
377         
378         dbuf = tdb_fetch(tdb, *pkey);
379         if (!dbuf.dptr) 
380                 terror("fetch failed");
381         else
382                 /* printf("%s : %*.*s\n", k, (int)dbuf.dsize, (int)dbuf.dsize, dbuf.dptr); */
383                 print_rec(tdb, *pkey, dbuf, NULL);
384 }
385
386 int main(int argc, char *argv[])
387 {
388     int bIterate = 0;
389     char *line;
390     char *tok;
391         TDB_DATA iterate_kbuf;
392
393     if (argv[1]) {
394         static char tmp[1024];
395         sprintf(tmp, "open %s", argv[1]);
396         tok=strtok(tmp," ");
397         open_tdb();
398     }
399
400     while ((line = tdb_getline("tdb> "))) {
401
402         /* Shell command */
403         
404         if (line[0] == '!') {
405             system(line + 1);
406             continue;
407         }
408         
409         if ((tok = strtok(line," "))==NULL) {
410            if (bIterate)
411               next_record(tdb, &iterate_kbuf);
412            continue;
413         }
414         if (strcmp(tok,"create") == 0) {
415             bIterate = 0;
416             create_tdb();
417             continue;
418         } else if (strcmp(tok,"open") == 0) {
419             open_tdb();
420             continue;
421         } else if ((strcmp(tok, "q") == 0) ||
422                    (strcmp(tok, "quit") == 0)) {
423             break;
424         }
425             
426         /* all the rest require a open database */
427         if (!tdb) {
428             bIterate = 0;
429             terror("database not open");
430             help();
431             continue;
432         }
433             
434         if (strcmp(tok,"insert") == 0) {
435             bIterate = 0;
436             insert_tdb();
437         } else if (strcmp(tok,"store") == 0) {
438             bIterate = 0;
439             store_tdb();
440         } else if (strcmp(tok,"show") == 0) {
441             bIterate = 0;
442             show_tdb();
443         } else if (strcmp(tok,"erase") == 0) {
444             bIterate = 0;
445             tdb_traverse(tdb, do_delete_fn, NULL);
446         } else if (strcmp(tok,"delete") == 0) {
447             bIterate = 0;
448             delete_tdb();
449         } else if (strcmp(tok,"dump") == 0) {
450             bIterate = 0;
451             tdb_traverse(tdb, print_rec, NULL);
452         } else if (strcmp(tok,"list") == 0) {
453             tdb_dump_all(tdb);
454         } else if (strcmp(tok, "free") == 0) {
455             tdb_printfreelist(tdb);
456         } else if (strcmp(tok,"info") == 0) {
457             info_tdb();
458         } else if ( (strcmp(tok, "1") == 0) ||
459                     (strcmp(tok, "first") == 0)) {
460             bIterate = 1;
461             first_record(tdb, &iterate_kbuf);
462         } else if ((strcmp(tok, "n") == 0) ||
463                    (strcmp(tok, "next") == 0)) {
464             next_record(tdb, &iterate_kbuf);
465         } else if ((strcmp(tok, "keys") == 0)) {
466                 bIterate = 0;
467                 tdb_traverse(tdb, print_key, NULL);
468         } else {
469             help();
470         }
471     }
472
473     if (tdb) tdb_close(tdb);
474
475     return 0;
476 }