2
* See the file LICENSE for redistribution information.
4
* Copyright (c) 1996-2002
5
* Sleepycat Software. All rights reserved.
11
static const char copyright[] =
12
"Copyright (c) 1996-2002\nSleepycat Software Inc. All rights reserved.\n";
13
static const char revid[] =
17
#ifndef NO_SYSTEM_INCLUDES
18
#include <sys/types.h>
28
#include "dbinc/db_page.h"
29
#include "dbinc/db_am.h"
31
typedef struct { /* XXX: Globals. */
32
const char *progname; /* Program name. */
33
char *hdrbuf; /* Input file header. */
34
u_long lineno; /* Input file line number. */
35
u_long origline; /* Original file line number. */
36
int endodata; /* Reached the end of a database. */
37
int endofile; /* Reached the end of the input. */
38
int version; /* Input version. */
39
char *home; /* Env home. */
40
char *passwd; /* Env passwd. */
41
int private; /* Private env. */
42
u_int32_t cache; /* Env cache size. */
45
void badend __P((DB_ENV *));
46
void badnum __P((DB_ENV *));
47
int configure __P((DB_ENV *, DB *, char **, char **, int *));
48
int convprintable __P((DB_ENV *, char *, char **));
49
int db_init __P((DB_ENV *, char *, u_int32_t, int *));
50
int dbt_rdump __P((DB_ENV *, DBT *));
51
int dbt_rprint __P((DB_ENV *, DBT *));
52
int dbt_rrecno __P((DB_ENV *, DBT *, int));
53
int digitize __P((DB_ENV *, int, int *));
54
int env_create __P((DB_ENV **, LDG *));
55
int load __P((DB_ENV *, char *, DBTYPE, char **, u_int, LDG *, int *));
56
int main __P((int, char *[]));
57
int rheader __P((DB_ENV *, DB *, DBTYPE *, char **, int *, int *));
58
int usage __P((void));
59
int version_check __P((const char *));
61
#define G(f) ((LDG *)dbenv->app_private)->f
63
/* Flags to the load function. */
64
#define LDF_NOHEADER 0x01 /* No dump header. */
65
#define LDF_NOOVERWRITE 0x02 /* Don't overwrite existing rows. */
66
#define LDF_PASSWORD 0x04 /* Encrypt created databases. */
79
int ch, existed, exitval, ret;
82
ldg.progname = "db_load";
84
ldg.endodata = ldg.endofile = 0;
91
if ((ret = version_check(ldg.progname)) != 0)
98
/* Allocate enough room for configuration arguments. */
99
if ((clp = clist = (char **)calloc(argc + 1, sizeof(char *))) == NULL) {
100
fprintf(stderr, "%s: %s\n", ldg.progname, strerror(ENOMEM));
101
return (EXIT_FAILURE);
104
while ((ch = getopt(argc, argv, "c:f:h:nP:Tt:V")) != EOF)
110
if (freopen(optarg, "r", stdin) == NULL) {
111
fprintf(stderr, "%s: %s: reopen: %s\n",
112
ldg.progname, optarg, strerror(errno));
113
return (EXIT_FAILURE);
120
ldf |= LDF_NOOVERWRITE;
123
ldg.passwd = strdup(optarg);
124
memset(optarg, 0, strlen(optarg));
125
if (ldg.passwd == NULL) {
126
fprintf(stderr, "%s: strdup: %s\n",
127
ldg.progname, strerror(errno));
128
return (EXIT_FAILURE);
136
if (strcmp(optarg, "btree") == 0) {
140
if (strcmp(optarg, "hash") == 0) {
144
if (strcmp(optarg, "recno") == 0) {
148
if (strcmp(optarg, "queue") == 0) {
154
printf("%s\n", db_version(NULL, NULL, NULL));
155
return (EXIT_SUCCESS);
166
/* Handle possible interruptions. */
170
* Create an environment object initialized for error reporting, and
173
if (env_create(&dbenv, &ldg) != 0)
176
while (!ldg.endofile)
177
if (load(dbenv, argv[0], dbtype, clist, ldf,
178
&ldg, &existed) != 0)
182
shutdown: exitval = 1;
184
if ((ret = dbenv->close(dbenv, 0)) != 0) {
187
"%s: dbenv->close: %s\n", ldg.progname, db_strerror(ret));
190
/* Resend any caught signal. */
191
__db_util_sigresend();
195
* Return 0 on success, 1 if keys existed already, and 2 on failure.
197
* Technically, this is wrong, because exit of anything other than
198
* 0 is implementation-defined by the ANSI C standard. I don't see
199
* any good solutions that don't involve API changes.
201
return (exitval == 0 ? (existed == 0 ? 0 : 1) : 2);
209
load(dbenv, name, argtype, clist, flags, ldg, existedp)
218
DBT key, rkey, data, *readp, *writep;
221
db_recno_t recno, datarecno;
223
int ascii_recno, checkprint, hexkeys, keyflag, keys, resize, ret, rval;
228
put_flags = LF_ISSET(LDF_NOOVERWRITE) ? DB_NOOVERWRITE : 0;
233
memset(&key, 0, sizeof(DBT));
234
memset(&data, 0, sizeof(DBT));
235
memset(&rkey, 0, sizeof(DBT));
238
/* Create the DB object. */
239
if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
240
dbenv->err(dbenv, ret, "db_create");
248
/* Read the header -- if there's no header, we expect flat text. */
249
if (LF_ISSET(LDF_NOHEADER)) {
254
dbp, &dbtype, &subdb, &checkprint, &keys) != 0)
261
* Apply command-line configuration changes. (We apply command-line
262
* configuration changes to all databases that are loaded, e.g., all
265
if (configure(dbenv, dbp, clist, &subdb, &keyflag))
270
dbp->err(dbp, EINVAL, "No keys specified in file");
274
else if (keyflag == 0) {
275
dbp->err(dbp, EINVAL, "Keys specified in file");
281
if (dbtype == DB_BTREE || dbtype == DB_HASH) {
284
EINVAL, "Btree and Hash must specify keys");
289
if (argtype != DB_UNKNOWN) {
291
if (dbtype == DB_RECNO || dbtype == DB_QUEUE)
292
if (keyflag != 1 && argtype != DB_RECNO &&
293
argtype != DB_QUEUE) {
295
"improper database type conversion specified");
301
if (dbtype == DB_UNKNOWN) {
302
dbenv->errx(dbenv, "no database type specified");
310
* Recno keys have only been printed in hexadecimal starting
311
* with db_dump format version 3 (DB 3.2).
314
* Note that version is set in rheader(), which must be called before
317
hexkeys = (G(version) >= 3 && keyflag == 1 && checkprint == 0);
319
if (keyflag == 1 && (dbtype == DB_RECNO || dbtype == DB_QUEUE))
324
/* If configured with a password, encrypt databases we create. */
325
if (LF_ISSET(LDF_PASSWORD) &&
326
(ret = dbp->set_flags(dbp, DB_ENCRYPT)) != 0) {
327
dbp->err(dbp, ret, "DB->set_flags: DB_ENCRYPT");
331
/* Open the DB file. */
332
if ((ret = dbp->open(dbp, NULL, name, subdb, dbtype,
333
DB_CREATE | (TXN_ON(dbenv) ? DB_AUTO_COMMIT : 0),
334
__db_omode("rwrwrw"))) != 0) {
335
dbp->err(dbp, ret, "DB->open: %s", name);
338
if (ldg->private != 0) {
340
__db_util_cache(dbenv, dbp, &ldg->cache, &resize)) != 0)
345
dbenv->close(dbenv, 0);
346
if ((ret = env_create(&dbenv, ldg)) != 0)
352
/* Initialize the key/data pair. */
355
if (dbtype == DB_RECNO || dbtype == DB_QUEUE) {
356
key.size = sizeof(recno);
358
key.data = &datarecno;
367
key_data: if ((readp->data =
368
(void *)malloc(readp->ulen = 1024)) == NULL) {
369
dbenv->err(dbenv, ENOMEM, NULL);
372
if ((data.data = (void *)malloc(data.ulen = 1024)) == NULL) {
373
dbenv->err(dbenv, ENOMEM, NULL);
378
(ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0)
381
/* Get each key/data pair and add them to the database. */
382
for (recno = 1; !__db_util_interrupted(); ++recno) {
385
if (dbt_rprint(dbenv, &data))
388
if (dbt_rdump(dbenv, &data))
393
if (dbt_rprint(dbenv, readp))
395
if (!G(endodata) && dbt_rprint(dbenv, &data))
399
if (dbt_rrecno(dbenv, readp, hexkeys))
402
if (dbt_rdump(dbenv, readp))
404
if (!G(endodata) && dbt_rdump(dbenv, &data)) {
405
fmt: dbenv->errx(dbenv,
406
"odd number of key/data pairs");
412
if (readp != writep) {
413
if (sscanf(readp->data, "%ud", &datarecno) != 1)
415
"%s: non-integer key at line: %d",
416
name, !keyflag ? recno : recno * 2 - 1);
418
dbenv->errx(dbenv, "%s: zero key at line: %d",
420
!keyflag ? recno : recno * 2 - 1);
422
retry: if (txn != NULL)
423
if ((ret = dbenv->txn_begin(dbenv, txn, &ctxn, 0)) != 0)
425
switch (ret = dbp->put(dbp, ctxn, writep, &data, put_flags)) {
429
ctxn->commit(ctxn, DB_TXN_NOSYNC)) != 0)
437
"%s: line %d: key already exists, not loaded:",
439
!keyflag ? recno : recno * 2 - 1);
441
(void)__db_prdbt(&key, checkprint, 0, stderr,
442
__db_verify_callback, 0, NULL);
444
case DB_LOCK_DEADLOCK:
445
/* If we have a child txn, retry--else it's fatal. */
447
if ((ret = ctxn->abort(ctxn)) != 0)
454
dbenv->err(dbenv, ret, NULL);
456
(void)ctxn->abort(ctxn);
462
if ((ret = ctxn->abort(ctxn)) != 0)
468
DB_ASSERT(ctxn == NULL);
469
if (txn != NULL && (ret = txn->commit(txn, 0)) != 0) {
476
DB_ASSERT(ctxn == NULL);
478
(void)txn->abort(txn);
481
/* Close the database. */
482
if (dbp != NULL && (ret = dbp->close(dbp, 0)) != 0) {
483
dbenv->err(dbenv, ret, "DB->close");
487
if (G(hdrbuf) != NULL)
490
/* Free allocated memory. */
493
if (dbtype != DB_RECNO && dbtype != DB_QUEUE)
495
if (rkey.data != NULL)
504
* Initialize the environment.
507
db_init(dbenv, home, cache, is_private)
517
/* We may be loading into a live environment. Try and join. */
518
flags = DB_USE_ENVIRON |
519
DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN;
520
if (dbenv->open(dbenv, home, flags, 0) == 0)
524
* We're trying to load a database.
526
* An environment is required because we may be trying to look at
527
* databases in directories other than the current one. We could
528
* avoid using an environment iff the -h option wasn't specified,
529
* but that seems like more work than it's worth.
531
* No environment exists (or, at least no environment that includes
532
* an mpool region exists). Create one, but make it private so that
533
* no files are actually created.
535
LF_CLR(DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN);
536
LF_SET(DB_CREATE | DB_PRIVATE);
538
if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) != 0) {
539
dbenv->err(dbenv, ret, "set_cachesize");
542
if ((ret = dbenv->open(dbenv, home, flags, 0)) == 0)
545
/* An environment is required. */
546
dbenv->err(dbenv, ret, "DB_ENV->open");
550
#define FLAG(name, value, keyword, flag) \
551
if (strcmp(name, keyword) == 0) { \
554
if ((ret = dbp->set_flags(dbp, flag)) != 0) { \
555
dbp->err(dbp, ret, "%s: set_flags: %s", \
556
G(progname), name); \
568
#define NUMBER(name, value, keyword, func) \
569
if (strcmp(name, keyword) == 0) { \
570
if (__db_getlong(dbp, \
571
NULL, value, 1, LONG_MAX, &val) != 0) \
573
if ((ret = dbp->func(dbp, val)) != 0) \
577
#define STRING(name, value, keyword, func) \
578
if (strcmp(name, keyword) == 0) { \
579
if ((ret = dbp->func(dbp, value[0])) != 0) \
586
* Handle command-line configuration options.
589
configure(dbenv, dbp, clp, subdbp, keysp)
592
char **clp, **subdbp;
599
for (; (name = *clp) != NULL; *--value = savech, ++clp) {
600
if ((value = strchr(name, '=')) == NULL) {
602
"command-line configuration uses name=value format");
608
if (strcmp(name, "database") == 0 ||
609
strcmp(name, "subdatabase") == 0) {
612
if ((*subdbp = strdup(value)) == NULL) {
613
dbp->err(dbp, ENOMEM, NULL);
618
if (strcmp(name, "keys") == 0) {
619
if (strcmp(value, "1") == 0)
621
else if (strcmp(value, "0") == 0)
631
NUMBER(name, value, "bt_maxkey", set_bt_maxkey);
633
NUMBER(name, value, "bt_minkey", set_bt_minkey);
634
NUMBER(name, value, "db_lorder", set_lorder);
635
NUMBER(name, value, "db_pagesize", set_pagesize);
636
FLAG(name, value, "chksum", DB_CHKSUM_SHA1);
637
FLAG(name, value, "duplicates", DB_DUP);
638
FLAG(name, value, "dupsort", DB_DUPSORT);
639
NUMBER(name, value, "h_ffactor", set_h_ffactor);
640
NUMBER(name, value, "h_nelem", set_h_nelem);
641
NUMBER(name, value, "re_len", set_re_len);
642
STRING(name, value, "re_pad", set_re_pad);
643
FLAG(name, value, "recnum", DB_RECNUM);
644
FLAG(name, value, "renumber", DB_RENUMBER);
647
"unknown command-line configuration keyword \"%s\"", name);
653
dbp->err(dbp, ret, "%s: %s=%s", G(progname), name, value);
659
* Read the header message.
662
rheader(dbenv, dbp, dbtypep, subdbp, checkprintp, keysp)
667
int *checkprintp, *keysp;
670
int ch, first, hdr, linelen, buflen, ret, start;
671
char *buf, *name, *p, *value;
673
*dbtypep = DB_UNKNOWN;
678
* We start with a smallish buffer; most headers are small.
679
* We may need to realloc it for a large subdatabase name.
682
if (G(hdrbuf) == NULL) {
684
if ((buf = (char *)malloc(buflen)) == NULL) {
685
memerr: dbp->errx(dbp, "could not allocate buffer %d", buflen);
689
G(origline) = G(lineno);
693
G(lineno) = G(origline);
697
for (first = 1;; first = 0) {
700
/* Read a line, which may be of arbitrary length, into buf. */
702
buf = &G(hdrbuf)[start];
705
if ((ch = getchar()) == EOF) {
706
if (!first || ferror(stdin))
717
/* If the buffer is too small, double it. */
718
if (linelen + start == buflen) {
719
G(hdrbuf) = (char *)realloc(G(hdrbuf),
721
if (G(hdrbuf) == NULL)
723
buf = &G(hdrbuf)[start];
726
if (G(endofile) == 1)
728
buf[linelen++] = '\0';
730
linelen = strlen(buf) + 1;
738
/* If we don't see the expected information, it's an error. */
739
if ((name = strdup(buf)) == NULL)
741
if ((p = strchr(name, '=')) == NULL)
747
if (name[0] == '\0' || value[0] == '\0')
750
if (strcmp(name, "HEADER") == 0)
752
if (strcmp(name, "VERSION") == 0) {
754
* Version 1 didn't have a "VERSION" header line. We
755
* only support versions 1, 2, and 3 of the dump format.
757
G(version) = atoi(value);
759
if (G(version) > 3) {
761
"line %lu: VERSION %d is unsupported",
762
G(lineno), G(version));
767
if (strcmp(name, "format") == 0) {
768
if (strcmp(value, "bytevalue") == 0) {
772
if (strcmp(value, "print") == 0) {
778
if (strcmp(name, "type") == 0) {
779
if (strcmp(value, "btree") == 0) {
783
if (strcmp(value, "hash") == 0) {
787
if (strcmp(value, "recno") == 0) {
791
if (strcmp(value, "queue") == 0) {
795
dbp->errx(dbp, "line %lu: unknown type", G(lineno));
798
if (strcmp(name, "database") == 0 ||
799
strcmp(name, "subdatabase") == 0) {
800
if ((ret = convprintable(dbenv, value, subdbp)) != 0) {
801
dbp->err(dbp, ret, "error reading db name");
806
if (strcmp(name, "keys") == 0) {
807
if (strcmp(value, "1") == 0)
809
else if (strcmp(value, "0") == 0)
819
NUMBER(name, value, "bt_maxkey", set_bt_maxkey);
821
NUMBER(name, value, "bt_minkey", set_bt_minkey);
822
NUMBER(name, value, "db_lorder", set_lorder);
823
NUMBER(name, value, "db_pagesize", set_pagesize);
824
NUMBER(name, value, "extentsize", set_q_extentsize);
825
FLAG(name, value, "chksum", DB_CHKSUM_SHA1);
826
FLAG(name, value, "duplicates", DB_DUP);
827
FLAG(name, value, "dupsort", DB_DUPSORT);
828
NUMBER(name, value, "h_ffactor", set_h_ffactor);
829
NUMBER(name, value, "h_nelem", set_h_nelem);
830
NUMBER(name, value, "re_len", set_re_len);
831
STRING(name, value, "re_pad", set_re_pad);
832
FLAG(name, value, "recnum", DB_RECNUM);
833
FLAG(name, value, "renumber", DB_RENUMBER);
836
"unknown input-file header configuration keyword \"%s\"",
843
dbp->err(dbp, ret, "%s: %s=%s", G(progname), name, value);
850
dbp->errx(dbp, "line %lu: unexpected format", G(lineno));
862
* Convert a printable-encoded string into a newly allocated string.
864
* In an ideal world, this would probably share code with dbt_rprint, but
865
* that's set up to read character-by-character (to avoid large memory
866
* allocations that aren't likely to be a problem here), and this has fewer
867
* special cases to deal with.
869
* Note that despite the printable encoding, the char * interface to this
870
* function (which is, not coincidentally, also used for database naming)
871
* means that outstr cannot contain any nuls.
874
convprintable(dbenv, instr, outstrp)
876
char *instr, **outstrp;
882
* Just malloc a string big enough for the whole input string;
883
* the output string will be smaller (or of equal length).
885
if ((outstr = (char *)malloc(strlen(instr))) == NULL)
891
for ( ; *instr != '\0'; instr++)
892
if (*instr == '\\') {
893
if (*++instr == '\\') {
897
c = digitize(dbenv, *instr, &e1) << 4;
898
c |= digitize(dbenv, *++instr, &e2);
915
* Read a printable line into a DBT structure.
918
dbt_rprint(dbenv, dbtp)
924
int c1, c2, e, escape, first;
931
for (p = dbtp->data, len = 0; (c1 = getchar()) != '\n';) {
934
G(endofile) = G(endodata) = 1;
942
if (G(version) > 1) {
946
sizeof(buf) - 1, stdin) == NULL ||
947
strcmp(buf, "DATA=END\n") != 0) {
959
if ((c2 = getchar()) == EOF) {
964
c1, &e) << 4 | digitize(dbenv, c2, &e);
974
if (len >= dbtp->ulen - 10) {
977
(void *)realloc(dbtp->data, dbtp->ulen)) == NULL) {
978
dbenv->err(dbenv, ENOMEM, NULL);
981
p = (u_int8_t *)dbtp->data + len;
993
* Read a byte dump line into a DBT structure.
996
dbt_rdump(dbenv, dbtp)
1002
int c1, c2, e, first;
1009
for (p = dbtp->data, len = 0; (c1 = getchar()) != '\n';) {
1012
G(endofile) = G(endodata) = 1;
1020
if (G(version) > 1) {
1024
sizeof(buf) - 1, stdin) == NULL ||
1025
strcmp(buf, "DATA=END\n") != 0) {
1035
if ((c2 = getchar()) == EOF) {
1039
if (len >= dbtp->ulen - 10) {
1042
(void *)realloc(dbtp->data, dbtp->ulen)) == NULL) {
1043
dbenv->err(dbenv, ENOMEM, NULL);
1046
p = (u_int8_t *)dbtp->data + len;
1049
*p++ = digitize(dbenv, c1, &e) << 4 | digitize(dbenv, c2, &e);
1060
* Read a record number dump line into a DBT structure.
1063
dbt_rrecno(dbenv, dbtp, ishex)
1068
char buf[32], *p, *q;
1072
if (fgets(buf, sizeof(buf), stdin) == NULL) {
1073
G(endofile) = G(endodata) = 1;
1077
if (strcmp(buf, "DATA=END\n") == 0) {
1086
* If we're expecting a hex key, do an in-place conversion
1087
* of hex to straight ASCII before calling __db_getulong().
1090
for (p = q = buf + 1; *q != '\0' && *q != '\n';) {
1092
* 0-9 in hex are 0x30-0x39, so this is easy.
1093
* We should alternate between 3's and [0-9], and
1094
* if the [0-9] are something unexpected,
1095
* __db_getulong will fail, so we only need to catch
1096
* end-of-string conditions.
1100
if (*q == '\n' || *q == '\0')
1107
if (__db_getulong(NULL,
1108
G(progname), buf + 1, 0, 0, (u_long *)dbtp->data)) {
1113
dbtp->size = sizeof(db_recno_t);
1119
* Convert a character to an integer.
1122
digitize(dbenv, c, errorp)
1126
switch (c) { /* Don't depend on ASCII ordering. */
1127
case '0': return (0);
1128
case '1': return (1);
1129
case '2': return (2);
1130
case '3': return (3);
1131
case '4': return (4);
1132
case '5': return (5);
1133
case '6': return (6);
1134
case '7': return (7);
1135
case '8': return (8);
1136
case '9': return (9);
1137
case 'a': return (10);
1138
case 'b': return (11);
1139
case 'c': return (12);
1140
case 'd': return (13);
1141
case 'e': return (14);
1142
case 'f': return (15);
1145
dbenv->errx(dbenv, "unexpected hexadecimal value");
1153
* Display the bad number message.
1160
"boolean name=value pairs require a value of 0 or 1");
1165
* Display the bad end to input message.
1171
dbenv->errx(dbenv, "unexpected end of input data or key/data pair");
1176
* Display the usage message.
1181
(void)fprintf(stderr, "%s\n\t%s\n",
1182
"usage: db_load [-nTV] [-c name=value] [-f file]",
1183
"[-h home] [-P password] [-t btree | hash | recno | queue] db_file");
1184
return (EXIT_FAILURE);
1188
version_check(progname)
1189
const char *progname;
1191
int v_major, v_minor, v_patch;
1193
/* Make sure we're loaded with the right version of the DB library. */
1194
(void)db_version(&v_major, &v_minor, &v_patch);
1195
if (v_major != DB_VERSION_MAJOR ||
1196
v_minor != DB_VERSION_MINOR || v_patch != DB_VERSION_PATCH) {
1198
"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
1199
progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
1200
DB_VERSION_PATCH, v_major, v_minor, v_patch);
1201
return (EXIT_FAILURE);
1207
env_create(dbenvp, ldg)
1214
if ((ret = db_env_create(dbenvp, 0)) != 0) {
1216
"%s: db_env_create: %s\n", ldg->progname, db_strerror(ret));
1220
dbenv->set_errfile(dbenv, stderr);
1221
dbenv->set_errpfx(dbenv, ldg->progname);
1222
if (ldg->passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
1223
ldg->passwd, DB_ENCRYPT_AES)) != 0) {
1224
dbenv->err(dbenv, ret, "set_passwd");
1227
if ((ret = db_init(dbenv, ldg->home, ldg->cache, &ldg->private)) != 0)
1229
dbenv->app_private = ldg;