db_load.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:21k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1996, 1997, 1998, 1999, 2000
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char copyright[] =
  10.     "Copyright (c) 1996-2000nSleepycat Software Inc.  All rights reserved.n";
  11. static const char revid[] =
  12.     "$Id: db_load.c,v 11.33 2001/01/22 17:25:07 krinsky 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 "db_page.h"
  24. #include "db_am.h"
  25. #include "clib_ext.h"
  26. void badend __P((void));
  27. void badnum __P((void));
  28. int configure __P((DB *, char **, char **, int *));
  29. int db_init __P((char *));
  30. int dbt_rdump __P((DBT *));
  31. int dbt_rprint __P((DBT *));
  32. int dbt_rrecno __P((DBT *, int));
  33. int digitize __P((int, int *));
  34. int load __P((char *, DBTYPE, char **, int, u_int32_t));
  35. int main __P((int, char *[]));
  36. int rheader __P((DB *, DBTYPE *, char **, int *, int *));
  37. void usage __P((void));
  38. void version_check __P((void));
  39. int endodata; /* Reached the end of a database. */
  40. int endofile; /* Reached the end of the input. */
  41. int existed; /* Tried to load existing key. */
  42. u_long lineno; /* Input file line number. */
  43. int version = 1; /* Input version. */
  44. DB_ENV *dbenv;
  45. const char
  46. *progname = "db_load"; /* Program name. */
  47. int
  48. main(argc, argv)
  49. int argc;
  50. char *argv[];
  51. {
  52. extern char *optarg;
  53. extern int optind;
  54. DBTYPE dbtype;
  55. u_int32_t db_nooverwrite;
  56. int ch, exitval, no_header, ret;
  57. char **clist, **clp, *home;
  58. version_check();
  59. home = NULL;
  60. db_nooverwrite = 0;
  61. exitval = no_header = 0;
  62. dbtype = DB_UNKNOWN;
  63. /* Allocate enough room for configuration arguments. */
  64. if ((clp = clist = (char **)calloc(argc + 1, sizeof(char *))) == NULL) {
  65. fprintf(stderr, "%s: %sn", progname, strerror(ENOMEM));
  66. exit(1);
  67. }
  68. while ((ch = getopt(argc, argv, "c:f:h:nTt:V")) != EOF)
  69. switch (ch) {
  70. case 'c':
  71. *clp++ = optarg;
  72. break;
  73. case 'f':
  74. if (freopen(optarg, "r", stdin) == NULL) {
  75. fprintf(stderr, "%s: %s: reopen: %sn",
  76.     progname, optarg, strerror(errno));
  77. exit(1);
  78. }
  79. break;
  80. case 'h':
  81. home = optarg;
  82. break;
  83. case 'n':
  84. db_nooverwrite = DB_NOOVERWRITE;
  85. break;
  86. case 'T':
  87. no_header = 1;
  88. break;
  89. case 't':
  90. if (strcmp(optarg, "btree") == 0) {
  91. dbtype = DB_BTREE;
  92. break;
  93. }
  94. if (strcmp(optarg, "hash") == 0) {
  95. dbtype = DB_HASH;
  96. break;
  97. }
  98. if (strcmp(optarg, "recno") == 0) {
  99. dbtype = DB_RECNO;
  100. break;
  101. }
  102. if (strcmp(optarg, "queue") == 0) {
  103. dbtype = DB_QUEUE;
  104. break;
  105. }
  106. usage();
  107. /* NOTREACHED */
  108. case 'V':
  109. printf("%sn", db_version(NULL, NULL, NULL));
  110. exit(0);
  111. case '?':
  112. default:
  113. usage();
  114. /* NOTREACHED */
  115. }
  116. argc -= optind;
  117. argv += optind;
  118. if (argc != 1)
  119. usage();
  120. /* Handle possible interruptions. */
  121. __db_util_siginit();
  122. /*
  123.  * Create an environment object initialized for error reporting, and
  124.  * then open it.
  125.  */
  126. if ((ret = db_env_create(&dbenv, 0)) != 0) {
  127. fprintf(stderr,
  128.     "%s: db_env_create: %sn", progname, db_strerror(ret));
  129. goto shutdown;
  130. }
  131. dbenv->set_errfile(dbenv, stderr);
  132. dbenv->set_errpfx(dbenv, progname);
  133. if (db_init(home) != 0)
  134. goto shutdown;
  135. while (!endofile)
  136. if (load(argv[0],
  137.     dbtype, clist, no_header, db_nooverwrite) != 0)
  138. goto shutdown;
  139. if (0) {
  140. shutdown: exitval = 1;
  141. }
  142. if ((ret = dbenv->close(dbenv, 0)) != 0) {
  143. exitval = 1;
  144. fprintf(stderr,
  145.     "%s: dbenv->close: %sn", progname, db_strerror(ret));
  146. }
  147. /* Resend any caught signal. */
  148. __db_util_sigresend();
  149. /* Return 0 on success, 1 if keys existed already, and 2 on failure. */
  150. return (exitval == 0 ? (existed == 0 ? 0 : 1) : 2);
  151. }
  152. /*
  153.  * load --
  154.  * Load a database.
  155.  */
  156. int
  157. load(name, argtype, clist, no_header, db_nooverwrite)
  158. char *name, **clist;
  159. DBTYPE argtype;
  160. int no_header;
  161. u_int32_t db_nooverwrite;
  162. {
  163. DB *dbp;
  164. DBT key, rkey, data, *readp, *writep;
  165. DBTYPE dbtype;
  166. DB_TXN *ctxn, *txn;
  167. db_recno_t recno, datarecno;
  168. int checkprint, hexkeys, keys, ret, rval;
  169. int keyflag, ascii_recno;
  170. char *subdb;
  171. endodata = 0;
  172. subdb = NULL;
  173. ctxn = txn = NULL;
  174. memset(&key, 0, sizeof(DBT));
  175. memset(&data, 0, sizeof(DBT));
  176. memset(&rkey, 0, sizeof(DBT));
  177. /* Create the DB object. */
  178. if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
  179. dbenv->err(dbenv, ret, "db_create");
  180. return (1);
  181. }
  182. dbtype = DB_UNKNOWN;
  183. keys = -1;
  184. hexkeys = -1;
  185. keyflag = -1;
  186. /* Read the header -- if there's no header, we expect flat text. */
  187. if (no_header) {
  188. checkprint = 1;
  189. dbtype = argtype;
  190. } else {
  191. if (rheader(dbp, &dbtype, &subdb, &checkprint, &keys) != 0)
  192. goto err;
  193. if (endofile)
  194. goto done;
  195. }
  196. /*
  197.  * Apply command-line configuration changes.  (We apply command-line
  198.  * configuration changes to all databases that are loaded, e.g., all
  199.  * subdatabases.)
  200.  */
  201. if (configure(dbp, clist, &subdb, &keyflag))
  202. goto err;
  203. if (keys != 1) {
  204. if (keyflag == 1) {
  205. dbp->err(dbp, EINVAL, "No keys specified in file");
  206. goto err;
  207. }
  208. }
  209. else if (keyflag == 0) {
  210. dbp->err(dbp, EINVAL, "Keys specified in file");
  211. goto err;
  212. }
  213. else
  214. keyflag = 1;
  215. if (dbtype == DB_BTREE || dbtype == DB_HASH) {
  216. if (keyflag == 0)
  217. dbp->err(dbp,
  218.     EINVAL, "Btree and Hash must specify keys");
  219. else
  220. keyflag = 1;
  221. }
  222. if (argtype != DB_UNKNOWN) {
  223. if (dbtype == DB_RECNO || dbtype == DB_QUEUE)
  224. if (keyflag != 1 && argtype != DB_RECNO
  225.      && argtype != DB_QUEUE) {
  226. dbenv->errx(dbenv,
  227.    "improper database type conversion specified");
  228. goto err;
  229. }
  230. dbtype = argtype;
  231. }
  232. if (dbtype == DB_UNKNOWN) {
  233. dbenv->errx(dbenv, "no database type specified");
  234. goto err;
  235. }
  236. if (keyflag == -1)
  237. keyflag = 0;
  238. /* 
  239.  * Recno keys have only been printed in hexadecimal starting
  240.  * with db_dump format version 3 (DB 3.2).  
  241.  *
  242.  * !!! 
  243.  * Note that version is set in rheader(), which must be called before 
  244.  * this assignment.
  245.  */
  246. hexkeys = (version >= 3 && keyflag == 1 && checkprint == 0);
  247. if (keyflag == 1 && (dbtype == DB_RECNO || dbtype == DB_QUEUE))
  248. ascii_recno = 1;
  249. else
  250. ascii_recno = 0;
  251. /* Open the DB file. */
  252. if ((ret = dbp->open(dbp,
  253.     name, subdb, dbtype, DB_CREATE, __db_omode("rwrwrw"))) != 0) {
  254. dbp->err(dbp, ret, "DB->open: %s", name);
  255. goto err;
  256. }
  257. /* Initialize the key/data pair. */
  258. readp = &key;
  259. writep = &key;
  260. if (dbtype == DB_RECNO || dbtype == DB_QUEUE) {
  261. key.size = sizeof(recno);
  262. if (keyflag) {
  263. key.data = &datarecno;
  264. if (checkprint) {
  265. readp = &rkey;
  266. goto key_data;
  267. }
  268. }
  269. else
  270. key.data = &recno;
  271. } else
  272. key_data: if ((readp->data =
  273.     (void *)malloc(readp->ulen = 1024)) == NULL) {
  274. dbenv->err(dbenv, ENOMEM, NULL);
  275. goto err;
  276. }
  277. if ((data.data = (void *)malloc(data.ulen = 1024)) == NULL) {
  278. dbenv->err(dbenv, ENOMEM, NULL);
  279. goto err;
  280. }
  281. if (TXN_ON(dbenv) && (ret = txn_begin(dbenv, NULL, &txn, 0)) != 0)
  282. goto err;
  283. /* Get each key/data pair and add them to the database. */
  284. for (recno = 1; !__db_util_interrupted(); ++recno) {
  285. if (!keyflag)
  286. if (checkprint) {
  287. if (dbt_rprint(&data))
  288. goto err;
  289. } else {
  290. if (dbt_rdump(&data))
  291. goto err;
  292. }
  293. else
  294. if (checkprint) {
  295. if (dbt_rprint(readp))
  296. goto err;
  297. if (!endodata && dbt_rprint(&data))
  298. goto fmt;
  299. } else {
  300. if (ascii_recno) {
  301. if (dbt_rrecno(readp, hexkeys))
  302. goto err;
  303. } else
  304. if (dbt_rdump(readp))
  305. goto err;
  306. if (!endodata && dbt_rdump(&data)) {
  307. fmt: dbenv->errx(dbenv,
  308.     "odd number of key/data pairs");
  309. goto err;
  310. }
  311. }
  312. if (endodata)
  313. break;
  314. if (readp != writep) {
  315. if (sscanf(readp->data, "%ud", &datarecno) != 1)
  316. dbenv->errx(dbenv,
  317.     "%s: non-integer key at line: %d",
  318.     name, !keyflag ? recno : recno * 2 - 1);
  319. if (datarecno == 0)
  320. dbenv->errx(dbenv, "%s: zero key at line: %d",
  321.     name,
  322.     !keyflag ? recno : recno * 2 - 1);
  323. }
  324. retry: if (txn != NULL)
  325. if ((ret = txn_begin(dbenv, txn, &ctxn, 0)) != 0)
  326. goto err;
  327. switch (ret =
  328.     dbp->put(dbp, txn, writep, &data, db_nooverwrite)) {
  329. case 0:
  330. if (ctxn != NULL) {
  331. if ((ret =
  332.     txn_commit(ctxn, DB_TXN_NOSYNC)) != 0)
  333. goto err;
  334. ctxn = NULL;
  335. }
  336. break;
  337. case DB_KEYEXIST:
  338. existed = 1;
  339. dbenv->errx(dbenv,
  340.     "%s: line %d: key already exists, not loaded:",
  341.     name,
  342.     !keyflag ? recno : recno * 2 - 1);
  343. (void)__db_prdbt(&key, checkprint, 0, stderr,
  344.     __db_verify_callback, 0, NULL);
  345. break;
  346. case DB_LOCK_DEADLOCK:
  347. /* If we have a child txn, retry--else it's fatal. */
  348. if (ctxn != NULL) {
  349. if ((ret = txn_abort(ctxn)) != 0)
  350. goto err;
  351. ctxn = NULL;
  352. goto retry;
  353. }
  354. /* FALLTHROUGH */
  355. default:
  356. dbenv->err(dbenv, ret, NULL);
  357. if (ctxn != NULL) {
  358. (void)txn_abort(ctxn);
  359. ctxn = NULL;
  360. }
  361. goto err;
  362. }
  363. if (ctxn != NULL) {
  364. if ((ret = txn_abort(ctxn)) != 0)
  365. goto err;
  366. ctxn = NULL;
  367. }
  368. }
  369. done: rval = 0;
  370. DB_ASSERT(ctxn == NULL);
  371. if (txn != NULL && (ret = txn_commit(txn, 0)) != 0) {
  372. txn = NULL;
  373. goto err;
  374. }
  375. if (0) {
  376. err: rval = 1;
  377. DB_ASSERT(ctxn == NULL);
  378. if (txn != NULL)
  379. (void)txn_abort(txn);
  380. }
  381. /* Close the database. */
  382. if ((ret = dbp->close(dbp, 0)) != 0) {
  383. dbp->err(dbp, ret, "DB->close");
  384. rval = 1;
  385. }
  386. /* Free allocated memory. */
  387. if (subdb != NULL)
  388. free(subdb);
  389. if (dbtype != DB_RECNO && dbtype != DB_QUEUE)
  390. free(key.data);
  391. if (rkey.data != NULL)
  392. free(rkey.data);
  393. free(data.data);
  394. return (rval);
  395. }
  396. /*
  397.  * db_init --
  398.  * Initialize the environment.
  399.  */
  400. int
  401. db_init(home)
  402. char *home;
  403. {
  404. u_int32_t flags;
  405. int ret;
  406. /* We may be loading into a live environment.  Try and join. */
  407. flags = DB_USE_ENVIRON |
  408.     DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN;
  409. if (dbenv->open(dbenv, home, flags, 0) == 0)
  410. return (0);
  411. /*
  412.  * We're trying to load a database.
  413.  *
  414.  * An environment is required because we may be trying to look at
  415.  * databases in directories other than the current one.  We could
  416.  * avoid using an environment iff the -h option wasn't specified,
  417.  * but that seems like more work than it's worth.
  418.  *
  419.  * No environment exists (or, at least no environment that includes
  420.  * an mpool region exists).  Create one, but make it private so that
  421.  * no files are actually created.
  422.  */
  423. LF_CLR(DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN);
  424. LF_SET(DB_CREATE | DB_PRIVATE);
  425. if ((ret = dbenv->open(dbenv, home, flags, 0)) == 0)
  426. return (0);
  427. /* An environment is required. */
  428. dbenv->err(dbenv, ret, "DBENV->open");
  429. return (1);
  430. }
  431. #define FLAG(name, value, keyword, flag)
  432. if (strcmp(name, keyword) == 0) {
  433. switch (*value) {
  434. case '1':
  435. if ((ret = dbp->set_flags(dbp, flag)) != 0) {
  436. dbp->err(dbp, ret, "%s: set_flags: %s",
  437.     progname, name);
  438. return (1);
  439. }
  440. break;
  441. case '0':
  442. break;
  443. default:
  444. badnum();
  445. return (1);
  446. }
  447. continue;
  448. }
  449. #define NUMBER(name, value, keyword, func)
  450. if (strcmp(name, keyword) == 0) {
  451. if (__db_getlong(dbp,
  452.     NULL, value, 1, LONG_MAX, &val) != 0)
  453. return (1);
  454. if ((ret = dbp->func(dbp, val)) != 0)
  455. goto nameerr;
  456. continue;
  457. }
  458. #define STRING(name, value, keyword, func)
  459. if (strcmp(name, keyword) == 0) {
  460. if ((ret = dbp->func(dbp, value[0])) != 0)
  461. goto nameerr;
  462. continue;
  463. }
  464. /*
  465.  * configure --
  466.  * Handle command-line configuration options.
  467.  */
  468. int
  469. configure(dbp, clp, subdbp, keysp)
  470. DB *dbp;
  471. char **clp, **subdbp;
  472. int *keysp;
  473. {
  474. long val;
  475. int ret, savech;
  476. char *name, *value;
  477. for (; (name = *clp) != NULL; *--value = savech, ++clp) {
  478. if ((value = strchr(name, '=')) == NULL) {
  479. dbp->errx(dbp,
  480.     "command-line configuration uses name=value format");
  481. return (1);
  482. }
  483. savech = *value;
  484. *value++ = '';
  485. if (strcmp(name, "database") == 0 ||
  486.     strcmp(name, "subdatabase") == 0) {
  487. if ((*subdbp = strdup(value)) == NULL) {
  488. dbp->err(dbp, ENOMEM, NULL);
  489. return (1);
  490. }
  491. continue;
  492. }
  493. if (strcmp(name, "keys") == 0) {
  494. if (strcmp(value, "1") == 0)
  495. *keysp = 1;
  496. else if (strcmp(value, "0") == 0)
  497. *keysp = 0;
  498. else {
  499. badnum();
  500. return (1);
  501. }
  502. continue;
  503. }
  504. #ifdef notyet
  505. NUMBER(name, value, "bt_maxkey", set_bt_maxkey);
  506. #endif
  507. NUMBER(name, value, "bt_minkey", set_bt_minkey);
  508. NUMBER(name, value, "db_lorder", set_lorder);
  509. NUMBER(name, value, "db_pagesize", set_pagesize);
  510. FLAG(name, value, "duplicates", DB_DUP);
  511. FLAG(name, value, "dupsort", DB_DUPSORT);
  512. NUMBER(name, value, "h_ffactor", set_h_ffactor);
  513. NUMBER(name, value, "h_nelem", set_h_nelem);
  514. NUMBER(name, value, "re_len", set_re_len);
  515. STRING(name, value, "re_pad", set_re_pad);
  516. FLAG(name, value, "recnum", DB_RECNUM);
  517. FLAG(name, value, "renumber", DB_RENUMBER);
  518. dbp->errx(dbp,
  519.     "unknown command-line configuration keyword");
  520. return (1);
  521. }
  522. return (0);
  523. nameerr:
  524. dbp->err(dbp, ret, "%s: %s=%s", progname, name, value);
  525. return (1);
  526. }
  527. /*
  528.  * rheader --
  529.  * Read the header message.
  530.  */
  531. int
  532. rheader(dbp, dbtypep, subdbp, checkprintp, keysp)
  533. DB *dbp;
  534. DBTYPE *dbtypep;
  535. char **subdbp;
  536. int *checkprintp, *keysp;
  537. {
  538. long val;
  539. int first, ret;
  540. char *name, *value, *p, buf[128];
  541. *dbtypep = DB_UNKNOWN;
  542. *checkprintp = 0;
  543. for (first = 1;; first = 0) {
  544. ++lineno;
  545. /* If we don't see the expected information, it's an error. */
  546. if (fgets(buf, sizeof(buf), stdin) == NULL) {
  547. if (!first || ferror(stdin))
  548. goto badfmt;
  549. endofile = 1;
  550. break;
  551. }
  552. if ((p = strchr(name = buf, '=')) == NULL)
  553. goto badfmt;
  554. *p++ = '';
  555. if ((p = strchr(value = p, 'n')) == NULL)
  556. goto badfmt;
  557. *p = '';
  558. if (name[0] == '' || value[0] == '')
  559. goto badfmt;
  560. if (strcmp(name, "HEADER") == 0)
  561. break;
  562. if (strcmp(name, "VERSION") == 0) {
  563. /*
  564.  * Version 1 didn't have a "VERSION" header line.  We
  565.  * only support versions 1, 2, and 3 of the dump format.
  566.  */
  567. version = atoi(value);
  568. if (version > 3) {
  569. dbp->errx(dbp,
  570.     "line %lu: VERSION %d is unsupported",
  571.     lineno, version);
  572. return (1);
  573. }
  574. continue;
  575. }
  576. if (strcmp(name, "format") == 0) {
  577. if (strcmp(value, "bytevalue") == 0) {
  578. *checkprintp = 0;
  579. continue;
  580. }
  581. if (strcmp(value, "print") == 0) {
  582. *checkprintp = 1;
  583. continue;
  584. }
  585. goto badfmt;
  586. }
  587. if (strcmp(name, "type") == 0) {
  588. if (strcmp(value, "btree") == 0) {
  589. *dbtypep = DB_BTREE;
  590. continue;
  591. }
  592. if (strcmp(value, "hash") == 0) {
  593. *dbtypep = DB_HASH;
  594. continue;
  595. }
  596. if (strcmp(value, "recno") == 0) {
  597. *dbtypep = DB_RECNO;
  598. continue;
  599. }
  600. if (strcmp(value, "queue") == 0) {
  601. *dbtypep = DB_QUEUE;
  602. continue;
  603. }
  604. dbp->errx(dbp, "line %lu: unknown type", lineno);
  605. return (1);
  606. }
  607. if (strcmp(name, "database") == 0 ||
  608.     strcmp(name, "subdatabase") == 0) {
  609. if ((*subdbp = strdup(value)) == NULL) {
  610. dbp->err(dbp, ENOMEM, NULL);
  611. return (1);
  612. }
  613. continue;
  614. }
  615. if (strcmp(name, "keys") == 0) {
  616. if (strcmp(value, "1") == 0)
  617. *keysp = 1;
  618. else if (strcmp(value, "0") == 0)
  619. *keysp = 0;
  620. else {
  621. badnum();
  622. return (1);
  623. }
  624. continue;
  625. }
  626. #ifdef notyet
  627. NUMBER(name, value, "bt_maxkey", set_bt_maxkey);
  628. #endif
  629. NUMBER(name, value, "bt_minkey", set_bt_minkey);
  630. NUMBER(name, value, "db_lorder", set_lorder);
  631. NUMBER(name, value, "db_pagesize", set_pagesize);
  632. FLAG(name, value, "duplicates", DB_DUP);
  633. FLAG(name, value, "dupsort", DB_DUPSORT);
  634. NUMBER(name, value, "h_ffactor", set_h_ffactor);
  635. NUMBER(name, value, "h_nelem", set_h_nelem);
  636. NUMBER(name, value, "re_len", set_re_len);
  637. STRING(name, value, "re_pad", set_re_pad);
  638. FLAG(name, value, "recnum", DB_RECNUM);
  639. FLAG(name, value, "renumber", DB_RENUMBER);
  640. dbp->errx(dbp,
  641.     "unknown input-file header configuration keyword");
  642. return (1);
  643. }
  644. return (0);
  645. nameerr:
  646. dbp->err(dbp, ret, "%s: %s=%s", progname, name, value);
  647. return (1);
  648. badfmt:
  649. dbp->errx(dbp, "line %lu: unexpected format", lineno);
  650. return (1);
  651. }
  652. /*
  653.  * dbt_rprint --
  654.  * Read a printable line into a DBT structure.
  655.  */
  656. int
  657. dbt_rprint(dbtp)
  658. DBT *dbtp;
  659. {
  660. u_int32_t len;
  661. u_int8_t *p;
  662. int c1, c2, e, escape, first;
  663. char buf[32];
  664. ++lineno;
  665. first = 1;
  666. e = escape = 0;
  667. for (p = dbtp->data, len = 0; (c1 = getchar()) != 'n';) {
  668. if (c1 == EOF) {
  669. if (len == 0) {
  670. endofile = endodata = 1;
  671. return (0);
  672. }
  673. badend();
  674. return (1);
  675. }
  676. if (first) {
  677. first = 0;
  678. if (version > 1) {
  679. if (c1 != ' ') {
  680. buf[0] = c1;
  681. if (fgets(buf + 1,
  682.     sizeof(buf) - 1, stdin) == NULL ||
  683.     strcmp(buf, "DATA=ENDn") != 0) {
  684. badend();
  685. return (1);
  686. }
  687. endodata = 1;
  688. return (0);
  689. }
  690. continue;
  691. }
  692. }
  693. if (escape) {
  694. if (c1 != '\') {
  695. if ((c2 = getchar()) == EOF) {
  696. badend();
  697. return (1);
  698. }
  699. c1 = digitize(c1, &e) << 4 | digitize(c2, &e);
  700. if (e)
  701. return (1);
  702. }
  703. escape = 0;
  704. } else
  705. if (c1 == '\') {
  706. escape = 1;
  707. continue;
  708. }
  709. if (len >= dbtp->ulen - 10) {
  710. dbtp->ulen *= 2;
  711. if ((dbtp->data =
  712.     (void *)realloc(dbtp->data, dbtp->ulen)) == NULL) {
  713. dbenv->err(dbenv, ENOMEM, NULL);
  714. return (1);
  715. }
  716. p = (u_int8_t *)dbtp->data + len;
  717. }
  718. ++len;
  719. *p++ = c1;
  720. }
  721. dbtp->size = len;
  722. return (0);
  723. }
  724. /*
  725.  * dbt_rdump --
  726.  * Read a byte dump line into a DBT structure.
  727.  */
  728. int
  729. dbt_rdump(dbtp)
  730. DBT *dbtp;
  731. {
  732. u_int32_t len;
  733. u_int8_t *p;
  734. int c1, c2, e, first;
  735. char buf[32];
  736. ++lineno;
  737. first = 1;
  738. e = 0;
  739. for (p = dbtp->data, len = 0; (c1 = getchar()) != 'n';) {
  740. if (c1 == EOF) {
  741. if (len == 0) {
  742. endofile = endodata = 1;
  743. return (0);
  744. }
  745. badend();
  746. return (1);
  747. }
  748. if (first) {
  749. first = 0;
  750. if (version > 1) {
  751. if (c1 != ' ') {
  752. buf[0] = c1;
  753. if (fgets(buf + 1,
  754.     sizeof(buf) - 1, stdin) == NULL ||
  755.     strcmp(buf, "DATA=ENDn") != 0) {
  756. badend();
  757. return (1);
  758. }
  759. endodata = 1;
  760. return (0);
  761. }
  762. continue;
  763. }
  764. }
  765. if ((c2 = getchar()) == EOF) {
  766. badend();
  767. return (1);
  768. }
  769. if (len >= dbtp->ulen - 10) {
  770. dbtp->ulen *= 2;
  771. if ((dbtp->data =
  772.     (void *)realloc(dbtp->data, dbtp->ulen)) == NULL) {
  773. dbenv->err(dbenv, ENOMEM, NULL);
  774. return (1);
  775. }
  776. p = (u_int8_t *)dbtp->data + len;
  777. }
  778. ++len;
  779. *p++ = digitize(c1, &e) << 4 | digitize(c2, &e);
  780. if (e)
  781. return (1);
  782. }
  783. dbtp->size = len;
  784. return (0);
  785. }
  786. /*
  787.  * dbt_rrecno --
  788.  * Read a record number dump line into a DBT structure.
  789.  */
  790. int
  791. dbt_rrecno(dbtp, ishex)
  792. DBT *dbtp;
  793. int ishex;
  794. {
  795. char buf[32], *p, *q;
  796. ++lineno;
  797. if (fgets(buf, sizeof(buf), stdin) == NULL) {
  798. endofile = endodata = 1;
  799. return (0);
  800. }
  801. if (strcmp(buf, "DATA=ENDn") == 0) {
  802. endodata = 1;
  803. return (0);
  804. }
  805. if (buf[0] != ' ')
  806. goto bad;
  807. /*
  808.  * If we're expecting a hex key, do an in-place conversion
  809.  * of hex to straight ASCII before calling __db_getulong().
  810.  */
  811. if (ishex) {
  812. for (p = q = buf + 1; *q != '' && *q != 'n';) {
  813. /*
  814.  * 0-9 in hex are 0x30-0x39, so this is easy.
  815.  * We should alternate between 3's and [0-9], and
  816.  * if the [0-9] are something unexpected,
  817.  * __db_getulong will fail, so we only need to catch
  818.  * end-of-string conditions.
  819.  */
  820. if (*q++ != '3')
  821. goto bad;
  822. if (*q == 'n' || *q == '')
  823. goto bad;
  824. *p++ = *q++;
  825. }
  826. *p = '';
  827. }
  828. if (__db_getulong(NULL,
  829.     progname, buf + 1, 0, 0, (u_long *)dbtp->data)) {
  830. bad: badend();
  831. return (1);
  832. }
  833. dbtp->size = sizeof(db_recno_t);
  834. return (0);
  835. }
  836. /*
  837.  * digitize --
  838.  * Convert a character to an integer.
  839.  */
  840. int
  841. digitize(c, errorp)
  842. int c, *errorp;
  843. {
  844. switch (c) { /* Don't depend on ASCII ordering. */
  845. case '0': return (0);
  846. case '1': return (1);
  847. case '2': return (2);
  848. case '3': return (3);
  849. case '4': return (4);
  850. case '5': return (5);
  851. case '6': return (6);
  852. case '7': return (7);
  853. case '8': return (8);
  854. case '9': return (9);
  855. case 'a': return (10);
  856. case 'b': return (11);
  857. case 'c': return (12);
  858. case 'd': return (13);
  859. case 'e': return (14);
  860. case 'f': return (15);
  861. }
  862. dbenv->errx(dbenv, "unexpected hexadecimal value");
  863. *errorp = 1;
  864. return (0);
  865. }
  866. /*
  867.  * badnum --
  868.  * Display the bad number message.
  869.  */
  870. void
  871. badnum()
  872. {
  873. dbenv->errx(dbenv,
  874.     "boolean name=value pairs require a value of 0 or 1");
  875. }
  876. /*
  877.  * badend --
  878.  * Display the bad end to input message.
  879.  */
  880. void
  881. badend()
  882. {
  883. dbenv->errx(dbenv, "unexpected end of input data or key/data pair");
  884. }
  885. /*
  886.  * usage --
  887.  * Display the usage message.
  888.  */
  889. void
  890. usage()
  891. {
  892. (void)fprintf(stderr, "%snt%sn",
  893.     "usage: db_load [-nTV]",
  894.     "[-c name=value] [-f file] [-h home] [-t btree | hash | recno] db_file");
  895. exit(1);
  896. }
  897. void
  898. version_check()
  899. {
  900. int v_major, v_minor, v_patch;
  901. /* Make sure we're loaded with the right version of the DB library. */
  902. (void)db_version(&v_major, &v_minor, &v_patch);
  903. if (v_major != DB_VERSION_MAJOR ||
  904.     v_minor != DB_VERSION_MINOR || v_patch != DB_VERSION_PATCH) {
  905. fprintf(stderr,
  906. "%s: version %d.%d.%d doesn't match library version %d.%d.%dn",
  907.     progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
  908.     DB_VERSION_PATCH, v_major, v_minor, v_patch);
  909. exit (1);
  910. }
  911. }