db_dump.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:14k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1996-2002
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char copyright[] =
  10.     "Copyright (c) 1996-2002nSleepycat Software Inc.  All rights reserved.n";
  11. static const char revid[] =
  12.     "$Id: db_dump.c,v 11.80 2002/08/08 03:50:34 bostic Exp $";
  13. #endif
  14. #ifndef NO_SYSTEM_INCLUDES
  15. #include <sys/types.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <unistd.h>
  20. #endif
  21. #include "db_int.h"
  22. #include "dbinc/db_page.h"
  23. #include "dbinc/db_am.h"
  24. int  db_init __P((DB_ENV *, char *, int, u_int32_t, int *));
  25. int  dump __P((DB *, int, int));
  26. int  dump_sub __P((DB_ENV *, DB *, char *, int, int));
  27. int  is_sub __P((DB *, int *));
  28. int  main __P((int, char *[]));
  29. int  show_subs __P((DB *));
  30. int  usage __P((void));
  31. int  version_check __P((const char *));
  32. int
  33. main(argc, argv)
  34. int argc;
  35. char *argv[];
  36. {
  37. extern char *optarg;
  38. extern int optind;
  39. const char *progname = "db_dump";
  40. DB_ENV *dbenv;
  41. DB *dbp;
  42. u_int32_t cache;
  43. int ch, d_close;
  44. int e_close, exitval, keyflag, lflag, nflag, pflag, private;
  45. int ret, Rflag, rflag, resize, subs;
  46. char *dopt, *home, *passwd, *subname;
  47. if ((ret = version_check(progname)) != 0)
  48. return (ret);
  49. dbp = NULL;
  50. d_close = e_close = exitval = lflag = nflag = pflag = rflag = Rflag = 0;
  51. keyflag = 0;
  52. cache = MEGABYTE;
  53. private = 0;
  54. dopt = home = passwd = subname = NULL;
  55. while ((ch = getopt(argc, argv, "d:f:h:klNpP:rRs:V")) != EOF)
  56. switch (ch) {
  57. case 'd':
  58. dopt = optarg;
  59. break;
  60. case 'f':
  61. if (freopen(optarg, "w", stdout) == NULL) {
  62. fprintf(stderr, "%s: %s: reopen: %sn",
  63.     progname, optarg, strerror(errno));
  64. return (EXIT_FAILURE);
  65. }
  66. break;
  67. case 'h':
  68. home = optarg;
  69. break;
  70. case 'k':
  71. keyflag = 1;
  72. break;
  73. case 'l':
  74. lflag = 1;
  75. break;
  76. case 'N':
  77. nflag = 1;
  78. break;
  79. case 'P':
  80. passwd = strdup(optarg);
  81. memset(optarg, 0, strlen(optarg));
  82. if (passwd == NULL) {
  83. fprintf(stderr, "%s: strdup: %sn",
  84.     progname, strerror(errno));
  85. return (EXIT_FAILURE);
  86. }
  87. break;
  88. case 'p':
  89. pflag = 1;
  90. break;
  91. case 's':
  92. subname = optarg;
  93. break;
  94. case 'R':
  95. Rflag = 1;
  96. /* DB_AGGRESSIVE requires DB_SALVAGE */
  97. /* FALLTHROUGH */
  98. case 'r':
  99. rflag = 1;
  100. break;
  101. case 'V':
  102. printf("%sn", db_version(NULL, NULL, NULL));
  103. return (EXIT_SUCCESS);
  104. case '?':
  105. default:
  106. return (usage());
  107. }
  108. argc -= optind;
  109. argv += optind;
  110. if (argc != 1)
  111. return (usage());
  112. if (dopt != NULL && pflag) {
  113. fprintf(stderr,
  114.     "%s: the -d and -p options may not both be specifiedn",
  115.     progname);
  116. return (EXIT_FAILURE);
  117. }
  118. if (lflag && subname != NULL) {
  119. fprintf(stderr,
  120.     "%s: the -l and -s options may not both be specifiedn",
  121.     progname);
  122. return (EXIT_FAILURE);
  123. }
  124. if (keyflag && rflag) {
  125. fprintf(stderr, "%s: %s",
  126.     "the -k and -r or -R options may not both be specifiedn",
  127.     progname);
  128. return (EXIT_FAILURE);
  129. }
  130. if (subname != NULL && rflag) {
  131. fprintf(stderr, "%s: %s",
  132.     "the -s and -r or R options may not both be specifiedn",
  133.     progname);
  134. return (EXIT_FAILURE);
  135. }
  136. /* Handle possible interruptions. */
  137. __db_util_siginit();
  138. /*
  139.  * Create an environment object and initialize it for error
  140.  * reporting.
  141.  */
  142. retry: if ((ret = db_env_create(&dbenv, 0)) != 0) {
  143. fprintf(stderr,
  144.     "%s: db_env_create: %sn", progname, db_strerror(ret));
  145. goto err;
  146. }
  147. e_close = 1;
  148. dbenv->set_errfile(dbenv, stderr);
  149. dbenv->set_errpfx(dbenv, progname);
  150. if (nflag) {
  151. if ((ret = dbenv->set_flags(dbenv, DB_NOLOCKING, 1)) != 0) {
  152. dbenv->err(dbenv, ret, "set_flags: DB_NOLOCKING");
  153. goto err;
  154. }
  155. if ((ret = dbenv->set_flags(dbenv, DB_NOPANIC, 1)) != 0) {
  156. dbenv->err(dbenv, ret, "set_flags: DB_NOPANIC");
  157. goto err;
  158. }
  159. }
  160. if (passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
  161.     passwd, DB_ENCRYPT_AES)) != 0) {
  162. dbenv->err(dbenv, ret, "set_passwd");
  163. goto err;
  164. }
  165. /* Initialize the environment. */
  166. if (db_init(dbenv, home, rflag, cache, &private) != 0)
  167. goto err;
  168. /* Create the DB object and open the file. */
  169. if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
  170. dbenv->err(dbenv, ret, "db_create");
  171. goto err;
  172. }
  173. d_close = 1;
  174. /*
  175.  * If we're salvaging, don't do an open;  it might not be safe.
  176.  * Dispatch now into the salvager.
  177.  */
  178. if (rflag) {
  179. if ((ret = dbp->verify(dbp, argv[0], NULL, stdout,
  180.     DB_SALVAGE |
  181.     (Rflag ? DB_AGGRESSIVE : 0) |
  182.     (pflag ? DB_PRINTABLE : 0))) != 0)
  183. goto err;
  184. exitval = 0;
  185. goto done;
  186. }
  187. if ((ret = dbp->open(dbp, NULL,
  188.     argv[0], subname, DB_UNKNOWN, DB_RDONLY, 0)) != 0) {
  189. dbp->err(dbp, ret, "open: %s", argv[0]);
  190. goto err;
  191. }
  192. if (private != 0) {
  193. if ((ret = __db_util_cache(dbenv, dbp, &cache, &resize)) != 0)
  194. goto err;
  195. if (resize) {
  196. (void)dbp->close(dbp, 0);
  197. d_close = 0;
  198. (void)dbenv->close(dbenv, 0);
  199. e_close = 0;
  200. goto retry;
  201. }
  202. }
  203. if (dopt != NULL) {
  204. if (__db_dump(dbp, dopt, NULL)) {
  205. dbp->err(dbp, ret, "__db_dump: %s", argv[0]);
  206. goto err;
  207. }
  208. } else if (lflag) {
  209. if (is_sub(dbp, &subs))
  210. goto err;
  211. if (subs == 0) {
  212. dbp->errx(dbp,
  213.     "%s: does not contain multiple databases", argv[0]);
  214. goto err;
  215. }
  216. if (show_subs(dbp))
  217. goto err;
  218. } else {
  219. subs = 0;
  220. if (subname == NULL && is_sub(dbp, &subs))
  221. goto err;
  222. if (subs) {
  223. if (dump_sub(dbenv, dbp, argv[0], pflag, keyflag))
  224. goto err;
  225. } else
  226. if (__db_prheader(dbp, NULL, pflag, keyflag, stdout,
  227.     __db_verify_callback, NULL, 0) ||
  228.     dump(dbp, pflag, keyflag))
  229. goto err;
  230. }
  231. if (0) {
  232. err: exitval = 1;
  233. }
  234. done: if (d_close && (ret = dbp->close(dbp, 0)) != 0) {
  235. exitval = 1;
  236. dbenv->err(dbenv, ret, "close");
  237. }
  238. if (e_close && (ret = dbenv->close(dbenv, 0)) != 0) {
  239. exitval = 1;
  240. fprintf(stderr,
  241.     "%s: dbenv->close: %sn", progname, db_strerror(ret));
  242. }
  243. /* Resend any caught signal. */
  244. __db_util_sigresend();
  245. return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
  246. }
  247. /*
  248.  * db_init --
  249.  * Initialize the environment.
  250.  */
  251. int
  252. db_init(dbenv, home, is_salvage, cache, is_privatep)
  253. DB_ENV *dbenv;
  254. char *home;
  255. int is_salvage;
  256. u_int32_t cache;
  257. int *is_privatep;
  258. {
  259. int ret;
  260. /*
  261.  * Try and use the underlying environment when opening a database.
  262.  * We wish to use the buffer pool so our information is as up-to-date
  263.  * as possible, even if the mpool cache hasn't been flushed.
  264.  *
  265.  * If we are not doing a salvage, we wish to use the DB_JOINENV flag;
  266.  * if a locking system is present, this will let us use it and be
  267.  * safe to run concurrently with other threads of control.  (We never
  268.  * need to use transactions explicitly, as we're read-only.)  Note
  269.  * that in CDB, too, this will configure our environment
  270.  * appropriately, and our cursors will (correctly) do locking as CDB
  271.  * read cursors.
  272.  *
  273.  * If we are doing a salvage, the verification code will protest
  274.  * if we initialize transactions, logging, or locking;  do an
  275.  * explicit DB_INIT_MPOOL to try to join any existing environment
  276.  * before we create our own.
  277.  */
  278. *is_privatep = 0;
  279. if (dbenv->open(dbenv, home,
  280.     DB_USE_ENVIRON | (is_salvage ? DB_INIT_MPOOL : DB_JOINENV), 0) == 0)
  281. return (0);
  282. /*
  283.  * An environment is required because we may be trying to look at
  284.  * databases in directories other than the current one.  We could
  285.  * avoid using an environment iff the -h option wasn't specified,
  286.  * but that seems like more work than it's worth.
  287.  *
  288.  * No environment exists (or, at least no environment that includes
  289.  * an mpool region exists).  Create one, but make it private so that
  290.  * no files are actually created.
  291.  */
  292. *is_privatep = 1;
  293. if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) == 0 &&
  294.     (ret = dbenv->open(dbenv, home,
  295.     DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0)) == 0)
  296. return (0);
  297. /* An environment is required. */
  298. dbenv->err(dbenv, ret, "open");
  299. return (1);
  300. }
  301. /*
  302.  * is_sub --
  303.  * Return if the database contains subdatabases.
  304.  */
  305. int
  306. is_sub(dbp, yesno)
  307. DB *dbp;
  308. int *yesno;
  309. {
  310. DB_BTREE_STAT *btsp;
  311. DB_HASH_STAT *hsp;
  312. int ret;
  313. switch (dbp->type) {
  314. case DB_BTREE:
  315. case DB_RECNO:
  316. if ((ret = dbp->stat(dbp, &btsp, DB_FAST_STAT)) != 0) {
  317. dbp->err(dbp, ret, "DB->stat");
  318. return (ret);
  319. }
  320. *yesno = btsp->bt_metaflags & BTM_SUBDB ? 1 : 0;
  321. free(btsp);
  322. break;
  323. case DB_HASH:
  324. if ((ret = dbp->stat(dbp, &hsp, DB_FAST_STAT)) != 0) {
  325. dbp->err(dbp, ret, "DB->stat");
  326. return (ret);
  327. }
  328. *yesno = hsp->hash_metaflags & DB_HASH_SUBDB ? 1 : 0;
  329. free(hsp);
  330. break;
  331. case DB_QUEUE:
  332. break;
  333. default:
  334. dbp->errx(dbp, "unknown database type");
  335. return (1);
  336. }
  337. return (0);
  338. }
  339. /*
  340.  * dump_sub --
  341.  * Dump out the records for a DB containing subdatabases.
  342.  */
  343. int
  344. dump_sub(dbenv, parent_dbp, parent_name, pflag, keyflag)
  345. DB_ENV *dbenv;
  346. DB *parent_dbp;
  347. char *parent_name;
  348. int pflag, keyflag;
  349. {
  350. DB *dbp;
  351. DBC *dbcp;
  352. DBT key, data;
  353. int ret;
  354. char *subdb;
  355. /*
  356.  * Get a cursor and step through the database, dumping out each
  357.  * subdatabase.
  358.  */
  359. if ((ret = parent_dbp->cursor(parent_dbp, NULL, &dbcp, 0)) != 0) {
  360. dbenv->err(dbenv, ret, "DB->cursor");
  361. return (1);
  362. }
  363. memset(&key, 0, sizeof(key));
  364. memset(&data, 0, sizeof(data));
  365. while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
  366. /* Nul terminate the subdatabase name. */
  367. if ((subdb = malloc(key.size + 1)) == NULL) {
  368. dbenv->err(dbenv, ENOMEM, NULL);
  369. return (1);
  370. }
  371. memcpy(subdb, key.data, key.size);
  372. subdb[key.size] = '';
  373. /* Create the DB object and open the file. */
  374. if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
  375. dbenv->err(dbenv, ret, "db_create");
  376. free(subdb);
  377. return (1);
  378. }
  379. if ((ret = dbp->open(dbp, NULL,
  380.     parent_name, subdb, DB_UNKNOWN, DB_RDONLY, 0)) != 0)
  381. dbp->err(dbp, ret,
  382.     "DB->open: %s:%s", parent_name, subdb);
  383. if (ret == 0 &&
  384.     (__db_prheader(dbp, subdb, pflag, keyflag, stdout,
  385.     __db_verify_callback, NULL, 0) ||
  386.     dump(dbp, pflag, keyflag)))
  387. ret = 1;
  388. (void)dbp->close(dbp, 0);
  389. free(subdb);
  390. if (ret != 0)
  391. return (1);
  392. }
  393. if (ret != DB_NOTFOUND) {
  394. dbp->err(dbp, ret, "DBcursor->get");
  395. return (1);
  396. }
  397. if ((ret = dbcp->c_close(dbcp)) != 0) {
  398. dbp->err(dbp, ret, "DBcursor->close");
  399. return (1);
  400. }
  401. return (0);
  402. }
  403. /*
  404.  * show_subs --
  405.  * Display the subdatabases for a database.
  406.  */
  407. int
  408. show_subs(dbp)
  409. DB *dbp;
  410. {
  411. DBC *dbcp;
  412. DBT key, data;
  413. int ret;
  414. /*
  415.  * Get a cursor and step through the database, printing out the key
  416.  * of each key/data pair.
  417.  */
  418. if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) {
  419. dbp->err(dbp, ret, "DB->cursor");
  420. return (1);
  421. }
  422. memset(&key, 0, sizeof(key));
  423. memset(&data, 0, sizeof(data));
  424. while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
  425. if ((ret = __db_prdbt(&key, 1, NULL, stdout,
  426.     __db_verify_callback, 0, NULL)) != 0) {
  427. dbp->errx(dbp, NULL);
  428. return (1);
  429. }
  430. }
  431. if (ret != DB_NOTFOUND) {
  432. dbp->err(dbp, ret, "DBcursor->get");
  433. return (1);
  434. }
  435. if ((ret = dbcp->c_close(dbcp)) != 0) {
  436. dbp->err(dbp, ret, "DBcursor->close");
  437. return (1);
  438. }
  439. return (0);
  440. }
  441. /*
  442.  * dump --
  443.  * Dump out the records for a DB.
  444.  */
  445. int
  446. dump(dbp, pflag, keyflag)
  447. DB *dbp;
  448. int pflag, keyflag;
  449. {
  450. DBC *dbcp;
  451. DBT key, data;
  452. DBT keyret, dataret;
  453. db_recno_t recno;
  454. int is_recno, failed, ret;
  455. void *pointer;
  456. /*
  457.  * Get a cursor and step through the database, printing out each
  458.  * key/data pair.
  459.  */
  460. if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) {
  461. dbp->err(dbp, ret, "DB->cursor");
  462. return (1);
  463. }
  464. failed = 0;
  465. memset(&key, 0, sizeof(key));
  466. memset(&data, 0, sizeof(data));
  467. data.data = malloc(1024 * 1024);
  468. if (data.data == NULL) {
  469. dbp->err(dbp, ENOMEM, "bulk get buffer");
  470. failed = 1;
  471. goto err;
  472. }
  473. data.ulen = 1024 * 1024;
  474. data.flags = DB_DBT_USERMEM;
  475. is_recno = (dbp->type == DB_RECNO || dbp->type == DB_QUEUE);
  476. keyflag = is_recno ? keyflag : 1;
  477. if (is_recno) {
  478. keyret.data = &recno;
  479. keyret.size = sizeof(recno);
  480. }
  481. retry:
  482. while ((ret =
  483.     dbcp->c_get(dbcp, &key, &data, DB_NEXT | DB_MULTIPLE_KEY)) == 0) {
  484. DB_MULTIPLE_INIT(pointer, &data);
  485. for (;;) {
  486. if (is_recno)
  487. DB_MULTIPLE_RECNO_NEXT(pointer, &data,
  488.     recno, dataret.data, dataret.size);
  489. else
  490. DB_MULTIPLE_KEY_NEXT(pointer,
  491.     &data, keyret.data,
  492.     keyret.size, dataret.data, dataret.size);
  493. if (dataret.data == NULL)
  494. break;
  495. if ((keyflag && (ret = __db_prdbt(&keyret,
  496.     pflag, " ", stdout, __db_verify_callback,
  497.     is_recno, NULL)) != 0) || (ret =
  498.     __db_prdbt(&dataret, pflag, " ", stdout,
  499. __db_verify_callback, 0, NULL)) != 0) {
  500. dbp->errx(dbp, NULL);
  501. failed = 1;
  502. goto err;
  503. }
  504. }
  505. }
  506. if (ret == ENOMEM) {
  507. data.data = realloc(data.data, data.size);
  508. if (data.data == NULL) {
  509. dbp->err(dbp, ENOMEM, "bulk get buffer");
  510. failed = 1;
  511. goto err;
  512. }
  513. data.ulen = data.size;
  514. goto retry;
  515. }
  516. if (ret != DB_NOTFOUND) {
  517. dbp->err(dbp, ret, "DBcursor->get");
  518. failed = 1;
  519. }
  520. err: if (data.data != NULL)
  521. free(data.data);
  522. if ((ret = dbcp->c_close(dbcp)) != 0) {
  523. dbp->err(dbp, ret, "DBcursor->close");
  524. failed = 1;
  525. }
  526. (void)__db_prfooter(stdout, __db_verify_callback);
  527. return (failed);
  528. }
  529. /*
  530.  * usage --
  531.  * Display the usage message.
  532.  */
  533. int
  534. usage()
  535. {
  536. (void)fprintf(stderr, "%snt%sn",
  537.     "usage: db_dump [-klNprRV]",
  538.     "[-d ahr] [-f output] [-h home] [-P password] [-s database] db_file");
  539. return (EXIT_FAILURE);
  540. }
  541. int
  542. version_check(progname)
  543. const char *progname;
  544. {
  545. int v_major, v_minor, v_patch;
  546. /* Make sure we're loaded with the right version of the DB library. */
  547. (void)db_version(&v_major, &v_minor, &v_patch);
  548. if (v_major != DB_VERSION_MAJOR ||
  549.     v_minor != DB_VERSION_MINOR || v_patch != DB_VERSION_PATCH) {
  550. fprintf(stderr,
  551. "%s: version %d.%d.%d doesn't match library version %d.%d.%dn",
  552.     progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
  553.     DB_VERSION_PATCH, v_major, v_minor, v_patch);
  554. return (EXIT_FAILURE);
  555. }
  556. return (0);
  557. }