tdb/tools/tdbtool.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    Samba database functions
00004    Copyright (C) Andrew Tridgell              1999-2000
00005    Copyright (C) Paul `Rusty' Russell              2000
00006    Copyright (C) Jeremy Allison                    2000
00007    Copyright (C) Andrew Esh                        2001
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2 of the License, or
00012    (at your option) any later version.
00013    
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018    
00019    You should have received a copy of the GNU General Public License
00020    along with this program; if not, write to the Free Software
00021    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00022 */
00023 
00024 #include <errno.h>
00025 #include <stdlib.h>
00026 #include <stdio.h>
00027 #include <fcntl.h>
00028 #include <unistd.h>
00029 #include <string.h>
00030 #include <fcntl.h>
00031 #include <time.h>
00032 #include <sys/mman.h>
00033 #include <sys/stat.h>
00034 #include <sys/time.h>
00035 #include <ctype.h>
00036 #include <signal.h>
00037 #include "tdb.h"
00038 #include "pstring.h"
00039 
00040 static int do_command(void);
00041 char *cmdname, *arg1, *arg2;
00042 size_t arg1len, arg2len;
00043 int do_connections;
00044 int bIterate = 0;
00045 char *line;
00046 TDB_DATA iterate_kbuf;
00047 char cmdline[1024];
00048 
00049 enum commands {
00050         CMD_CREATE_TDB,
00051         CMD_OPEN_TDB,
00052         CMD_ERASE,
00053         CMD_DUMP,
00054         CMD_CDUMP,
00055         CMD_INSERT,
00056         CMD_MOVE,
00057         CMD_STORE,
00058         CMD_SHOW,
00059         CMD_KEYS,
00060         CMD_HEXKEYS,
00061         CMD_DELETE,
00062         CMD_LIST_HASH_FREE,
00063         CMD_LIST_FREE,
00064         CMD_INFO,
00065         CMD_FIRST,
00066         CMD_NEXT,
00067         CMD_SYSTEM,
00068         CMD_QUIT,
00069         CMD_HELP
00070 };
00071 
00072 typedef struct {
00073         const char *name;
00074         enum commands cmd;
00075 } COMMAND_TABLE;
00076 
00077 COMMAND_TABLE cmd_table[] = {
00078         {"create",      CMD_CREATE_TDB},
00079         {"open",        CMD_OPEN_TDB},
00080         {"erase",       CMD_ERASE},
00081         {"dump",        CMD_DUMP},
00082         {"cdump",       CMD_CDUMP},
00083         {"insert",      CMD_INSERT},
00084         {"move",        CMD_MOVE},
00085         {"store",       CMD_STORE},
00086         {"show",        CMD_SHOW},
00087         {"keys",        CMD_KEYS},
00088         {"hexkeys",     CMD_HEXKEYS},
00089         {"delete",      CMD_DELETE},
00090         {"list",        CMD_LIST_HASH_FREE},
00091         {"free",        CMD_LIST_FREE},
00092         {"info",        CMD_INFO},
00093         {"first",       CMD_FIRST},
00094         {"1",           CMD_FIRST},
00095         {"next",        CMD_NEXT},
00096         {"n",           CMD_NEXT},
00097         {"quit",        CMD_QUIT},
00098         {"q",           CMD_QUIT},
00099         {"!",           CMD_SYSTEM},
00100         {NULL,          CMD_HELP}
00101 };
00102 
00103 /* a tdb tool for manipulating a tdb database */
00104 
00105 /* these are taken from smb.h - make sure they are in sync */
00106 
00107 typedef struct connections_key {
00108         pid_t pid;
00109         int cnum;
00110         fstring name;
00111 } connections_key;
00112 
00113 typedef struct connections_data {
00114         int magic;
00115         pid_t pid;
00116         int cnum;
00117         uid_t uid;
00118         gid_t gid;
00119         char servicename[FSTRING_LEN];
00120         char addr[24];
00121         char machine[FSTRING_LEN];
00122         time_t start;
00123         unsigned bcast_msg_flags;
00124 } connections_data;
00125 
00126 static TDB_CONTEXT *tdb;
00127 
00128 static int print_crec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
00129 static int print_arec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
00130 static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
00131 static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
00132 static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
00133 
00134 static void print_asc(const char *buf,int len)
00135 {
00136         int i;
00137 
00138         /* We're probably printing ASCII strings so don't try to display
00139            the trailing NULL character. */
00140 
00141         if (buf[len - 1] == 0)
00142                 len--;
00143 
00144         for (i=0;i<len;i++)
00145                 printf("%c",isprint(buf[i])?buf[i]:'.');
00146 }
00147 
00148 static void print_data(const char *buf,int len)
00149 {
00150         int i=0;
00151         if (len<=0) return;
00152         printf("[%03X] ",i);
00153         for (i=0;i<len;) {
00154                 printf("%02X ",(int)((unsigned char)buf[i]));
00155                 i++;
00156                 if (i%8 == 0) printf(" ");
00157                 if (i%16 == 0) {      
00158                         print_asc(&buf[i-16],8); printf(" ");
00159                         print_asc(&buf[i-8],8); printf("\n");
00160                         if (i<len) printf("[%03X] ",i);
00161                 }
00162         }
00163         if (i%16) {
00164                 int n;
00165                 
00166                 n = 16 - (i%16);
00167                 printf(" ");
00168                 if (n>8) printf(" ");
00169                 while (n--) printf("   ");
00170                 
00171                 n = i%16;
00172                 if (n > 8) n = 8;
00173                 print_asc(&buf[i-(i%16)],n); printf(" ");
00174                 n = (i%16) - n;
00175                 if (n>0) print_asc(&buf[i-n],n); 
00176                 printf("\n");    
00177         }
00178 }
00179 
00180 static void help(void)
00181 {
00182         printf("\n"
00183 "tdbtool: \n"
00184 "  create    dbname     : create a database\n"
00185 "  open      dbname     : open an existing database\n"
00186 "  erase                : erase the database\n"
00187 "  dump                 : dump the database as strings\n"
00188 "  cdump                : dump the database as connection records\n"
00189 "  keys                 : dump the database keys as strings\n"
00190 "  hexkeys              : dump the database keys as hex values\n"
00191 "  info                 : print summary info about the database\n"
00192 "  insert    key  data  : insert a record\n"
00193 "  move      key  file  : move a record to a destination tdb\n"
00194 "  store     key  data  : store a record (replace)\n"
00195 "  show      key        : show a record by key\n"
00196 "  delete    key        : delete a record by key\n"
00197 "  list                 : print the database hash table and freelist\n"
00198 "  free                 : print the database freelist\n"
00199 "  ! command            : execute system command\n"             
00200 "  1 | first            : print the first record\n"
00201 "  n | next             : print the next record\n"
00202 "  q | quit             : terminate\n"
00203 "  \\n                   : repeat 'next' command\n"
00204 "\n");
00205 }
00206 
00207 static void terror(const char *why)
00208 {
00209         printf("%s\n", why);
00210 }
00211 
00212 static void create_tdb(char * tdbname)
00213 {
00214         if (tdb) tdb_close(tdb);
00215         tdb = tdb_open(tdbname, 0, TDB_CLEAR_IF_FIRST,
00216                        O_RDWR | O_CREAT | O_TRUNC, 0600);
00217         if (!tdb) {
00218                 printf("Could not create %s: %s\n", tdbname, strerror(errno));
00219         }
00220 }
00221 
00222 static void open_tdb(char *tdbname)
00223 {
00224         if (tdb) tdb_close(tdb);
00225         tdb = tdb_open(tdbname, 0, 0, O_RDWR, 0600);
00226         if (!tdb) {
00227                 printf("Could not open %s: %s\n", tdbname, strerror(errno));
00228         }
00229 }
00230 
00231 static void insert_tdb(char *keyname, size_t keylen, char* data, size_t datalen)
00232 {
00233         TDB_DATA key, dbuf;
00234 
00235         if ((keyname == NULL) || (keylen == 0)) {
00236                 terror("need key");
00237                 return;
00238         }
00239 
00240         key.dptr = keyname;
00241         key.dsize = keylen;
00242         dbuf.dptr = data;
00243         dbuf.dsize = datalen;
00244 
00245         if (tdb_store(tdb, key, dbuf, TDB_INSERT) == -1) {
00246                 terror("insert failed");
00247         }
00248 }
00249 
00250 static void store_tdb(char *keyname, size_t keylen, char* data, size_t datalen)
00251 {
00252         TDB_DATA key, dbuf;
00253 
00254         if ((keyname == NULL) || (keylen == 0)) {
00255                 terror("need key");
00256                 return;
00257         }
00258 
00259         if ((data == NULL) || (datalen == 0)) {
00260                 terror("need data");
00261                 return;
00262         }
00263 
00264         key.dptr = keyname;
00265         key.dsize = keylen;
00266         dbuf.dptr = data;
00267         dbuf.dsize = datalen;
00268 
00269         printf("Storing key:\n");
00270         print_rec(tdb, key, dbuf, NULL);
00271 
00272         if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) {
00273                 terror("store failed");
00274         }
00275 }
00276 
00277 static void show_tdb(char *keyname, size_t keylen)
00278 {
00279         TDB_DATA key, dbuf;
00280 
00281         if ((keyname == NULL) || (keylen == 0)) {
00282                 terror("need key");
00283                 return;
00284         }
00285 
00286         key.dptr = keyname;
00287         key.dsize = keylen;
00288 
00289         dbuf = tdb_fetch(tdb, key);
00290         if (!dbuf.dptr) {
00291             terror("fetch failed");
00292             return;
00293         }
00294         
00295         print_rec(tdb, key, dbuf, NULL);
00296         
00297         free( dbuf.dptr );
00298         
00299         return;
00300 }
00301 
00302 static void delete_tdb(char *keyname, size_t keylen)
00303 {
00304         TDB_DATA key;
00305 
00306         if ((keyname == NULL) || (keylen == 0)) {
00307                 terror("need key");
00308                 return;
00309         }
00310 
00311         key.dptr = keyname;
00312         key.dsize = keylen;
00313 
00314         if (tdb_delete(tdb, key) != 0) {
00315                 terror("delete failed");
00316         }
00317 }
00318 
00319 static void move_rec(char *keyname, size_t keylen, char* tdbname)
00320 {
00321         TDB_DATA key, dbuf;
00322         TDB_CONTEXT *dst_tdb;
00323 
00324         if ((keyname == NULL) || (keylen == 0)) {
00325                 terror("need key");
00326                 return;
00327         }
00328 
00329         if ( !tdbname ) {
00330                 terror("need destination tdb name");
00331                 return;
00332         }
00333 
00334         key.dptr = keyname;
00335         key.dsize = keylen;
00336 
00337         dbuf = tdb_fetch(tdb, key);
00338         if (!dbuf.dptr) {
00339                 terror("fetch failed");
00340                 return;
00341         }
00342         
00343         print_rec(tdb, key, dbuf, NULL);
00344         
00345         dst_tdb = tdb_open(tdbname, 0, 0, O_RDWR, 0600);
00346         if ( !dst_tdb ) {
00347                 terror("unable to open destination tdb");
00348                 return;
00349         }
00350         
00351         if ( tdb_store( dst_tdb, key, dbuf, TDB_REPLACE ) == -1 ) {
00352                 terror("failed to move record");
00353         }
00354         else
00355                 printf("record moved\n");
00356         
00357         tdb_close( dst_tdb );
00358         
00359         return;
00360 }
00361 
00362 static int print_conn_key(TDB_DATA key)
00363 {
00364         printf( "\nkey %d bytes\n", (int)key.dsize);
00365         printf( "pid    =%5d   ", ((connections_key*)key.dptr)->pid);
00366         printf( "cnum   =%10d  ", ((connections_key*)key.dptr)->cnum);
00367         printf( "name   =[%s]\n", ((connections_key*)key.dptr)->name);
00368         return 0;
00369 }
00370 
00371 static int print_conn_data(TDB_DATA dbuf)
00372 {
00373         printf( "\ndata %d bytes\n", (int)dbuf.dsize);
00374         printf( "pid    =%5d   ", ((connections_data*)dbuf.dptr)->pid);
00375         printf( "cnum   =%10d  ", ((connections_data*)dbuf.dptr)->cnum);
00376         printf( "name   =[%s]\n", ((connections_data*)dbuf.dptr)->servicename);
00377         
00378         printf( "uid    =%5d   ",  ((connections_data*)dbuf.dptr)->uid);
00379         printf( "addr   =[%s]\n", ((connections_data*)dbuf.dptr)->addr);
00380         printf( "gid    =%5d   ",  ((connections_data*)dbuf.dptr)->gid);
00381         printf( "machine=[%s]\n", ((connections_data*)dbuf.dptr)->machine);
00382         printf( "start  = %s\n",   ctime(&((connections_data*)dbuf.dptr)->start));
00383         printf( "magic  = 0x%x ",   ((connections_data*)dbuf.dptr)->magic);
00384         printf( "flags  = 0x%x\n",  ((connections_data*)dbuf.dptr)->bcast_msg_flags);
00385         return 0;
00386 }
00387 
00388 static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
00389 {
00390         if (do_connections && (dbuf.dsize == sizeof(connections_data)))
00391                 print_crec(the_tdb, key, dbuf, state);
00392         else
00393                 print_arec(the_tdb, key, dbuf, state);
00394         return 0;
00395 }
00396 
00397 static int print_crec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
00398 {
00399         print_conn_key(key);
00400         print_conn_data(dbuf);
00401         return 0;
00402 }
00403 
00404 static int print_arec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
00405 {
00406         printf("\nkey %d bytes\n", (int)key.dsize);
00407         print_asc(key.dptr, key.dsize);
00408         printf("\ndata %d bytes\n", (int)dbuf.dsize);
00409         print_data(dbuf.dptr, dbuf.dsize);
00410         return 0;
00411 }
00412 
00413 static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
00414 {
00415         printf("key %d bytes: ", (int)key.dsize);
00416         print_asc(key.dptr, key.dsize);
00417         printf("\n");
00418         return 0;
00419 }
00420 
00421 static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
00422 {
00423         printf("key %d bytes\n", (int)key.dsize);
00424         print_data(key.dptr, key.dsize);
00425         printf("\n");
00426         return 0;
00427 }
00428 
00429 static int total_bytes;
00430 
00431 static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
00432 {
00433         total_bytes += dbuf.dsize;
00434         return 0;
00435 }
00436 
00437 static void info_tdb(void)
00438 {
00439         int count;
00440         total_bytes = 0;
00441         if ((count = tdb_traverse(tdb, traverse_fn, NULL)) == -1)
00442                 printf("Error = %s\n", tdb_errorstr(tdb));
00443         else
00444                 printf("%d records totalling %d bytes\n", count, total_bytes);
00445 }
00446 
00447 static char *tdb_getline(const char *prompt)
00448 {
00449         static char thisline[1024];
00450         char *p;
00451         fputs(prompt, stdout);
00452         thisline[0] = 0;
00453         p = fgets(thisline, sizeof(thisline)-1, stdin);
00454         if (p) p = strchr(p, '\n');
00455         if (p) *p = 0;
00456         return p?thisline:NULL;
00457 }
00458 
00459 static int do_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf,
00460                      void *state)
00461 {
00462     return tdb_delete(the_tdb, key);
00463 }
00464 
00465 static void first_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey)
00466 {
00467         TDB_DATA dbuf;
00468         *pkey = tdb_firstkey(the_tdb);
00469         
00470         dbuf = tdb_fetch(the_tdb, *pkey);
00471         if (!dbuf.dptr) terror("fetch failed");
00472         else {
00473                 print_rec(the_tdb, *pkey, dbuf, NULL);
00474         }
00475 }
00476 
00477 static void next_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey)
00478 {
00479         TDB_DATA dbuf;
00480         *pkey = tdb_nextkey(the_tdb, *pkey);
00481         
00482         dbuf = tdb_fetch(the_tdb, *pkey);
00483         if (!dbuf.dptr) 
00484                 terror("fetch failed");
00485         else
00486                 print_rec(the_tdb, *pkey, dbuf, NULL);
00487 }
00488 
00489 static int do_command(void)
00490 {
00491         COMMAND_TABLE *ctp = cmd_table;
00492         enum commands mycmd = CMD_HELP;
00493         int cmd_len;
00494 
00495         do_connections = 0;
00496 
00497         if (cmdname && strlen(cmdname) == 0) {
00498             mycmd = CMD_NEXT;
00499         } else {
00500             while (ctp->name) {
00501                 cmd_len = strlen(ctp->name);
00502                 if (strncmp(ctp->name,cmdname,cmd_len) == 0) {
00503                         mycmd = ctp->cmd;
00504                         break;
00505                 }
00506                 ctp++;
00507             }
00508         }
00509 
00510         switch (mycmd) {
00511         case CMD_CREATE_TDB:
00512             bIterate = 0;
00513             create_tdb(arg1);
00514             return 0;
00515         case CMD_OPEN_TDB:
00516             bIterate = 0;
00517             open_tdb(arg1);
00518             return 0;
00519         case CMD_SYSTEM:
00520             /* Shell command */
00521             system(arg1);
00522             return 0;
00523         case CMD_QUIT:
00524             return 1;
00525         default:
00526             /* all the rest require a open database */
00527             if (!tdb) {
00528                 bIterate = 0;
00529                 terror("database not open");
00530                 help();
00531                 return 0;
00532             }
00533             switch (mycmd) {
00534             case CMD_ERASE:
00535                 bIterate = 0;
00536                 tdb_traverse(tdb, do_delete_fn, NULL);
00537                 return 0;
00538             case CMD_DUMP:
00539                 bIterate = 0;
00540                 tdb_traverse(tdb, print_rec, NULL);
00541                 return 0;
00542             case CMD_CDUMP:
00543                 do_connections = 1;
00544                 bIterate = 0;
00545                 tdb_traverse(tdb, print_rec, NULL);
00546                 return 0;
00547             case CMD_INSERT:
00548                 bIterate = 0;
00549                 insert_tdb(arg1, arg1len,arg2,arg2len);
00550                 return 0;
00551             case CMD_MOVE:
00552                 bIterate = 0;
00553                 move_rec(arg1,arg1len,arg2);
00554                 return 0;
00555             case CMD_STORE:
00556                 bIterate = 0;
00557                 store_tdb(arg1,arg1len,arg2,arg2len);
00558                 return 0;
00559             case CMD_SHOW:
00560                 bIterate = 0;
00561                 show_tdb(arg1, arg1len);
00562                 return 0;
00563             case CMD_KEYS:
00564                 tdb_traverse(tdb, print_key, NULL);
00565                 return 0;
00566             case CMD_HEXKEYS:
00567                 tdb_traverse(tdb, print_hexkey, NULL);
00568                 return 0;
00569             case CMD_DELETE:
00570                 bIterate = 0;
00571                 delete_tdb(arg1,arg1len);
00572                 return 0;
00573             case CMD_LIST_HASH_FREE:
00574                 tdb_dump_all(tdb);
00575                 return 0;
00576             case CMD_LIST_FREE:
00577                 tdb_printfreelist(tdb);
00578                 return 0;
00579             case CMD_INFO:
00580                 info_tdb();
00581                 return 0;
00582             case CMD_FIRST:
00583                 bIterate = 1;
00584                 first_record(tdb, &iterate_kbuf);
00585                 return 0;
00586             case CMD_NEXT:
00587                if (bIterate)
00588                   next_record(tdb, &iterate_kbuf);
00589                 return 0;
00590             case CMD_HELP:
00591                 help();
00592                 return 0;
00593             case CMD_CREATE_TDB:
00594             case CMD_OPEN_TDB:
00595             case CMD_SYSTEM:
00596             case CMD_QUIT:
00597                 /*
00598                  * unhandled commands.  cases included here to avoid compiler
00599                  * warnings.
00600                  */
00601                 return 0;
00602             }
00603         }
00604 
00605         return 0;
00606 }
00607 
00608 static char *convert_string(char *instring, size_t *sizep)
00609 {
00610     size_t length = 0;
00611     char *outp, *inp;
00612     char temp[3];
00613     
00614 
00615     outp = inp = instring;
00616 
00617     while (*inp) {
00618         if (*inp == '\\') {
00619             inp++;
00620             if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) {
00621                 temp[0] = *inp++;
00622                 temp[1] = '\0';
00623                 if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) {
00624                     temp[1] = *inp++;
00625                     temp[2] = '\0';
00626                 }
00627                 *outp++ = (char)strtol((const char *)temp,NULL,16);
00628             } else {
00629                 *outp++ = *inp++;
00630             }
00631         } else {
00632             *outp++ = *inp++;
00633         }
00634         length++;
00635     }
00636     *sizep = length;
00637     return instring;
00638 }
00639 
00640 int main(int argc, char *argv[])
00641 {
00642     cmdname = (char *) "";
00643     arg1 = NULL;
00644     arg1len = 0;
00645     arg2 = NULL;
00646     arg2len = 0;
00647 
00648     if (argv[1]) {
00649         cmdname = (char *) "open";
00650         arg1 = argv[1];
00651         do_command();
00652         cmdname = (char *) "";
00653         arg1 = NULL;
00654     }
00655 
00656     switch (argc) {
00657         case 1:
00658         case 2:
00659             /* Interactive mode */
00660             while ((cmdname = tdb_getline("tdb> "))) {
00661                 arg2 = arg1 = NULL;
00662                 if ((arg1 = strchr((const char *)cmdname,' ')) != NULL) {
00663                     arg1++;
00664                     arg2 = arg1;
00665                     while (*arg2) {
00666                         if (*arg2 == ' ') {
00667                             *arg2++ = '\0';
00668                             break;
00669                         }
00670                         if ((*arg2++ == '\\') && (*arg2 == ' ')) {
00671                             arg2++;
00672                         }
00673                     }
00674                 }
00675                 if (arg1) arg1 = convert_string(arg1,&arg1len);
00676                 if (arg2) arg2 = convert_string(arg2,&arg2len);
00677                 if (do_command()) break;
00678             }
00679             break;
00680         case 5:
00681             arg2 = convert_string(argv[4],&arg2len);
00682         case 4:
00683             arg1 = convert_string(argv[3],&arg1len);
00684         case 3:
00685             cmdname = argv[2];
00686         default:
00687             do_command();
00688             break;
00689     }
00690 
00691     if (tdb) tdb_close(tdb);
00692 
00693     return 0;
00694 }

Sambaに対してSat Aug 29 21:23:27 2009に生成されました。  doxygen 1.4.7