tdbtool.c 17 KB

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