LCOV - code coverage report
Current view: top level - lib/tdb/tools - tdbtool.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 107 489 21.9 %
Date: 2024-05-31 13:13:24 Functions: 9 32 28.1 %

          Line data    Source code
       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 3 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, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "replace.h"
      24             : #include "system/locale.h"
      25             : #include "system/time.h"
      26             : #include "system/filesys.h"
      27             : #include "system/wait.h"
      28             : #include "tdb.h"
      29             : 
      30             : static int do_command(void);
      31             : const char *cmdname;
      32             : char *arg1, *arg2;
      33             : size_t arg1len, arg2len;
      34             : int bIterate = 0;
      35             : char *line;
      36             : TDB_DATA iterate_kbuf;
      37             : char cmdline[1024];
      38             : static int disable_mmap;
      39             : static int _disable_lock;
      40             : 
      41             : enum commands {
      42             :         CMD_CREATE_TDB,
      43             :         CMD_OPEN_TDB,
      44             :         CMD_TRANSACTION_START,
      45             :         CMD_TRANSACTION_COMMIT,
      46             :         CMD_TRANSACTION_CANCEL,
      47             :         CMD_ERASE,
      48             :         CMD_DUMP,
      49             :         CMD_INSERT,
      50             :         CMD_MOVE,
      51             :         CMD_STOREHEX,
      52             :         CMD_STORE,
      53             :         CMD_SHOW,
      54             :         CMD_KEYS,
      55             :         CMD_HEXKEYS,
      56             :         CMD_DELETE,
      57             :         CMD_LIST_HASH_FREE,
      58             :         CMD_LIST_FREE,
      59             :         CMD_FREELIST_SIZE,
      60             :         CMD_INFO,
      61             :         CMD_MMAP,
      62             :         CMD_SPEED,
      63             :         CMD_FIRST,
      64             :         CMD_NEXT,
      65             :         CMD_SYSTEM,
      66             :         CMD_CHECK,
      67             :         CMD_REPACK,
      68             :         CMD_QUIT,
      69             :         CMD_HELP
      70             : };
      71             : 
      72             : typedef struct {
      73             :         const char *name;
      74             :         enum commands cmd;
      75             : } COMMAND_TABLE;
      76             : 
      77             : COMMAND_TABLE cmd_table[] = {
      78             :         {"create",    CMD_CREATE_TDB},
      79             :         {"open",      CMD_OPEN_TDB},
      80             :         {"transaction_start", CMD_TRANSACTION_START},
      81             :         {"transaction_commit",        CMD_TRANSACTION_COMMIT},
      82             :         {"transaction_cancel",        CMD_TRANSACTION_CANCEL},
      83             :         {"erase",     CMD_ERASE},
      84             :         {"dump",      CMD_DUMP},
      85             :         {"insert",    CMD_INSERT},
      86             :         {"move",      CMD_MOVE},
      87             :         {"storehex",  CMD_STOREHEX},
      88             :         {"store",     CMD_STORE},
      89             :         {"show",      CMD_SHOW},
      90             :         {"keys",      CMD_KEYS},
      91             :         {"hexkeys",   CMD_HEXKEYS},
      92             :         {"delete",    CMD_DELETE},
      93             :         {"list",      CMD_LIST_HASH_FREE},
      94             :         {"free",      CMD_LIST_FREE},
      95             :         {"freelist_size",     CMD_FREELIST_SIZE},
      96             :         {"info",      CMD_INFO},
      97             :         {"speed",     CMD_SPEED},
      98             :         {"mmap",      CMD_MMAP},
      99             :         {"first",     CMD_FIRST},
     100             :         {"1",         CMD_FIRST},
     101             :         {"next",      CMD_NEXT},
     102             :         {"n",         CMD_NEXT},
     103             :         {"check",     CMD_CHECK},
     104             :         {"quit",      CMD_QUIT},
     105             :         {"q",         CMD_QUIT},
     106             :         {"!",         CMD_SYSTEM},
     107             :         {"repack",    CMD_REPACK},
     108             :         {NULL,          CMD_HELP}
     109             : };
     110             : 
     111             : struct timeval tp1,tp2;
     112             : 
     113           0 : static void _start_timer(void)
     114             : {
     115           0 :         gettimeofday(&tp1,NULL);
     116           0 : }
     117             : 
     118           0 : static double _end_timer(void)
     119             : {
     120           0 :         gettimeofday(&tp2,NULL);
     121           0 :         return((tp2.tv_sec - tp1.tv_sec) +
     122           0 :                (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
     123             : }
     124             : 
     125             : #ifdef PRINTF_ATTRIBUTE
     126             : static void tdb_log_open(struct tdb_context *tdb, enum tdb_debug_level level,
     127             :                          const char *format, ...) PRINTF_ATTRIBUTE(3,4);
     128             : #endif
     129           4 : static void tdb_log_open(struct tdb_context *tdb, enum tdb_debug_level level,
     130             :                          const char *format, ...)
     131             : {
     132           4 :         const char *mutex_msg =
     133             :                 "Can use mutexes only with MUTEX_LOCKING or NOLOCK\n";
     134             :         char *p;
     135             :         va_list ap;
     136             : 
     137           4 :         p = strstr(format, mutex_msg);
     138           4 :         if (p != NULL) {
     139             :                 /*
     140             :                  * Yes, this is a hack, but we don't want to see this
     141             :                  * message on first open, but we want to see
     142             :                  * everything else.
     143             :                  */
     144           4 :                 return;
     145             :         }
     146             : 
     147           0 :         va_start(ap, format);
     148           0 :         vfprintf(stderr, format, ap);
     149           0 :         va_end(ap);
     150             : }
     151             : 
     152             : #ifdef PRINTF_ATTRIBUTE
     153             : static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...) PRINTF_ATTRIBUTE(3,4);
     154             : #endif
     155           0 : static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...)
     156             : {
     157             :         va_list ap;
     158             : 
     159           0 :         va_start(ap, format);
     160           0 :         vfprintf(stderr, format, ap);
     161           0 :         va_end(ap);
     162           0 : }
     163             : 
     164             : /* a tdb tool for manipulating a tdb database */
     165             : 
     166             : static TDB_CONTEXT *tdb;
     167             : 
     168             : static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
     169             : static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
     170             : static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
     171             : 
     172          12 : static void print_asc(const char *buf,int len)
     173             : {
     174             :         int i;
     175             : 
     176             :         /* We're probably printing ASCII strings so don't try to display
     177             :            the trailing NULL character. */
     178             : 
     179          12 :         if (buf[len - 1] == 0)
     180          12 :                 len--;
     181             : 
     182          96 :         for (i=0;i<len;i++)
     183          84 :                 printf("%c",isprint(buf[i])?buf[i]:'.');
     184          12 : }
     185             : 
     186           4 : static void print_data(const char *buf,int len)
     187             : {
     188           4 :         int i=0;
     189           4 :         if (len<=0) return;
     190           4 :         printf("[%03X] ",i);
     191         100 :         for (i=0;i<len;) {
     192          96 :                 printf("%02X ",(int)((unsigned char)buf[i]));
     193          96 :                 i++;
     194          96 :                 if (i%8 == 0) printf(" ");
     195          96 :                 if (i%16 == 0) {
     196           4 :                         print_asc(&buf[i-16],8); printf(" ");
     197           4 :                         print_asc(&buf[i-8],8); printf("\n");
     198           4 :                         if (i<len) printf("[%03X] ",i);
     199             :                 }
     200             :         }
     201           4 :         if (i%16) {
     202             :                 int n;
     203             : 
     204           4 :                 n = 16 - (i%16);
     205           4 :                 printf(" ");
     206           4 :                 if (n>8) printf(" ");
     207          36 :                 while (n--) printf("   ");
     208             : 
     209           4 :                 n = i%16;
     210           4 :                 if (n > 8) n = 8;
     211           4 :                 print_asc(&buf[i-(i%16)],n); printf(" ");
     212           4 :                 n = (i%16) - n;
     213           4 :                 if (n>0) print_asc(&buf[i-n],n);
     214           4 :                 printf("\n");
     215             :         }
     216             : }
     217             : 
     218           0 : static void help(void)
     219             : {
     220           0 :         printf("\n"
     221             : "tdbtool: \n"
     222             : "  create    dbname     : create a database\n"
     223             : "  open      dbname     : open an existing database\n"
     224             : "  transaction_start    : start a transaction\n"
     225             : "  transaction_commit   : commit a transaction\n"
     226             : "  transaction_cancel   : cancel a transaction\n"
     227             : "  erase                : erase the database\n"
     228             : "  dump                 : dump the database as strings\n"
     229             : "  keys                 : dump the database keys as strings\n"
     230             : "  hexkeys              : dump the database keys as hex values\n"
     231             : "  info                 : print summary info about the database\n"
     232             : "  insert    key  data  : insert a record\n"
     233             : "  move      key  file  : move a record to a destination tdb\n"
     234             : "  storehex  key  data  : store a record (replace), key/value in hex format\n"
     235             : "  store     key  data  : store a record (replace)\n"
     236             : "  show      key        : show a record by key\n"
     237             : "  delete    key        : delete a record by key\n"
     238             : "  list                 : print the database hash table and freelist\n"
     239             : "  free                 : print the database freelist\n"
     240             : "  freelist_size        : print the number of records in the freelist\n"
     241             : "  check                : check the integrity of an opened database\n"
     242             : "  repack               : repack the database\n"
     243             : "  speed                : perform speed tests on the database\n"
     244             : "  ! command            : execute system command\n"
     245             : "  1 | first            : print the first record\n"
     246             : "  n | next             : print the next record\n"
     247             : "  q | quit             : terminate\n"
     248             : "  \\n                   : repeat 'next' command\n"
     249             : "\n");
     250           0 : }
     251             : 
     252           2 : static void terror(const char *why)
     253             : {
     254           2 :         printf("%s\n", why);
     255           2 : }
     256             : 
     257           0 : static void create_tdb(const char *tdbname)
     258             : {
     259           0 :         struct tdb_logging_context log_ctx = { NULL, NULL};
     260           0 :         log_ctx.log_fn = tdb_log;
     261             : 
     262           0 :         if (tdb) tdb_close(tdb);
     263           0 :         tdb = tdb_open_ex(tdbname, 0,
     264           0 :                           TDB_CLEAR_IF_FIRST |
     265           0 :                           (disable_mmap?TDB_NOMMAP:0) |
     266           0 :                           (_disable_lock?TDB_NOLOCK:0),
     267             :                           O_RDWR | O_CREAT | O_TRUNC, 0600, &log_ctx, NULL);
     268           0 :         if (!tdb) {
     269           0 :                 printf("Could not create %s: %s\n", tdbname, strerror(errno));
     270             :         }
     271           0 : }
     272             : 
     273           6 : static void open_tdb(const char *tdbname)
     274             : {
     275           6 :         struct tdb_logging_context log_ctx = { NULL, NULL };
     276           6 :         log_ctx.log_fn = tdb_log_open;
     277             : 
     278           6 :         if (tdb) tdb_close(tdb);
     279           6 :         tdb = tdb_open_ex(tdbname, 0,
     280           6 :                           (disable_mmap?TDB_NOMMAP:0) |
     281           6 :                           (_disable_lock?TDB_NOLOCK:0),
     282             :                           O_RDWR, 0600,
     283             :                           &log_ctx, NULL);
     284             : 
     285           6 :         log_ctx.log_fn = tdb_log;
     286           6 :         if (tdb != NULL) {
     287           2 :                 tdb_set_logging_function(tdb, &log_ctx);
     288             :         }
     289             : 
     290           6 :         if ((tdb == NULL) && (errno == EINVAL)) {
     291             :                 /*
     292             :                  * Retry NOLOCK and readonly. There we want to see all
     293             :                  * error messages.
     294             :                  */
     295           4 :                 tdb = tdb_open_ex(tdbname, 0,
     296           4 :                                   (disable_mmap?TDB_NOMMAP:0) |TDB_NOLOCK,
     297             :                                   O_RDONLY, 0600,
     298             :                                   &log_ctx, NULL);
     299             :         }
     300             : 
     301           6 :         if (!tdb) {
     302           0 :                 printf("Could not open %s: %s\n", tdbname, strerror(errno));
     303             :         }
     304           6 : }
     305             : 
     306           0 : static void insert_tdb(char *keyname, size_t keylen, char* data, size_t datalen)
     307             : {
     308             :         TDB_DATA key, dbuf;
     309             : 
     310           0 :         if ((keyname == NULL) || (keylen == 0)) {
     311           0 :                 terror("need key");
     312           0 :                 return;
     313             :         }
     314             : 
     315           0 :         key.dptr = (unsigned char *)keyname;
     316           0 :         key.dsize = keylen;
     317           0 :         dbuf.dptr = (unsigned char *)data;
     318           0 :         dbuf.dsize = datalen;
     319             : 
     320           0 :         if (tdb_store(tdb, key, dbuf, TDB_INSERT) != 0) {
     321           0 :                 terror("insert failed");
     322             :         }
     323             : }
     324             : 
     325           0 : static void store_tdb(char *keyname, size_t keylen, char* data, size_t datalen)
     326             : {
     327             :         TDB_DATA key, dbuf;
     328             : 
     329           0 :         if ((keyname == NULL) || (keylen == 0)) {
     330           0 :                 terror("need key");
     331           0 :                 return;
     332             :         }
     333             : 
     334           0 :         if ((data == NULL) || (datalen == 0)) {
     335           0 :                 terror("need data");
     336           0 :                 return;
     337             :         }
     338             : 
     339           0 :         key.dptr = (unsigned char *)keyname;
     340           0 :         key.dsize = keylen;
     341           0 :         dbuf.dptr = (unsigned char *)data;
     342           0 :         dbuf.dsize = datalen;
     343             : 
     344           0 :         printf("Storing key:\n");
     345           0 :         print_rec(tdb, key, dbuf, NULL);
     346             : 
     347           0 :         if (tdb_store(tdb, key, dbuf, TDB_REPLACE) != 0) {
     348           0 :                 terror("store failed");
     349             :         }
     350             : }
     351             : 
     352           0 : static bool parse_hex(const char *src, size_t srclen, uint8_t *dst)
     353             : {
     354           0 :         size_t i=0;
     355             : 
     356           0 :         if ((srclen % 2) != 0) {
     357           0 :                 return false;
     358             :         }
     359             : 
     360           0 :         while (i<srclen) {
     361           0 :                 bool ok = hex_byte(src, dst);
     362           0 :                 if (!ok) {
     363           0 :                         return false;
     364             :                 }
     365           0 :                 src += 2;
     366           0 :                 dst += 1;
     367             :         }
     368             : 
     369           0 :         return true;
     370             : }
     371             : 
     372           0 : static void store_hex_tdb(char *keystr, size_t keylen,
     373             :                           char *datastr, size_t datalen)
     374             : {
     375           0 :         if ((keystr == NULL) || (keylen == 0)) {
     376           0 :                 terror("need key");
     377           0 :                 return;
     378             :         }
     379           0 :         if ((datastr == NULL) || (datalen == 0)) {
     380           0 :                 terror("need data");
     381           0 :                 return;
     382             :         }
     383             : 
     384           0 :         {
     385           0 :                 uint8_t keybuf[keylen/2];
     386           0 :                 TDB_DATA key = { .dptr = keybuf, .dsize = sizeof(keybuf) };
     387           0 :                 uint8_t databuf[datalen/2];
     388           0 :                 TDB_DATA data = { .dptr = databuf, .dsize = sizeof(databuf) };
     389             :                 bool ok;
     390             : 
     391           0 :                 ok = parse_hex(keystr, keylen, keybuf);
     392           0 :                 if (!ok) {
     393           0 :                         terror("need hex key");
     394           0 :                         return;
     395             :                 }
     396           0 :                 ok = parse_hex(datastr, datalen, databuf);
     397           0 :                 if (!ok) {
     398           0 :                         terror("need hex data");
     399           0 :                         return;
     400             :                 }
     401             : 
     402           0 :                 printf("storing key/data:\n");
     403           0 :                 print_data((char *)key.dptr, key.dsize);
     404           0 :                 print_data((char *)data.dptr, data.dsize);
     405             : 
     406           0 :                 if (tdb_store(tdb, key, data, TDB_REPLACE) != 0) {
     407           0 :                         terror("store failed");
     408             :                 }
     409             :         }
     410             : }
     411             : 
     412           0 : static void show_tdb(char *keyname, size_t keylen)
     413             : {
     414             :         TDB_DATA key, dbuf;
     415             : 
     416           0 :         if ((keyname == NULL) || (keylen == 0)) {
     417           0 :                 terror("need key");
     418           0 :                 return;
     419             :         }
     420             : 
     421           0 :         key.dptr = (unsigned char *)keyname;
     422           0 :         key.dsize = keylen;
     423             : 
     424           0 :         dbuf = tdb_fetch(tdb, key);
     425           0 :         if (!dbuf.dptr) {
     426           0 :             terror("fetch failed");
     427           0 :             return;
     428             :         }
     429             : 
     430           0 :         print_rec(tdb, key, dbuf, NULL);
     431             : 
     432           0 :         free( dbuf.dptr );
     433             : 
     434           0 :         return;
     435             : }
     436             : 
     437           2 : static void delete_tdb(char *keyname, size_t keylen)
     438             : {
     439             :         TDB_DATA key;
     440             : 
     441           2 :         if ((keyname == NULL) || (keylen == 0)) {
     442           2 :                 terror("need key");
     443           2 :                 return;
     444             :         }
     445             : 
     446           0 :         key.dptr = (unsigned char *)keyname;
     447           0 :         key.dsize = keylen;
     448             : 
     449           0 :         if (tdb_delete(tdb, key) != 0) {
     450           0 :                 terror("delete failed");
     451             :         }
     452             : }
     453             : 
     454           0 : static void move_rec(char *keyname, size_t keylen, char* tdbname)
     455             : {
     456             :         TDB_DATA key, dbuf;
     457             :         TDB_CONTEXT *dst_tdb;
     458             : 
     459           0 :         if ((keyname == NULL) || (keylen == 0)) {
     460           0 :                 terror("need key");
     461           0 :                 return;
     462             :         }
     463             : 
     464           0 :         if ( !tdbname ) {
     465           0 :                 terror("need destination tdb name");
     466           0 :                 return;
     467             :         }
     468             : 
     469           0 :         key.dptr = (unsigned char *)keyname;
     470           0 :         key.dsize = keylen;
     471             : 
     472           0 :         dbuf = tdb_fetch(tdb, key);
     473           0 :         if (!dbuf.dptr) {
     474           0 :                 terror("fetch failed");
     475           0 :                 return;
     476             :         }
     477             : 
     478           0 :         print_rec(tdb, key, dbuf, NULL);
     479             : 
     480           0 :         dst_tdb = tdb_open(tdbname, 0, 0, O_RDWR, 0600);
     481           0 :         if ( !dst_tdb ) {
     482           0 :                 terror("unable to open destination tdb");
     483           0 :                 return;
     484             :         }
     485             : 
     486           0 :         if (tdb_store( dst_tdb, key, dbuf, TDB_REPLACE ) != 0) {
     487           0 :                 terror("failed to move record");
     488             :         }
     489             :         else
     490           0 :                 printf("record moved\n");
     491             : 
     492           0 :         tdb_close( dst_tdb );
     493             : 
     494           0 :         return;
     495             : }
     496             : 
     497           0 : static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
     498             : {
     499           0 :         printf("\nkey %d bytes\n", (int)key.dsize);
     500           0 :         print_asc((const char *)key.dptr, key.dsize);
     501           0 :         printf("\ndata %d bytes\n", (int)dbuf.dsize);
     502           0 :         print_data((const char *)dbuf.dptr, dbuf.dsize);
     503           0 :         return 0;
     504             : }
     505             : 
     506           0 : static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
     507             : {
     508           0 :         printf("key %d bytes: ", (int)key.dsize);
     509           0 :         print_asc((const char *)key.dptr, key.dsize);
     510           0 :         printf("\n");
     511           0 :         return 0;
     512             : }
     513             : 
     514           4 : static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
     515             : {
     516           4 :         printf("key %d bytes\n", (int)key.dsize);
     517           4 :         print_data((const char *)key.dptr, key.dsize);
     518           4 :         printf("\n");
     519           4 :         return 0;
     520             : }
     521             : 
     522             : static int total_bytes;
     523             : 
     524           0 : static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
     525             : {
     526           0 :         total_bytes += dbuf.dsize;
     527           0 :         return 0;
     528             : }
     529             : 
     530           0 : static void info_tdb(void)
     531             : {
     532           0 :         char *summary = tdb_summary(tdb);
     533             : 
     534           0 :         if (!summary) {
     535           0 :                 printf("Error = %s\n", tdb_errorstr(tdb));
     536             :         } else {
     537           0 :                 printf("%s", summary);
     538           0 :                 free(summary);
     539             :         }
     540           0 : }
     541             : 
     542           0 : static void speed_tdb(const char *tlimit)
     543             : {
     544           0 :         const char *str = "store test", *str2 = "transaction test";
     545           0 :         unsigned timelimit = tlimit?atoi(tlimit):0;
     546             :         double t;
     547             :         int ops;
     548           0 :         if (timelimit == 0) timelimit = 5;
     549             : 
     550           0 :         ops = 0;
     551           0 :         printf("Testing store speed for %u seconds\n", timelimit);
     552           0 :         _start_timer();
     553             :         do {
     554           0 :                 long int r = random();
     555             :                 TDB_DATA key, dbuf;
     556           0 :                 key.dptr = discard_const_p(uint8_t, str);
     557           0 :                 key.dsize = strlen((char *)key.dptr);
     558           0 :                 dbuf.dptr = (uint8_t *) &r;
     559           0 :                 dbuf.dsize = sizeof(r);
     560           0 :                 tdb_store(tdb, key, dbuf, TDB_REPLACE);
     561           0 :                 t = _end_timer();
     562           0 :                 ops++;
     563           0 :         } while (t < timelimit);
     564           0 :         printf("%10.3f ops/sec\n", ops/t);
     565             : 
     566           0 :         ops = 0;
     567           0 :         printf("Testing fetch speed for %u seconds\n", timelimit);
     568           0 :         _start_timer();
     569             :         do {
     570             :                 TDB_DATA key;
     571           0 :                 key.dptr = discard_const_p(uint8_t, str);
     572           0 :                 key.dsize = strlen((char *)key.dptr);
     573           0 :                 tdb_fetch(tdb, key);
     574           0 :                 t = _end_timer();
     575           0 :                 ops++;
     576           0 :         } while (t < timelimit);
     577           0 :         printf("%10.3f ops/sec\n", ops/t);
     578             : 
     579           0 :         ops = 0;
     580           0 :         printf("Testing transaction speed for %u seconds\n", timelimit);
     581           0 :         _start_timer();
     582             :         do {
     583           0 :                 long int r = random();
     584             :                 TDB_DATA key, dbuf;
     585           0 :                 key.dptr = discard_const_p(uint8_t, str2);
     586           0 :                 key.dsize = strlen((char *)key.dptr);
     587           0 :                 dbuf.dptr = (uint8_t *) &r;
     588           0 :                 dbuf.dsize = sizeof(r);
     589           0 :                 tdb_transaction_start(tdb);
     590           0 :                 tdb_store(tdb, key, dbuf, TDB_REPLACE);
     591           0 :                 tdb_transaction_commit(tdb);
     592           0 :                 t = _end_timer();
     593           0 :                 ops++;
     594           0 :         } while (t < timelimit);
     595           0 :         printf("%10.3f ops/sec\n", ops/t);
     596             : 
     597           0 :         ops = 0;
     598           0 :         printf("Testing traverse speed for %u seconds\n", timelimit);
     599           0 :         _start_timer();
     600             :         do {
     601           0 :                 tdb_traverse(tdb, traverse_fn, NULL);
     602           0 :                 t = _end_timer();
     603           0 :                 ops++;
     604           0 :         } while (t < timelimit);
     605           0 :         printf("%10.3f ops/sec\n", ops/t);
     606           0 : }
     607             : 
     608           0 : static void toggle_mmap(void)
     609             : {
     610           0 :         disable_mmap = !disable_mmap;
     611           0 :         if (disable_mmap) {
     612           0 :                 printf("mmap is disabled\n");
     613             :         } else {
     614           0 :                 printf("mmap is enabled\n");
     615             :         }
     616           0 : }
     617             : 
     618           0 : static char *tdb_getline(const char *prompt)
     619             : {
     620             :         static char thisline[1024];
     621             :         char *p;
     622           0 :         fputs(prompt, stdout);
     623           0 :         thisline[0] = 0;
     624           0 :         p = fgets(thisline, sizeof(thisline)-1, stdin);
     625           0 :         if (p) p = strchr(p, '\n');
     626           0 :         if (p) *p = 0;
     627           0 :         return p?thisline:NULL;
     628             : }
     629             : 
     630           0 : static void first_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey)
     631             : {
     632             :         TDB_DATA dbuf;
     633           0 :         *pkey = tdb_firstkey(the_tdb);
     634             : 
     635           0 :         dbuf = tdb_fetch(the_tdb, *pkey);
     636           0 :         if (!dbuf.dptr) terror("fetch failed");
     637             :         else {
     638           0 :                 print_rec(the_tdb, *pkey, dbuf, NULL);
     639             :         }
     640           0 : }
     641             : 
     642           0 : static void next_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey)
     643             : {
     644             :         TDB_DATA dbuf;
     645           0 :         *pkey = tdb_nextkey(the_tdb, *pkey);
     646             : 
     647           0 :         dbuf = tdb_fetch(the_tdb, *pkey);
     648           0 :         if (!dbuf.dptr)
     649           0 :                 terror("fetch failed");
     650             :         else
     651           0 :                 print_rec(the_tdb, *pkey, dbuf, NULL);
     652           0 : }
     653             : 
     654           0 : static int count(TDB_DATA key, TDB_DATA data, void *private_data)
     655             : {
     656           0 :         (*(unsigned int *)private_data)++;
     657           0 :         return 0;
     658             : }
     659             : 
     660           0 : static void check_db(TDB_CONTEXT *the_tdb)
     661             : {
     662           0 :         int tdbcount = 0;
     663           0 :         if (!the_tdb)
     664           0 :                 printf("Error: No database opened!\n");
     665           0 :         else if (tdb_check(the_tdb, count, &tdbcount) == -1)
     666           0 :                 printf("Integrity check for the opened database failed.\n");
     667             :         else
     668           0 :                 printf("Database integrity is OK and has %d records.\n",
     669             :                        tdbcount);
     670           0 : }
     671             : 
     672          12 : static int do_command(void)
     673             : {
     674          12 :         COMMAND_TABLE *ctp = cmd_table;
     675          12 :         enum commands mycmd = CMD_HELP;
     676             :         int cmd_len;
     677             : 
     678          12 :         if (cmdname != NULL) {
     679          12 :                 if (strlen(cmdname) == 0) {
     680           0 :                         mycmd = CMD_NEXT;
     681             :                 } else {
     682          98 :                         while (ctp->name) {
     683          98 :                                 cmd_len = strlen(ctp->name);
     684          98 :                                 if (strncmp(ctp->name,cmdname,cmd_len) == 0) {
     685          12 :                                         mycmd = ctp->cmd;
     686          12 :                                         break;
     687             :                                 }
     688          86 :                                 ctp++;
     689             :                         }
     690             :                 }
     691             :         }
     692             : 
     693          12 :         switch (mycmd) {
     694           0 :         case CMD_CREATE_TDB:
     695           0 :                 bIterate = 0;
     696           0 :                 create_tdb(arg1);
     697           0 :                 return 0;
     698           6 :         case CMD_OPEN_TDB:
     699           6 :                 bIterate = 0;
     700           6 :                 open_tdb(arg1);
     701           6 :                 return 0;
     702           0 :         case CMD_SYSTEM:
     703             :                 /* Shell command */
     704           0 :                 if (system(arg1) == -1) {
     705           0 :                         terror("system() call failed\n");
     706             :                 }
     707           0 :                 return 0;
     708           0 :         case CMD_QUIT:
     709           0 :                 return 1;
     710           6 :         default:
     711             :                 /* all the rest require a open database */
     712           6 :                 if (!tdb) {
     713           0 :                         bIterate = 0;
     714           0 :                         terror("database not open");
     715           0 :                         help();
     716           0 :                         return 0;
     717             :                 }
     718             :                 switch (mycmd) {
     719           0 :                 case CMD_TRANSACTION_START:
     720           0 :                         bIterate = 0;
     721           0 :                         tdb_transaction_start(tdb);
     722           0 :                         return 0;
     723           0 :                 case CMD_TRANSACTION_COMMIT:
     724           0 :                         bIterate = 0;
     725           0 :                         tdb_transaction_commit(tdb);
     726           0 :                         return 0;
     727           0 :                 case CMD_REPACK:
     728           0 :                         bIterate = 0;
     729           0 :                         tdb_repack(tdb);
     730           0 :                         return 0;
     731           0 :                 case CMD_TRANSACTION_CANCEL:
     732           0 :                         bIterate = 0;
     733           0 :                         tdb_transaction_cancel(tdb);
     734           0 :                         return 0;
     735           0 :                 case CMD_ERASE:
     736           0 :                         bIterate = 0;
     737           0 :                         tdb_wipe_all(tdb);
     738           0 :                         return 0;
     739           0 :                 case CMD_DUMP:
     740           0 :                         bIterate = 0;
     741           0 :                         tdb_traverse(tdb, print_rec, NULL);
     742           0 :                         return 0;
     743           0 :                 case CMD_INSERT:
     744           0 :                         bIterate = 0;
     745           0 :                         insert_tdb(arg1, arg1len,arg2,arg2len);
     746           0 :                         return 0;
     747           0 :                 case CMD_MOVE:
     748           0 :                         bIterate = 0;
     749           0 :                         move_rec(arg1,arg1len,arg2);
     750           0 :                         return 0;
     751           0 :                 case CMD_STORE:
     752           0 :                         bIterate = 0;
     753           0 :                         store_tdb(arg1,arg1len,arg2,arg2len);
     754           0 :                         return 0;
     755           0 :                 case CMD_STOREHEX:
     756           0 :                         bIterate = 0;
     757           0 :                         store_hex_tdb(arg1,arg1len,arg2,arg2len);
     758           0 :                         return 0;
     759           0 :                 case CMD_SHOW:
     760           0 :                         bIterate = 0;
     761           0 :                         show_tdb(arg1, arg1len);
     762           0 :                         return 0;
     763           0 :                 case CMD_KEYS:
     764           0 :                         tdb_traverse(tdb, print_key, NULL);
     765           0 :                         return 0;
     766           4 :                 case CMD_HEXKEYS:
     767           4 :                         tdb_traverse(tdb, print_hexkey, NULL);
     768           4 :                         return 0;
     769           2 :                 case CMD_DELETE:
     770           2 :                         bIterate = 0;
     771           2 :                         delete_tdb(arg1,arg1len);
     772           2 :                         return 0;
     773           0 :                 case CMD_LIST_HASH_FREE:
     774           0 :                         tdb_dump_all(tdb);
     775           0 :                         return 0;
     776           0 :                 case CMD_LIST_FREE:
     777           0 :                         tdb_printfreelist(tdb);
     778           0 :                         return 0;
     779           0 :                 case CMD_FREELIST_SIZE: {
     780             :                         int size;
     781             : 
     782           0 :                         size = tdb_freelist_size(tdb);
     783           0 :                         if (size < 0) {
     784           0 :                                 printf("Error getting freelist size.\n");
     785             :                         } else {
     786           0 :                                 printf("freelist size: %d\n", size);
     787             :                         }
     788             : 
     789           0 :                         return 0;
     790             :                 }
     791           0 :                 case CMD_INFO:
     792           0 :                         info_tdb();
     793           0 :                         return 0;
     794           0 :                 case CMD_SPEED:
     795           0 :                         speed_tdb(arg1);
     796           0 :                         return 0;
     797           0 :                 case CMD_MMAP:
     798           0 :                         toggle_mmap();
     799           0 :                         return 0;
     800           0 :                 case CMD_FIRST:
     801           0 :                         bIterate = 1;
     802           0 :                         first_record(tdb, &iterate_kbuf);
     803           0 :                         return 0;
     804           0 :                 case CMD_NEXT:
     805           0 :                         if (bIterate)
     806           0 :                                 next_record(tdb, &iterate_kbuf);
     807           0 :                         return 0;
     808           0 :                 case CMD_CHECK:
     809           0 :                         check_db(tdb);
     810           0 :                         return 0;
     811           0 :                 case CMD_HELP:
     812           0 :                         help();
     813           0 :                         return 0;
     814           0 :                 case CMD_CREATE_TDB:
     815             :                 case CMD_OPEN_TDB:
     816             :                 case CMD_SYSTEM:
     817             :                 case CMD_QUIT:
     818             :                         /*
     819             :                          * unhandled commands.  cases included here to avoid compiler
     820             :                          * warnings.
     821             :                          */
     822           0 :                         return 0;
     823             :                 }
     824             :         }
     825             : 
     826           0 :         return 0;
     827             : }
     828             : 
     829           0 : static char *tdb_convert_string(char *instring, size_t *sizep)
     830             : {
     831           0 :         size_t length = 0;
     832             :         char *outp, *inp;
     833             :         char temp[3];
     834             : 
     835           0 :         outp = inp = instring;
     836             : 
     837           0 :         while (*inp) {
     838           0 :                 if (*inp == '\\') {
     839           0 :                         inp++;
     840           0 :                         if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) {
     841           0 :                                 temp[0] = *inp++;
     842           0 :                                 temp[1] = '\0';
     843           0 :                                 if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) {
     844           0 :                                         temp[1] = *inp++;
     845           0 :                                         temp[2] = '\0';
     846             :                                 }
     847           0 :                                 *outp++ = (char)strtol((const char *)temp,NULL,16);
     848             :                         } else {
     849           0 :                                 *outp++ = *inp++;
     850             :                         }
     851             :                 } else {
     852           0 :                         *outp++ = *inp++;
     853             :                 }
     854           0 :                 length++;
     855             :         }
     856           0 :         *sizep = length;
     857           0 :         return instring;
     858             : }
     859             : 
     860           6 : int main(int argc, char *argv[])
     861             : {
     862           6 :         cmdname = "";
     863           6 :         arg1 = NULL;
     864           6 :         arg1len = 0;
     865           6 :         arg2 = NULL;
     866           6 :         arg2len = 0;
     867             : 
     868           6 :         if (argv[1] && (strcmp(argv[1], "-l") == 0)) {
     869           0 :                 _disable_lock = 1;
     870           0 :                 argv[1] = argv[0];
     871           0 :                 argv += 1;
     872           0 :                 argc -= 1;
     873             :         }
     874             : 
     875           6 :         if (argv[1]) {
     876           6 :                 cmdname = "open";
     877           6 :                 arg1 = argv[1];
     878           6 :                 do_command();
     879           6 :                 cmdname =  "";
     880           6 :                 arg1 = NULL;
     881             :         }
     882             : 
     883           6 :         switch (argc) {
     884           0 :         case 1:
     885             :         case 2:
     886             :                 /* Interactive mode */
     887           0 :                 while ((cmdname = tdb_getline("tdb> "))) {
     888           0 :                         arg2 = arg1 = NULL;
     889           0 :                         if ((arg1 = strchr((const char *)cmdname,' ')) != NULL) {
     890           0 :                                 arg1++;
     891           0 :                                 arg2 = arg1;
     892           0 :                                 while (*arg2) {
     893           0 :                                         if (*arg2 == ' ') {
     894           0 :                                                 *arg2++ = '\0';
     895           0 :                                                 break;
     896             :                                         }
     897           0 :                                         if ((*arg2++ == '\\') && (*arg2 == ' ')) {
     898           0 :                                                 arg2++;
     899             :                                         }
     900             :                                 }
     901             :                         }
     902           0 :                         if (arg1) arg1 = tdb_convert_string(arg1,&arg1len);
     903           0 :                         if (arg2) arg2 = tdb_convert_string(arg2,&arg2len);
     904           0 :                         if (do_command()) break;
     905             :                 }
     906           0 :                 break;
     907           0 :         case 5:
     908           0 :                 arg2 = tdb_convert_string(argv[4],&arg2len);
     909             :                 FALL_THROUGH;
     910           0 :         case 4:
     911           0 :                 arg1 = tdb_convert_string(argv[3],&arg1len);
     912             :                 FALL_THROUGH;
     913           6 :         case 3:
     914           6 :                 cmdname = argv[2];
     915             :                 FALL_THROUGH;
     916           6 :         default:
     917           6 :                 do_command();
     918           6 :                 break;
     919             :         }
     920             : 
     921           6 :         if (tdb) tdb_close(tdb);
     922             : 
     923           6 :         return 0;
     924             : }

Generated by: LCOV version 1.14