This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.(This used to...
[ira/wip.git] / source3 / tdb / tdbtool.c
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 "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 *the_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 #if 0
283 static int print_conn_key(TDB_DATA key)
284 {
285         printf( "pid    =%5d   ", ((connections_key*)key.dptr)->pid);
286         printf( "cnum   =%10d  ", ((connections_key*)key.dptr)->cnum);
287         printf( "name   =[%s]\n", ((connections_key*)key.dptr)->name);
288         return 0;
289 }
290
291 static int print_conn_data(TDB_DATA dbuf)
292 {
293         printf( "pid    =%5d   ", ((connections_data*)dbuf.dptr)->pid);
294         printf( "cnum   =%10d  ", ((connections_data*)dbuf.dptr)->cnum);
295         printf( "name   =[%s]\n", ((connections_data*)dbuf.dptr)->name);
296         
297         printf( "uid    =%5d   ",  ((connections_data*)dbuf.dptr)->uid);
298         printf( "addr   =[%s]\n", ((connections_data*)dbuf.dptr)->addr);
299         printf( "gid    =%5d   ",  ((connections_data*)dbuf.dptr)->gid);
300         printf( "machine=[%s]\n", ((connections_data*)dbuf.dptr)->machine);
301         printf( "start  = %s\n",   ctime(&((connections_data*)dbuf.dptr)->start));
302         return 0;
303 }
304 #endif
305
306 static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
307 {
308 #if 0
309         print_conn_key(key);
310         print_conn_data(dbuf);
311         return 0;
312 #else
313         printf("\nkey %d bytes\n", key.dsize);
314         print_asc(key.dptr, key.dsize);
315         printf("\ndata %d bytes\n", dbuf.dsize);
316         print_data(dbuf.dptr, dbuf.dsize);
317         return 0;
318 #endif
319 }
320
321 static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
322 {
323         print_asc(key.dptr, key.dsize);
324         printf("\n");
325         return 0;
326 }
327
328 static int total_bytes;
329
330 static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
331 {
332         total_bytes += dbuf.dsize;
333         return 0;
334 }
335
336 static void info_tdb(void)
337 {
338         int count;
339         total_bytes = 0;
340         if ((count = tdb_traverse(tdb, traverse_fn, NULL) == -1))
341                 printf("Error = %s\n", tdb_errorstr(tdb));
342         else
343                 printf("%d records totalling %d bytes\n", count, total_bytes);
344 }
345
346 static char *tdb_getline(char *prompt)
347 {
348         static char line[1024];
349         char *p;
350         fputs(prompt, stdout);
351         line[0] = 0;
352         p = fgets(line, sizeof(line)-1, stdin);
353         if (p) p = strchr(p, '\n');
354         if (p) *p = 0;
355         return p?line:NULL;
356 }
357
358 static int do_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf,
359                      void *state)
360 {
361     return tdb_delete(the_tdb, key);
362 }
363
364 static void first_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey)
365 {
366         TDB_DATA dbuf;
367         *pkey = tdb_firstkey(the_tdb);
368         
369         dbuf = tdb_fetch(the_tdb, *pkey);
370         if (!dbuf.dptr) terror("fetch failed");
371         else {
372                 /* printf("%s : %*.*s\n", k, (int)dbuf.dsize, (int)dbuf.dsize, dbuf.dptr); */
373                 print_rec(the_tdb, *pkey, dbuf, NULL);
374         }
375 }
376
377 static void next_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey)
378 {
379         TDB_DATA dbuf;
380         *pkey = tdb_nextkey(the_tdb, *pkey);
381         
382         dbuf = tdb_fetch(the_tdb, *pkey);
383         if (!dbuf.dptr) 
384                 terror("fetch failed");
385         else
386                 /* printf("%s : %*.*s\n", k, (int)dbuf.dsize, (int)dbuf.dsize, dbuf.dptr); */
387                 print_rec(the_tdb, *pkey, dbuf, NULL);
388 }
389
390 int main(int argc, char *argv[])
391 {
392     int bIterate = 0;
393     char *line;
394     char *tok;
395         TDB_DATA iterate_kbuf;
396
397     if (argv[1]) {
398         static char tmp[1024];
399         sprintf(tmp, "open %s", argv[1]);
400         tok=strtok(tmp," ");
401         open_tdb();
402     }
403
404     while ((line = tdb_getline("tdb> "))) {
405
406         /* Shell command */
407         
408         if (line[0] == '!') {
409             system(line + 1);
410             continue;
411         }
412         
413         if ((tok = strtok(line," "))==NULL) {
414            if (bIterate)
415               next_record(tdb, &iterate_kbuf);
416            continue;
417         }
418         if (strcmp(tok,"create") == 0) {
419             bIterate = 0;
420             create_tdb();
421             continue;
422         } else if (strcmp(tok,"open") == 0) {
423             open_tdb();
424             continue;
425         } else if ((strcmp(tok, "q") == 0) ||
426                    (strcmp(tok, "quit") == 0)) {
427             break;
428         }
429             
430         /* all the rest require a open database */
431         if (!tdb) {
432             bIterate = 0;
433             terror("database not open");
434             help();
435             continue;
436         }
437             
438         if (strcmp(tok,"insert") == 0) {
439             bIterate = 0;
440             insert_tdb();
441         } else if (strcmp(tok,"store") == 0) {
442             bIterate = 0;
443             store_tdb();
444         } else if (strcmp(tok,"show") == 0) {
445             bIterate = 0;
446             show_tdb();
447         } else if (strcmp(tok,"erase") == 0) {
448             bIterate = 0;
449             tdb_traverse(tdb, do_delete_fn, NULL);
450         } else if (strcmp(tok,"delete") == 0) {
451             bIterate = 0;
452             delete_tdb();
453         } else if (strcmp(tok,"dump") == 0) {
454             bIterate = 0;
455             tdb_traverse(tdb, print_rec, NULL);
456         } else if (strcmp(tok,"list") == 0) {
457             tdb_dump_all(tdb);
458         } else if (strcmp(tok, "free") == 0) {
459             tdb_printfreelist(tdb);
460         } else if (strcmp(tok,"info") == 0) {
461             info_tdb();
462         } else if ( (strcmp(tok, "1") == 0) ||
463                     (strcmp(tok, "first") == 0)) {
464             bIterate = 1;
465             first_record(tdb, &iterate_kbuf);
466         } else if ((strcmp(tok, "n") == 0) ||
467                    (strcmp(tok, "next") == 0)) {
468             next_record(tdb, &iterate_kbuf);
469         } else if ((strcmp(tok, "keys") == 0)) {
470                 bIterate = 0;
471                 tdb_traverse(tdb, print_key, NULL);
472         } else {
473             help();
474         }
475     }
476
477     if (tdb) tdb_close(tdb);
478
479     return 0;
480 }