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

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_load.c,v 11.71 2002/08/08 03:50:36 bostic Exp $";
  13. #endif
  14. #ifndef NO_SYSTEM_INCLUDES
  15. #include <sys/types.h>
  16. #include <limits.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <unistd.h>
  21. #endif
  22. #include "db_int.h"
  23. #include "dbinc/db_page.h"
  24. #include "dbinc/db_am.h"
  25. typedef struct { /* XXX: Globals. */
  26. const char *progname; /* Program name. */
  27. char *hdrbuf; /* Input file header. */
  28. u_long lineno; /* Input file line number. */
  29. u_long origline; /* Original file line number. */
  30. int endodata; /* Reached the end of a database. */
  31. int endofile; /* Reached the end of the input. */
  32. int version; /* Input version. */
  33. char *home; /* Env home. */
  34. char *passwd; /* Env passwd. */
  35. int private; /* Private env. */
  36. u_int32_t cache; /* Env cache size. */
  37. } LDG;
  38. void badend __P((DB_ENV *));
  39. void badnum __P((DB_ENV *));
  40. int configure __P((DB_ENV *, DB *, char **, char **, int *));
  41. int convprintable __P((DB_ENV *, char *, char **));
  42. int db_init __P((DB_ENV *, char *, u_int32_t, int *));
  43. int dbt_rdump __P((DB_ENV *, DBT *));
  44. int dbt_rprint __P((DB_ENV *, DBT *));
  45. int dbt_rrecno __P((DB_ENV *, DBT *, int));
  46. int digitize __P((DB_ENV *, int, int *));
  47. int env_create __P((DB_ENV **, LDG *));
  48. int load __P((DB_ENV *, char *, DBTYPE, char **, u_int, LDG *, int *));
  49. int main __P((int, char *[]));
  50. int rheader __P((DB_ENV *, DB *, DBTYPE *, char **, int *, int *));
  51. int usage __P((void));
  52. int version_check __P((const char *));
  53. #define G(f) ((LDG *)dbenv->app_private)->f
  54. /* Flags to the load function. */
  55. #define LDF_NOHEADER 0x01 /* No dump header. */
  56. #define LDF_NOOVERWRITE 0x02 /* Don't overwrite existing rows. */
  57. #define LDF_PASSWORD 0x04 /* Encrypt created databases. */
  58. int
  59. main(argc, argv)
  60. int argc;
  61. char *argv[];
  62. {
  63. extern char *optarg;
  64. extern int optind;
  65. DBTYPE dbtype;
  66. DB_ENV *dbenv;
  67. LDG ldg;
  68. u_int32_t ldf;
  69. int ch, existed, exitval, ret;
  70. char **clist, **clp;
  71. ldg.progname = "db_load";
  72. ldg.lineno = 0;
  73. ldg.endodata = ldg.endofile = 0;
  74. ldg.version = 1;
  75. ldg.cache = MEGABYTE;
  76. ldg.hdrbuf = NULL;
  77. ldg.home = NULL;
  78. ldg.passwd = NULL;
  79. if ((ret = version_check(ldg.progname)) != 0)
  80. return (ret);
  81. ldf = 0;
  82. exitval = 0;
  83. dbtype = DB_UNKNOWN;
  84. /* Allocate enough room for configuration arguments. */
  85. if ((clp = clist = (char **)calloc(argc + 1, sizeof(char *))) == NULL) {
  86. fprintf(stderr, "%s: %sn", ldg.progname, strerror(ENOMEM));
  87. return (EXIT_FAILURE);
  88. }
  89. while ((ch = getopt(argc, argv, "c:f:h:nP:Tt:V")) != EOF)
  90. switch (ch) {
  91. case 'c':
  92. *clp++ = optarg;
  93. break;
  94. case 'f':
  95. if (freopen(optarg, "r", stdin) == NULL) {
  96. fprintf(stderr, "%s: %s: reopen: %sn",
  97.     ldg.progname, optarg, strerror(errno));
  98. return (EXIT_FAILURE);
  99. }
  100. break;
  101. case 'h':
  102. ldg.home = optarg;
  103. break;
  104. case 'n':
  105. ldf |= LDF_NOOVERWRITE;
  106. break;
  107. case 'P':
  108. ldg.passwd = strdup(optarg);
  109. memset(optarg, 0, strlen(optarg));
  110. if (ldg.passwd == NULL) {
  111. fprintf(stderr, "%s: strdup: %sn",
  112.     ldg.progname, strerror(errno));
  113. return (EXIT_FAILURE);
  114. }
  115. ldf |= LDF_PASSWORD;
  116. break;
  117. case 'T':
  118. ldf |= LDF_NOHEADER;
  119. break;
  120. case 't':
  121. if (strcmp(optarg, "btree") == 0) {
  122. dbtype = DB_BTREE;
  123. break;
  124. }
  125. if (strcmp(optarg, "hash") == 0) {
  126. dbtype = DB_HASH;
  127. break;
  128. }
  129. if (strcmp(optarg, "recno") == 0) {
  130. dbtype = DB_RECNO;
  131. break;
  132. }
  133. if (strcmp(optarg, "queue") == 0) {
  134. dbtype = DB_QUEUE;
  135. break;
  136. }
  137. return (usage());
  138. case 'V':
  139. printf("%sn", db_version(NULL, NULL, NULL));
  140. return (EXIT_SUCCESS);
  141. case '?':
  142. default:
  143. return (usage());
  144. }
  145. argc -= optind;
  146. argv += optind;
  147. if (argc != 1)
  148. return (usage());
  149. /* Handle possible interruptions. */
  150. __db_util_siginit();
  151. /*
  152.  * Create an environment object initialized for error reporting, and
  153.  * then open it.
  154.  */
  155. if (env_create(&dbenv, &ldg) != 0)
  156. goto shutdown;
  157. while (!ldg.endofile)
  158. if (load(dbenv, argv[0], dbtype, clist, ldf,
  159.     &ldg, &existed) != 0)
  160. goto shutdown;
  161. if (0) {
  162. shutdown: exitval = 1;
  163. }
  164. if ((ret = dbenv->close(dbenv, 0)) != 0) {
  165. exitval = 1;
  166. fprintf(stderr,
  167.     "%s: dbenv->close: %sn", ldg.progname, db_strerror(ret));
  168. }
  169. /* Resend any caught signal. */
  170. __db_util_sigresend();
  171. free(clist);
  172. /*
  173.  * Return 0 on success, 1 if keys existed already, and 2 on failure.
  174.  *
  175.  * Technically, this is wrong, because exit of anything other than
  176.  * 0 is implementation-defined by the ANSI C standard.  I don't see
  177.  * any good solutions that don't involve API changes.
  178.  */
  179. return (exitval == 0 ? (existed == 0 ? 0 : 1) : 2);
  180. }
  181. /*
  182.  * load --
  183.  * Load a database.
  184.  */
  185. int
  186. load(dbenv, name, argtype, clist, flags, ldg, existedp)
  187. DB_ENV *dbenv;
  188. char *name, **clist;
  189. DBTYPE argtype;
  190. u_int flags;
  191. LDG *ldg;
  192. int *existedp;
  193. {
  194. DB *dbp;
  195. DBT key, rkey, data, *readp, *writep;
  196. DBTYPE dbtype;
  197. DB_TXN *ctxn, *txn;
  198. db_recno_t recno, datarecno;
  199. u_int32_t put_flags;
  200. int ascii_recno, checkprint, hexkeys, keyflag, keys, resize, ret, rval;
  201. char *subdb;
  202. *existedp = 0;
  203. put_flags = LF_ISSET(LDF_NOOVERWRITE) ? DB_NOOVERWRITE : 0;
  204. G(endodata) = 0;
  205. subdb = NULL;
  206. ctxn = txn = NULL;
  207. memset(&key, 0, sizeof(DBT));
  208. memset(&data, 0, sizeof(DBT));
  209. memset(&rkey, 0, sizeof(DBT));
  210. retry_db:
  211. /* Create the DB object. */
  212. if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
  213. dbenv->err(dbenv, ret, "db_create");
  214. goto err;
  215. }
  216. dbtype = DB_UNKNOWN;
  217. keys = -1;
  218. hexkeys = -1;
  219. keyflag = -1;
  220. /* Read the header -- if there's no header, we expect flat text. */
  221. if (LF_ISSET(LDF_NOHEADER)) {
  222. checkprint = 1;
  223. dbtype = argtype;
  224. } else {
  225. if (rheader(dbenv,
  226.     dbp, &dbtype, &subdb, &checkprint, &keys) != 0)
  227. goto err;
  228. if (G(endofile))
  229. goto done;
  230. }
  231. /*
  232.  * Apply command-line configuration changes.  (We apply command-line
  233.  * configuration changes to all databases that are loaded, e.g., all
  234.  * subdatabases.)
  235.  */
  236. if (configure(dbenv, dbp, clist, &subdb, &keyflag))
  237. goto err;
  238. if (keys != 1) {
  239. if (keyflag == 1) {
  240. dbp->err(dbp, EINVAL, "No keys specified in file");
  241. goto err;
  242. }
  243. }
  244. else if (keyflag == 0) {
  245. dbp->err(dbp, EINVAL, "Keys specified in file");
  246. goto err;
  247. }
  248. else
  249. keyflag = 1;
  250. if (dbtype == DB_BTREE || dbtype == DB_HASH) {
  251. if (keyflag == 0)
  252. dbp->err(dbp,
  253.     EINVAL, "Btree and Hash must specify keys");
  254. else
  255. keyflag = 1;
  256. }
  257. if (argtype != DB_UNKNOWN) {
  258. if (dbtype == DB_RECNO || dbtype == DB_QUEUE)
  259. if (keyflag != 1 && argtype != DB_RECNO &&
  260.     argtype != DB_QUEUE) {
  261. dbenv->errx(dbenv,
  262.    "improper database type conversion specified");
  263. goto err;
  264. }
  265. dbtype = argtype;
  266. }
  267. if (dbtype == DB_UNKNOWN) {
  268. dbenv->errx(dbenv, "no database type specified");
  269. goto err;
  270. }
  271. if (keyflag == -1)
  272. keyflag = 0;
  273. /*
  274.  * Recno keys have only been printed in hexadecimal starting
  275.  * with db_dump format version 3 (DB 3.2).
  276.  *
  277.  * !!!
  278.  * Note that version is set in rheader(), which must be called before
  279.  * this assignment.
  280.  */
  281. hexkeys = (G(version) >= 3 && keyflag == 1 && checkprint == 0);
  282. if (keyflag == 1 && (dbtype == DB_RECNO || dbtype == DB_QUEUE))
  283. ascii_recno = 1;
  284. else
  285. ascii_recno = 0;
  286. /* If configured with a password, encrypt databases we create. */
  287. if (LF_ISSET(LDF_PASSWORD) &&
  288.     (ret = dbp->set_flags(dbp, DB_ENCRYPT)) != 0) {
  289. dbp->err(dbp, ret, "DB->set_flags: DB_ENCRYPT");
  290. goto err;
  291. }
  292. /* Open the DB file. */
  293. if ((ret = dbp->open(dbp, NULL, name, subdb, dbtype,
  294.     DB_CREATE | (TXN_ON(dbenv) ? DB_AUTO_COMMIT : 0),
  295.     __db_omode("rwrwrw"))) != 0) {
  296. dbp->err(dbp, ret, "DB->open: %s", name);
  297. goto err;
  298. }
  299. if (ldg->private != 0) {
  300. if ((ret =
  301.     __db_util_cache(dbenv, dbp, &ldg->cache, &resize)) != 0)
  302. goto err;
  303. if (resize) {
  304. dbp->close(dbp, 0);
  305. dbp = NULL;
  306. dbenv->close(dbenv, 0);
  307. if ((ret = env_create(&dbenv, ldg)) != 0)
  308. goto err;
  309. goto retry_db;
  310. }
  311. }
  312. /* Initialize the key/data pair. */
  313. readp = &key;
  314. writep = &key;
  315. if (dbtype == DB_RECNO || dbtype == DB_QUEUE) {
  316. key.size = sizeof(recno);
  317. if (keyflag) {
  318. key.data = &datarecno;
  319. if (checkprint) {
  320. readp = &rkey;
  321. goto key_data;
  322. }
  323. }
  324. else
  325. key.data = &recno;
  326. } else
  327. key_data: if ((readp->data =
  328.     (void *)malloc(readp->ulen = 1024)) == NULL) {
  329. dbenv->err(dbenv, ENOMEM, NULL);
  330. goto err;
  331. }
  332. if ((data.data = (void *)malloc(data.ulen = 1024)) == NULL) {
  333. dbenv->err(dbenv, ENOMEM, NULL);
  334. goto err;
  335. }
  336. if (TXN_ON(dbenv) &&
  337.     (ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0)
  338. goto err;
  339. /* Get each key/data pair and add them to the database. */
  340. for (recno = 1; !__db_util_interrupted(); ++recno) {
  341. if (!keyflag)
  342. if (checkprint) {
  343. if (dbt_rprint(dbenv, &data))
  344. goto err;
  345. } else {
  346. if (dbt_rdump(dbenv, &data))
  347. goto err;
  348. }
  349. else
  350. if (checkprint) {
  351. if (dbt_rprint(dbenv, readp))
  352. goto err;
  353. if (!G(endodata) && dbt_rprint(dbenv, &data))
  354. goto fmt;
  355. } else {
  356. if (ascii_recno) {
  357. if (dbt_rrecno(dbenv, readp, hexkeys))
  358. goto err;
  359. } else
  360. if (dbt_rdump(dbenv, readp))
  361. goto err;
  362. if (!G(endodata) && dbt_rdump(dbenv, &data)) {
  363. fmt: dbenv->errx(dbenv,
  364.     "odd number of key/data pairs");
  365. goto err;
  366. }
  367. }
  368. if (G(endodata))
  369. break;
  370. if (readp != writep) {
  371. if (sscanf(readp->data, "%ud", &datarecno) != 1)
  372. dbenv->errx(dbenv,
  373.     "%s: non-integer key at line: %d",
  374.     name, !keyflag ? recno : recno * 2 - 1);
  375. if (datarecno == 0)
  376. dbenv->errx(dbenv, "%s: zero key at line: %d",
  377.     name,
  378.     !keyflag ? recno : recno * 2 - 1);
  379. }
  380. retry: if (txn != NULL)
  381. if ((ret = dbenv->txn_begin(dbenv, txn, &ctxn, 0)) != 0)
  382. goto err;
  383. switch (ret = dbp->put(dbp, ctxn, writep, &data, put_flags)) {
  384. case 0:
  385. if (ctxn != NULL) {
  386. if ((ret =
  387.     ctxn->commit(ctxn, DB_TXN_NOSYNC)) != 0)
  388. goto err;
  389. ctxn = NULL;
  390. }
  391. break;
  392. case DB_KEYEXIST:
  393. *existedp = 1;
  394. dbenv->errx(dbenv,
  395.     "%s: line %d: key already exists, not loaded:",
  396.     name,
  397.     !keyflag ? recno : recno * 2 - 1);
  398. (void)__db_prdbt(&key, checkprint, 0, stderr,
  399.     __db_verify_callback, 0, NULL);
  400. break;
  401. case DB_LOCK_DEADLOCK:
  402. /* If we have a child txn, retry--else it's fatal. */
  403. if (ctxn != NULL) {
  404. if ((ret = ctxn->abort(ctxn)) != 0)
  405. goto err;
  406. ctxn = NULL;
  407. goto retry;
  408. }
  409. /* FALLTHROUGH */
  410. default:
  411. dbenv->err(dbenv, ret, NULL);
  412. if (ctxn != NULL) {
  413. (void)ctxn->abort(ctxn);
  414. ctxn = NULL;
  415. }
  416. goto err;
  417. }
  418. if (ctxn != NULL) {
  419. if ((ret = ctxn->abort(ctxn)) != 0)
  420. goto err;
  421. ctxn = NULL;
  422. }
  423. }
  424. done: rval = 0;
  425. DB_ASSERT(ctxn == NULL);
  426. if (txn != NULL && (ret = txn->commit(txn, 0)) != 0) {
  427. txn = NULL;
  428. goto err;
  429. }
  430. if (0) {
  431. err: rval = 1;
  432. DB_ASSERT(ctxn == NULL);
  433. if (txn != NULL)
  434. (void)txn->abort(txn);
  435. }
  436. /* Close the database. */
  437. if (dbp != NULL && (ret = dbp->close(dbp, 0)) != 0) {
  438. dbenv->err(dbenv, ret, "DB->close");
  439. rval = 1;
  440. }
  441. if (G(hdrbuf) != NULL)
  442. free(G(hdrbuf));
  443. G(hdrbuf) = NULL;
  444. /* Free allocated memory. */
  445. if (subdb != NULL)
  446. free(subdb);
  447. if (dbtype != DB_RECNO && dbtype != DB_QUEUE)
  448. free(key.data);
  449. if (rkey.data != NULL)
  450. free(rkey.data);
  451. free(data.data);
  452. return (rval);
  453. }
  454. /*
  455.  * db_init --
  456.  * Initialize the environment.
  457.  */
  458. int
  459. db_init(dbenv, home, cache, is_private)
  460. DB_ENV *dbenv;
  461. char *home;
  462. u_int32_t cache;
  463. int *is_private;
  464. {
  465. u_int32_t flags;
  466. int ret;
  467. *is_private = 0;
  468. /* We may be loading into a live environment.  Try and join. */
  469. flags = DB_USE_ENVIRON |
  470.     DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN;
  471. if (dbenv->open(dbenv, home, flags, 0) == 0)
  472. return (0);
  473. /*
  474.  * We're trying to load a database.
  475.  *
  476.  * An environment is required because we may be trying to look at
  477.  * databases in directories other than the current one.  We could
  478.  * avoid using an environment iff the -h option wasn't specified,
  479.  * but that seems like more work than it's worth.
  480.  *
  481.  * No environment exists (or, at least no environment that includes
  482.  * an mpool region exists).  Create one, but make it private so that
  483.  * no files are actually created.
  484.  */
  485. LF_CLR(DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN);
  486. LF_SET(DB_CREATE | DB_PRIVATE);
  487. *is_private = 1;
  488. if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) != 0) {
  489. dbenv->err(dbenv, ret, "set_cachesize");
  490. return (1);
  491. }
  492. if ((ret = dbenv->open(dbenv, home, flags, 0)) == 0)
  493. return (0);
  494. /* An environment is required. */
  495. dbenv->err(dbenv, ret, "DB_ENV->open");
  496. return (1);
  497. }
  498. #define FLAG(name, value, keyword, flag)
  499. if (strcmp(name, keyword) == 0) {
  500. switch (*value) {
  501. case '1':
  502. if ((ret = dbp->set_flags(dbp, flag)) != 0) {
  503. dbp->err(dbp, ret, "%s: set_flags: %s",
  504.     G(progname), name);
  505. return (1);
  506. }
  507. break;
  508. case '0':
  509. break;
  510. default:
  511. badnum(dbenv);
  512. return (1);
  513. }
  514. continue;
  515. }
  516. #define NUMBER(name, value, keyword, func)
  517. if (strcmp(name, keyword) == 0) {
  518. if (__db_getlong(dbp,
  519.     NULL, value, 1, LONG_MAX, &val) != 0)
  520. return (1);
  521. if ((ret = dbp->func(dbp, val)) != 0)
  522. goto nameerr;
  523. continue;
  524. }
  525. #define STRING(name, value, keyword, func)
  526. if (strcmp(name, keyword) == 0) {
  527. if ((ret = dbp->func(dbp, value[0])) != 0)
  528. goto nameerr;
  529. continue;
  530. }
  531. /*
  532.  * configure --
  533.  * Handle command-line configuration options.
  534.  */
  535. int
  536. configure(dbenv, dbp, clp, subdbp, keysp)
  537. DB_ENV *dbenv;
  538. DB *dbp;
  539. char **clp, **subdbp;
  540. int *keysp;
  541. {
  542. long val;
  543. int ret, savech;
  544. char *name, *value;
  545. for (; (name = *clp) != NULL; *--value = savech, ++clp) {
  546. if ((value = strchr(name, '=')) == NULL) {
  547. dbp->errx(dbp,
  548.     "command-line configuration uses name=value format");
  549. return (1);
  550. }
  551. savech = *value;
  552. *value++ = '';
  553. if (strcmp(name, "database") == 0 ||
  554.     strcmp(name, "subdatabase") == 0) {
  555. if (*subdbp != NULL)
  556. free(*subdbp);
  557. if ((*subdbp = strdup(value)) == NULL) {
  558. dbp->err(dbp, ENOMEM, NULL);
  559. return (1);
  560. }
  561. continue;
  562. }
  563. if (strcmp(name, "keys") == 0) {
  564. if (strcmp(value, "1") == 0)
  565. *keysp = 1;
  566. else if (strcmp(value, "0") == 0)
  567. *keysp = 0;
  568. else {
  569. badnum(dbenv);
  570. return (1);
  571. }
  572. continue;
  573. }
  574. #ifdef notyet
  575. NUMBER(name, value, "bt_maxkey", set_bt_maxkey);
  576. #endif
  577. NUMBER(name, value, "bt_minkey", set_bt_minkey);
  578. NUMBER(name, value, "db_lorder", set_lorder);
  579. NUMBER(name, value, "db_pagesize", set_pagesize);
  580. FLAG(name, value, "chksum", DB_CHKSUM_SHA1);
  581. FLAG(name, value, "duplicates", DB_DUP);
  582. FLAG(name, value, "dupsort", DB_DUPSORT);
  583. NUMBER(name, value, "h_ffactor", set_h_ffactor);
  584. NUMBER(name, value, "h_nelem", set_h_nelem);
  585. NUMBER(name, value, "re_len", set_re_len);
  586. STRING(name, value, "re_pad", set_re_pad);
  587. FLAG(name, value, "recnum", DB_RECNUM);
  588. FLAG(name, value, "renumber", DB_RENUMBER);
  589. dbp->errx(dbp,
  590.     "unknown command-line configuration keyword "%s"", name);
  591. return (1);
  592. }
  593. return (0);
  594. nameerr:
  595. dbp->err(dbp, ret, "%s: %s=%s", G(progname), name, value);
  596. return (1);
  597. }
  598. /*
  599.  * rheader --
  600.  * Read the header message.
  601.  */
  602. int
  603. rheader(dbenv, dbp, dbtypep, subdbp, checkprintp, keysp)
  604. DB_ENV *dbenv;
  605. DB *dbp;
  606. DBTYPE *dbtypep;
  607. char **subdbp;
  608. int *checkprintp, *keysp;
  609. {
  610. long val;
  611. int ch, first, hdr, linelen, buflen, ret, start;
  612. char *buf, *name, *p, *value;
  613. *dbtypep = DB_UNKNOWN;
  614. *checkprintp = 0;
  615. name = p = NULL;
  616. /*
  617.  * We start with a smallish buffer;  most headers are small.
  618.  * We may need to realloc it for a large subdatabase name.
  619.  */
  620. buflen = 4096;
  621. if (G(hdrbuf) == NULL) {
  622. hdr = 0;
  623. if ((buf = (char *)malloc(buflen)) == NULL) {
  624. memerr: dbp->errx(dbp, "could not allocate buffer %d", buflen);
  625. return (1);
  626. }
  627. G(hdrbuf) = buf;
  628. G(origline) = G(lineno);
  629. } else {
  630. hdr = 1;
  631. buf = G(hdrbuf);
  632. G(lineno) = G(origline);
  633. }
  634. start = 0;
  635. for (first = 1;; first = 0) {
  636. ++G(lineno);
  637. /* Read a line, which may be of arbitrary length, into buf. */
  638. linelen = 0;
  639. buf = &G(hdrbuf)[start];
  640. if (hdr == 0) {
  641. for (;;) {
  642. if ((ch = getchar()) == EOF) {
  643. if (!first || ferror(stdin))
  644. goto badfmt;
  645. G(endofile) = 1;
  646. break;
  647. }
  648. if (ch == 'n')
  649. break;
  650. buf[linelen++] = ch;
  651. /* If the buffer is too small, double it. */
  652. if (linelen + start == buflen) {
  653. G(hdrbuf) = (char *)realloc(G(hdrbuf),
  654.     buflen *= 2);
  655. if (G(hdrbuf) == NULL)
  656. goto memerr;
  657. buf = &G(hdrbuf)[start];
  658. }
  659. }
  660. if (G(endofile) == 1)
  661. break;
  662. buf[linelen++] = '';
  663. } else
  664. linelen = strlen(buf) + 1;
  665. start += linelen;
  666. if (name != NULL) {
  667. *p = '=';
  668. free(name);
  669. name = NULL;
  670. }
  671. /* If we don't see the expected information, it's an error. */
  672. if ((name = strdup(buf)) == NULL)
  673. goto memerr;
  674. if ((p = strchr(name, '=')) == NULL)
  675. goto badfmt;
  676. *p++ = '';
  677. value = p--;
  678. if (name[0] == '' || value[0] == '')
  679. goto badfmt;
  680. if (strcmp(name, "HEADER") == 0)
  681. break;
  682. if (strcmp(name, "VERSION") == 0) {
  683. /*
  684.  * Version 1 didn't have a "VERSION" header line.  We
  685.  * only support versions 1, 2, and 3 of the dump format.
  686.  */
  687. G(version) = atoi(value);
  688. if (G(version) > 3) {
  689. dbp->errx(dbp,
  690.     "line %lu: VERSION %d is unsupported",
  691.     G(lineno), G(version));
  692. goto err;
  693. }
  694. continue;
  695. }
  696. if (strcmp(name, "format") == 0) {
  697. if (strcmp(value, "bytevalue") == 0) {
  698. *checkprintp = 0;
  699. continue;
  700. }
  701. if (strcmp(value, "print") == 0) {
  702. *checkprintp = 1;
  703. continue;
  704. }
  705. goto badfmt;
  706. }
  707. if (strcmp(name, "type") == 0) {
  708. if (strcmp(value, "btree") == 0) {
  709. *dbtypep = DB_BTREE;
  710. continue;
  711. }
  712. if (strcmp(value, "hash") == 0) {
  713. *dbtypep = DB_HASH;
  714. continue;
  715. }
  716. if (strcmp(value, "recno") == 0) {
  717. *dbtypep = DB_RECNO;
  718. continue;
  719. }
  720. if (strcmp(value, "queue") == 0) {
  721. *dbtypep = DB_QUEUE;
  722. continue;
  723. }
  724. dbp->errx(dbp, "line %lu: unknown type", G(lineno));
  725. goto err;
  726. }
  727. if (strcmp(name, "database") == 0 ||
  728.     strcmp(name, "subdatabase") == 0) {
  729. if ((ret = convprintable(dbenv, value, subdbp)) != 0) {
  730. dbp->err(dbp, ret, "error reading db name");
  731. goto err;
  732. }
  733. continue;
  734. }
  735. if (strcmp(name, "keys") == 0) {
  736. if (strcmp(value, "1") == 0)
  737. *keysp = 1;
  738. else if (strcmp(value, "0") == 0)
  739. *keysp = 0;
  740. else {
  741. badnum(dbenv);
  742. goto err;
  743. }
  744. continue;
  745. }
  746. #ifdef notyet
  747. NUMBER(name, value, "bt_maxkey", set_bt_maxkey);
  748. #endif
  749. NUMBER(name, value, "bt_minkey", set_bt_minkey);
  750. NUMBER(name, value, "db_lorder", set_lorder);
  751. NUMBER(name, value, "db_pagesize", set_pagesize);
  752. NUMBER(name, value, "extentsize", set_q_extentsize);
  753. FLAG(name, value, "chksum", DB_CHKSUM_SHA1);
  754. FLAG(name, value, "duplicates", DB_DUP);
  755. FLAG(name, value, "dupsort", DB_DUPSORT);
  756. NUMBER(name, value, "h_ffactor", set_h_ffactor);
  757. NUMBER(name, value, "h_nelem", set_h_nelem);
  758. NUMBER(name, value, "re_len", set_re_len);
  759. STRING(name, value, "re_pad", set_re_pad);
  760. FLAG(name, value, "recnum", DB_RECNUM);
  761. FLAG(name, value, "renumber", DB_RENUMBER);
  762. dbp->errx(dbp,
  763.     "unknown input-file header configuration keyword "%s"",
  764.     name);
  765. goto err;
  766. }
  767. ret = 0;
  768. if (0) {
  769. nameerr:
  770. dbp->err(dbp, ret, "%s: %s=%s", G(progname), name, value);
  771. ret = 1;
  772. }
  773. if (0)
  774. err: ret = 1;
  775. if (0) {
  776. badfmt:
  777. dbp->errx(dbp, "line %lu: unexpected format", G(lineno));
  778. ret = 1;
  779. }
  780. if (name != NULL) {
  781. *p = '=';
  782. free(name);
  783. }
  784. return (ret);
  785. }
  786. /*
  787.  * convprintable --
  788.  * Convert a printable-encoded string into a newly allocated string.
  789.  *
  790.  * In an ideal world, this would probably share code with dbt_rprint, but
  791.  * that's set up to read character-by-character (to avoid large memory
  792.  * allocations that aren't likely to be a problem here), and this has fewer
  793.  * special cases to deal with.
  794.  *
  795.  * Note that despite the printable encoding, the char * interface to this
  796.  * function (which is, not coincidentally, also used for database naming)
  797.  * means that outstr cannot contain any nuls.
  798.  */
  799. int
  800. convprintable(dbenv, instr, outstrp)
  801. DB_ENV *dbenv;
  802. char *instr, **outstrp;
  803. {
  804. char c, *outstr;
  805. int e1, e2;
  806. /*
  807.  * Just malloc a string big enough for the whole input string;
  808.  * the output string will be smaller (or of equal length).
  809.  */
  810. if ((outstr = (char *)malloc(strlen(instr))) == NULL)
  811. return (ENOMEM);
  812. *outstrp = outstr;
  813. e1 = e2 = 0;
  814. for ( ; *instr != ''; instr++)
  815. if (*instr == '\') {
  816. if (*++instr == '\') {
  817. *outstr++ = '\';
  818. continue;
  819. }
  820. c = digitize(dbenv, *instr, &e1) << 4;
  821. c |= digitize(dbenv, *++instr, &e2);
  822. if (e1 || e2) {
  823. badend(dbenv);
  824. return (EINVAL);
  825. }
  826. *outstr++ = c;
  827. } else
  828. *outstr++ = *instr;
  829. *outstr = '';
  830. return (0);
  831. }
  832. /*
  833.  * dbt_rprint --
  834.  * Read a printable line into a DBT structure.
  835.  */
  836. int
  837. dbt_rprint(dbenv, dbtp)
  838. DB_ENV *dbenv;
  839. DBT *dbtp;
  840. {
  841. u_int32_t len;
  842. u_int8_t *p;
  843. int c1, c2, e, escape, first;
  844. char buf[32];
  845. ++G(lineno);
  846. first = 1;
  847. e = escape = 0;
  848. for (p = dbtp->data, len = 0; (c1 = getchar()) != 'n';) {
  849. if (c1 == EOF) {
  850. if (len == 0) {
  851. G(endofile) = G(endodata) = 1;
  852. return (0);
  853. }
  854. badend(dbenv);
  855. return (1);
  856. }
  857. if (first) {
  858. first = 0;
  859. if (G(version) > 1) {
  860. if (c1 != ' ') {
  861. buf[0] = c1;
  862. if (fgets(buf + 1,
  863.     sizeof(buf) - 1, stdin) == NULL ||
  864.     strcmp(buf, "DATA=ENDn") != 0) {
  865. badend(dbenv);
  866. return (1);
  867. }
  868. G(endodata) = 1;
  869. return (0);
  870. }
  871. continue;
  872. }
  873. }
  874. if (escape) {
  875. if (c1 != '\') {
  876. if ((c2 = getchar()) == EOF) {
  877. badend(dbenv);
  878. return (1);
  879. }
  880. c1 = digitize(dbenv,
  881.     c1, &e) << 4 | digitize(dbenv, c2, &e);
  882. if (e)
  883. return (1);
  884. }
  885. escape = 0;
  886. } else
  887. if (c1 == '\') {
  888. escape = 1;
  889. continue;
  890. }
  891. if (len >= dbtp->ulen - 10) {
  892. dbtp->ulen *= 2;
  893. if ((dbtp->data =
  894.     (void *)realloc(dbtp->data, dbtp->ulen)) == NULL) {
  895. dbenv->err(dbenv, ENOMEM, NULL);
  896. return (1);
  897. }
  898. p = (u_int8_t *)dbtp->data + len;
  899. }
  900. ++len;
  901. *p++ = c1;
  902. }
  903. dbtp->size = len;
  904. return (0);
  905. }
  906. /*
  907.  * dbt_rdump --
  908.  * Read a byte dump line into a DBT structure.
  909.  */
  910. int
  911. dbt_rdump(dbenv, dbtp)
  912. DB_ENV *dbenv;
  913. DBT *dbtp;
  914. {
  915. u_int32_t len;
  916. u_int8_t *p;
  917. int c1, c2, e, first;
  918. char buf[32];
  919. ++G(lineno);
  920. first = 1;
  921. e = 0;
  922. for (p = dbtp->data, len = 0; (c1 = getchar()) != 'n';) {
  923. if (c1 == EOF) {
  924. if (len == 0) {
  925. G(endofile) = G(endodata) = 1;
  926. return (0);
  927. }
  928. badend(dbenv);
  929. return (1);
  930. }
  931. if (first) {
  932. first = 0;
  933. if (G(version) > 1) {
  934. if (c1 != ' ') {
  935. buf[0] = c1;
  936. if (fgets(buf + 1,
  937.     sizeof(buf) - 1, stdin) == NULL ||
  938.     strcmp(buf, "DATA=ENDn") != 0) {
  939. badend(dbenv);
  940. return (1);
  941. }
  942. G(endodata) = 1;
  943. return (0);
  944. }
  945. continue;
  946. }
  947. }
  948. if ((c2 = getchar()) == EOF) {
  949. badend(dbenv);
  950. return (1);
  951. }
  952. if (len >= dbtp->ulen - 10) {
  953. dbtp->ulen *= 2;
  954. if ((dbtp->data =
  955.     (void *)realloc(dbtp->data, dbtp->ulen)) == NULL) {
  956. dbenv->err(dbenv, ENOMEM, NULL);
  957. return (1);
  958. }
  959. p = (u_int8_t *)dbtp->data + len;
  960. }
  961. ++len;
  962. *p++ = digitize(dbenv, c1, &e) << 4 | digitize(dbenv, c2, &e);
  963. if (e)
  964. return (1);
  965. }
  966. dbtp->size = len;
  967. return (0);
  968. }
  969. /*
  970.  * dbt_rrecno --
  971.  * Read a record number dump line into a DBT structure.
  972.  */
  973. int
  974. dbt_rrecno(dbenv, dbtp, ishex)
  975. DB_ENV *dbenv;
  976. DBT *dbtp;
  977. int ishex;
  978. {
  979. char buf[32], *p, *q;
  980. ++G(lineno);
  981. if (fgets(buf, sizeof(buf), stdin) == NULL) {
  982. G(endofile) = G(endodata) = 1;
  983. return (0);
  984. }
  985. if (strcmp(buf, "DATA=ENDn") == 0) {
  986. G(endodata) = 1;
  987. return (0);
  988. }
  989. if (buf[0] != ' ')
  990. goto bad;
  991. /*
  992.  * If we're expecting a hex key, do an in-place conversion
  993.  * of hex to straight ASCII before calling __db_getulong().
  994.  */
  995. if (ishex) {
  996. for (p = q = buf + 1; *q != '' && *q != 'n';) {
  997. /*
  998.  * 0-9 in hex are 0x30-0x39, so this is easy.
  999.  * We should alternate between 3's and [0-9], and
  1000.  * if the [0-9] are something unexpected,
  1001.  * __db_getulong will fail, so we only need to catch
  1002.  * end-of-string conditions.
  1003.  */
  1004. if (*q++ != '3')
  1005. goto bad;
  1006. if (*q == 'n' || *q == '')
  1007. goto bad;
  1008. *p++ = *q++;
  1009. }
  1010. *p = '';
  1011. }
  1012. if (__db_getulong(NULL,
  1013.     G(progname), buf + 1, 0, 0, (u_long *)dbtp->data)) {
  1014. bad: badend(dbenv);
  1015. return (1);
  1016. }
  1017. dbtp->size = sizeof(db_recno_t);
  1018. return (0);
  1019. }
  1020. /*
  1021.  * digitize --
  1022.  * Convert a character to an integer.
  1023.  */
  1024. int
  1025. digitize(dbenv, c, errorp)
  1026. DB_ENV *dbenv;
  1027. int c, *errorp;
  1028. {
  1029. switch (c) { /* Don't depend on ASCII ordering. */
  1030. case '0': return (0);
  1031. case '1': return (1);
  1032. case '2': return (2);
  1033. case '3': return (3);
  1034. case '4': return (4);
  1035. case '5': return (5);
  1036. case '6': return (6);
  1037. case '7': return (7);
  1038. case '8': return (8);
  1039. case '9': return (9);
  1040. case 'a': return (10);
  1041. case 'b': return (11);
  1042. case 'c': return (12);
  1043. case 'd': return (13);
  1044. case 'e': return (14);
  1045. case 'f': return (15);
  1046. }
  1047. dbenv->errx(dbenv, "unexpected hexadecimal value");
  1048. *errorp = 1;
  1049. return (0);
  1050. }
  1051. /*
  1052.  * badnum --
  1053.  * Display the bad number message.
  1054.  */
  1055. void
  1056. badnum(dbenv)
  1057. DB_ENV *dbenv;
  1058. {
  1059. dbenv->errx(dbenv,
  1060.     "boolean name=value pairs require a value of 0 or 1");
  1061. }
  1062. /*
  1063.  * badend --
  1064.  * Display the bad end to input message.
  1065.  */
  1066. void
  1067. badend(dbenv)
  1068. DB_ENV *dbenv;
  1069. {
  1070. dbenv->errx(dbenv, "unexpected end of input data or key/data pair");
  1071. }
  1072. /*
  1073.  * usage --
  1074.  * Display the usage message.
  1075.  */
  1076. int
  1077. usage()
  1078. {
  1079. (void)fprintf(stderr, "%snt%sn",
  1080.     "usage: db_load [-nTV] [-c name=value] [-f file]",
  1081.     "[-h home] [-P password] [-t btree | hash | recno | queue] db_file");
  1082. return (EXIT_FAILURE);
  1083. }
  1084. int
  1085. version_check(progname)
  1086. const char *progname;
  1087. {
  1088. int v_major, v_minor, v_patch;
  1089. /* Make sure we're loaded with the right version of the DB library. */
  1090. (void)db_version(&v_major, &v_minor, &v_patch);
  1091. if (v_major != DB_VERSION_MAJOR ||
  1092.     v_minor != DB_VERSION_MINOR || v_patch != DB_VERSION_PATCH) {
  1093. fprintf(stderr,
  1094. "%s: version %d.%d.%d doesn't match library version %d.%d.%dn",
  1095.     progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
  1096.     DB_VERSION_PATCH, v_major, v_minor, v_patch);
  1097. return (EXIT_FAILURE);
  1098. }
  1099. return (0);
  1100. }
  1101. int
  1102. env_create(dbenvp, ldg)
  1103. DB_ENV **dbenvp;
  1104. LDG *ldg;
  1105. {
  1106. DB_ENV *dbenv;
  1107. int ret;
  1108. if ((ret = db_env_create(dbenvp, 0)) != 0) {
  1109. fprintf(stderr,
  1110.     "%s: db_env_create: %sn", ldg->progname, db_strerror(ret));
  1111. return (ret);
  1112. }
  1113. dbenv = *dbenvp;
  1114. dbenv->set_errfile(dbenv, stderr);
  1115. dbenv->set_errpfx(dbenv, ldg->progname);
  1116. if (ldg->passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
  1117.     ldg->passwd, DB_ENCRYPT_AES)) != 0) {
  1118. dbenv->err(dbenv, ret, "set_passwd");
  1119. return (ret);
  1120. }
  1121. if ((ret = db_init(dbenv, ldg->home, ldg->cache, &ldg->private)) != 0)
  1122. return (ret);
  1123. dbenv->app_private = ldg;
  1124. return (0);
  1125. }