summaryrefslogtreecommitdiff
path: root/bdb/db_load
diff options
context:
space:
mode:
Diffstat (limited to 'bdb/db_load')
-rw-r--r--bdb/db_load/db_load.c594
1 files changed, 414 insertions, 180 deletions
diff --git a/bdb/db_load/db_load.c b/bdb/db_load/db_load.c
index 33e2eb5e02b..d27fca04ec0 100644
--- a/bdb/db_load/db_load.c
+++ b/bdb/db_load/db_load.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
@@ -9,9 +9,9 @@
#ifndef lint
static const char copyright[] =
- "Copyright (c) 1996-2000\nSleepycat Software Inc. All rights reserved.\n";
+ "Copyright (c) 1996-2002\nSleepycat Software Inc. All rights reserved.\n";
static const char revid[] =
- "$Id: db_load.c,v 11.33 2001/01/22 17:25:07 krinsky Exp $";
+ "$Id: db_load.c,v 11.71 2002/08/08 03:50:36 bostic Exp $";
#endif
#ifndef NO_SYSTEM_INCLUDES
@@ -25,33 +25,45 @@ static const char revid[] =
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "db_am.h"
-#include "clib_ext.h"
-
-void badend __P((void));
-void badnum __P((void));
-int configure __P((DB *, char **, char **, int *));
-int db_init __P((char *));
-int dbt_rdump __P((DBT *));
-int dbt_rprint __P((DBT *));
-int dbt_rrecno __P((DBT *, int));
-int digitize __P((int, int *));
-int load __P((char *, DBTYPE, char **, int, u_int32_t));
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
+
+typedef struct { /* XXX: Globals. */
+ const char *progname; /* Program name. */
+ char *hdrbuf; /* Input file header. */
+ u_long lineno; /* Input file line number. */
+ u_long origline; /* Original file line number. */
+ int endodata; /* Reached the end of a database. */
+ int endofile; /* Reached the end of the input. */
+ int version; /* Input version. */
+ char *home; /* Env home. */
+ char *passwd; /* Env passwd. */
+ int private; /* Private env. */
+ u_int32_t cache; /* Env cache size. */
+} LDG;
+
+void badend __P((DB_ENV *));
+void badnum __P((DB_ENV *));
+int configure __P((DB_ENV *, DB *, char **, char **, int *));
+int convprintable __P((DB_ENV *, char *, char **));
+int db_init __P((DB_ENV *, char *, u_int32_t, int *));
+int dbt_rdump __P((DB_ENV *, DBT *));
+int dbt_rprint __P((DB_ENV *, DBT *));
+int dbt_rrecno __P((DB_ENV *, DBT *, int));
+int digitize __P((DB_ENV *, int, int *));
+int env_create __P((DB_ENV **, LDG *));
+int load __P((DB_ENV *, char *, DBTYPE, char **, u_int, LDG *, int *));
int main __P((int, char *[]));
-int rheader __P((DB *, DBTYPE *, char **, int *, int *));
-void usage __P((void));
-void version_check __P((void));
+int rheader __P((DB_ENV *, DB *, DBTYPE *, char **, int *, int *));
+int usage __P((void));
+int version_check __P((const char *));
-int endodata; /* Reached the end of a database. */
-int endofile; /* Reached the end of the input. */
-int existed; /* Tried to load existing key. */
-u_long lineno; /* Input file line number. */
-int version = 1; /* Input version. */
+#define G(f) ((LDG *)dbenv->app_private)->f
-DB_ENV *dbenv;
-const char
- *progname = "db_load"; /* Program name. */
+ /* Flags to the load function. */
+#define LDF_NOHEADER 0x01 /* No dump header. */
+#define LDF_NOOVERWRITE 0x02 /* Don't overwrite existing rows. */
+#define LDF_PASSWORD 0x04 /* Encrypt created databases. */
int
main(argc, argv)
@@ -61,24 +73,35 @@ main(argc, argv)
extern char *optarg;
extern int optind;
DBTYPE dbtype;
- u_int32_t db_nooverwrite;
- int ch, exitval, no_header, ret;
- char **clist, **clp, *home;
-
- version_check();
-
- home = NULL;
- db_nooverwrite = 0;
- exitval = no_header = 0;
+ DB_ENV *dbenv;
+ LDG ldg;
+ u_int32_t ldf;
+ int ch, existed, exitval, ret;
+ char **clist, **clp;
+
+ ldg.progname = "db_load";
+ ldg.lineno = 0;
+ ldg.endodata = ldg.endofile = 0;
+ ldg.version = 1;
+ ldg.cache = MEGABYTE;
+ ldg.hdrbuf = NULL;
+ ldg.home = NULL;
+ ldg.passwd = NULL;
+
+ if ((ret = version_check(ldg.progname)) != 0)
+ return (ret);
+
+ ldf = 0;
+ exitval = 0;
dbtype = DB_UNKNOWN;
/* Allocate enough room for configuration arguments. */
if ((clp = clist = (char **)calloc(argc + 1, sizeof(char *))) == NULL) {
- fprintf(stderr, "%s: %s\n", progname, strerror(ENOMEM));
- exit(1);
+ fprintf(stderr, "%s: %s\n", ldg.progname, strerror(ENOMEM));
+ return (EXIT_FAILURE);
}
- while ((ch = getopt(argc, argv, "c:f:h:nTt:V")) != EOF)
+ while ((ch = getopt(argc, argv, "c:f:h:nP:Tt:V")) != EOF)
switch (ch) {
case 'c':
*clp++ = optarg;
@@ -86,18 +109,28 @@ main(argc, argv)
case 'f':
if (freopen(optarg, "r", stdin) == NULL) {
fprintf(stderr, "%s: %s: reopen: %s\n",
- progname, optarg, strerror(errno));
- exit(1);
+ ldg.progname, optarg, strerror(errno));
+ return (EXIT_FAILURE);
}
break;
case 'h':
- home = optarg;
+ ldg.home = optarg;
break;
case 'n':
- db_nooverwrite = DB_NOOVERWRITE;
+ ldf |= LDF_NOOVERWRITE;
+ break;
+ case 'P':
+ ldg.passwd = strdup(optarg);
+ memset(optarg, 0, strlen(optarg));
+ if (ldg.passwd == NULL) {
+ fprintf(stderr, "%s: strdup: %s\n",
+ ldg.progname, strerror(errno));
+ return (EXIT_FAILURE);
+ }
+ ldf |= LDF_PASSWORD;
break;
case 'T':
- no_header = 1;
+ ldf |= LDF_NOHEADER;
break;
case 't':
if (strcmp(optarg, "btree") == 0) {
@@ -116,21 +149,19 @@ main(argc, argv)
dbtype = DB_QUEUE;
break;
}
- usage();
- /* NOTREACHED */
+ return (usage());
case 'V':
printf("%s\n", db_version(NULL, NULL, NULL));
- exit(0);
+ return (EXIT_SUCCESS);
case '?':
default:
- usage();
- /* NOTREACHED */
+ return (usage());
}
argc -= optind;
argv += optind;
if (argc != 1)
- usage();
+ return (usage());
/* Handle possible interruptions. */
__db_util_siginit();
@@ -139,19 +170,12 @@ main(argc, argv)
* Create an environment object initialized for error reporting, and
* then open it.
*/
- if ((ret = db_env_create(&dbenv, 0)) != 0) {
- fprintf(stderr,
- "%s: db_env_create: %s\n", progname, db_strerror(ret));
- goto shutdown;
- }
- dbenv->set_errfile(dbenv, stderr);
- dbenv->set_errpfx(dbenv, progname);
- if (db_init(home) != 0)
+ if (env_create(&dbenv, &ldg) != 0)
goto shutdown;
- while (!endofile)
- if (load(argv[0],
- dbtype, clist, no_header, db_nooverwrite) != 0)
+ while (!ldg.endofile)
+ if (load(dbenv, argv[0], dbtype, clist, ldf,
+ &ldg, &existed) != 0)
goto shutdown;
if (0) {
@@ -160,13 +184,20 @@ shutdown: exitval = 1;
if ((ret = dbenv->close(dbenv, 0)) != 0) {
exitval = 1;
fprintf(stderr,
- "%s: dbenv->close: %s\n", progname, db_strerror(ret));
+ "%s: dbenv->close: %s\n", ldg.progname, db_strerror(ret));
}
/* Resend any caught signal. */
__db_util_sigresend();
+ free(clist);
- /* Return 0 on success, 1 if keys existed already, and 2 on failure. */
+ /*
+ * Return 0 on success, 1 if keys existed already, and 2 on failure.
+ *
+ * Technically, this is wrong, because exit of anything other than
+ * 0 is implementation-defined by the ANSI C standard. I don't see
+ * any good solutions that don't involve API changes.
+ */
return (exitval == 0 ? (existed == 0 ? 0 : 1) : 2);
}
@@ -175,32 +206,39 @@ shutdown: exitval = 1;
* Load a database.
*/
int
-load(name, argtype, clist, no_header, db_nooverwrite)
+load(dbenv, name, argtype, clist, flags, ldg, existedp)
+ DB_ENV *dbenv;
char *name, **clist;
DBTYPE argtype;
- int no_header;
- u_int32_t db_nooverwrite;
+ u_int flags;
+ LDG *ldg;
+ int *existedp;
{
DB *dbp;
DBT key, rkey, data, *readp, *writep;
DBTYPE dbtype;
DB_TXN *ctxn, *txn;
db_recno_t recno, datarecno;
- int checkprint, hexkeys, keys, ret, rval;
- int keyflag, ascii_recno;
+ u_int32_t put_flags;
+ int ascii_recno, checkprint, hexkeys, keyflag, keys, resize, ret, rval;
char *subdb;
- endodata = 0;
+ *existedp = 0;
+
+ put_flags = LF_ISSET(LDF_NOOVERWRITE) ? DB_NOOVERWRITE : 0;
+ G(endodata) = 0;
+
subdb = NULL;
ctxn = txn = NULL;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
memset(&rkey, 0, sizeof(DBT));
+retry_db:
/* Create the DB object. */
if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_create");
- return (1);
+ goto err;
}
dbtype = DB_UNKNOWN;
@@ -208,13 +246,14 @@ load(name, argtype, clist, no_header, db_nooverwrite)
hexkeys = -1;
keyflag = -1;
/* Read the header -- if there's no header, we expect flat text. */
- if (no_header) {
+ if (LF_ISSET(LDF_NOHEADER)) {
checkprint = 1;
dbtype = argtype;
} else {
- if (rheader(dbp, &dbtype, &subdb, &checkprint, &keys) != 0)
+ if (rheader(dbenv,
+ dbp, &dbtype, &subdb, &checkprint, &keys) != 0)
goto err;
- if (endofile)
+ if (G(endofile))
goto done;
}
@@ -223,7 +262,7 @@ load(name, argtype, clist, no_header, db_nooverwrite)
* configuration changes to all databases that are loaded, e.g., all
* subdatabases.)
*/
- if (configure(dbp, clist, &subdb, &keyflag))
+ if (configure(dbenv, dbp, clist, &subdb, &keyflag))
goto err;
if (keys != 1) {
@@ -250,8 +289,8 @@ load(name, argtype, clist, no_header, db_nooverwrite)
if (argtype != DB_UNKNOWN) {
if (dbtype == DB_RECNO || dbtype == DB_QUEUE)
- if (keyflag != 1 && argtype != DB_RECNO
- && argtype != DB_QUEUE) {
+ if (keyflag != 1 && argtype != DB_RECNO &&
+ argtype != DB_QUEUE) {
dbenv->errx(dbenv,
"improper database type conversion specified");
goto err;
@@ -267,27 +306,48 @@ load(name, argtype, clist, no_header, db_nooverwrite)
if (keyflag == -1)
keyflag = 0;
- /*
+ /*
* Recno keys have only been printed in hexadecimal starting
- * with db_dump format version 3 (DB 3.2).
+ * with db_dump format version 3 (DB 3.2).
*
- * !!!
- * Note that version is set in rheader(), which must be called before
+ * !!!
+ * Note that version is set in rheader(), which must be called before
* this assignment.
*/
- hexkeys = (version >= 3 && keyflag == 1 && checkprint == 0);
+ hexkeys = (G(version) >= 3 && keyflag == 1 && checkprint == 0);
if (keyflag == 1 && (dbtype == DB_RECNO || dbtype == DB_QUEUE))
ascii_recno = 1;
else
ascii_recno = 0;
+ /* If configured with a password, encrypt databases we create. */
+ if (LF_ISSET(LDF_PASSWORD) &&
+ (ret = dbp->set_flags(dbp, DB_ENCRYPT)) != 0) {
+ dbp->err(dbp, ret, "DB->set_flags: DB_ENCRYPT");
+ goto err;
+ }
+
/* Open the DB file. */
- if ((ret = dbp->open(dbp,
- name, subdb, dbtype, DB_CREATE, __db_omode("rwrwrw"))) != 0) {
+ if ((ret = dbp->open(dbp, NULL, name, subdb, dbtype,
+ DB_CREATE | (TXN_ON(dbenv) ? DB_AUTO_COMMIT : 0),
+ __db_omode("rwrwrw"))) != 0) {
dbp->err(dbp, ret, "DB->open: %s", name);
goto err;
}
+ if (ldg->private != 0) {
+ if ((ret =
+ __db_util_cache(dbenv, dbp, &ldg->cache, &resize)) != 0)
+ goto err;
+ if (resize) {
+ dbp->close(dbp, 0);
+ dbp = NULL;
+ dbenv->close(dbenv, 0);
+ if ((ret = env_create(&dbenv, ldg)) != 0)
+ goto err;
+ goto retry_db;
+ }
+ }
/* Initialize the key/data pair. */
readp = &key;
@@ -314,39 +374,40 @@ key_data: if ((readp->data =
goto err;
}
- if (TXN_ON(dbenv) && (ret = txn_begin(dbenv, NULL, &txn, 0)) != 0)
+ if (TXN_ON(dbenv) &&
+ (ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0)
goto err;
/* Get each key/data pair and add them to the database. */
for (recno = 1; !__db_util_interrupted(); ++recno) {
if (!keyflag)
if (checkprint) {
- if (dbt_rprint(&data))
+ if (dbt_rprint(dbenv, &data))
goto err;
} else {
- if (dbt_rdump(&data))
+ if (dbt_rdump(dbenv, &data))
goto err;
}
else
if (checkprint) {
- if (dbt_rprint(readp))
+ if (dbt_rprint(dbenv, readp))
goto err;
- if (!endodata && dbt_rprint(&data))
+ if (!G(endodata) && dbt_rprint(dbenv, &data))
goto fmt;
} else {
if (ascii_recno) {
- if (dbt_rrecno(readp, hexkeys))
+ if (dbt_rrecno(dbenv, readp, hexkeys))
goto err;
} else
- if (dbt_rdump(readp))
+ if (dbt_rdump(dbenv, readp))
goto err;
- if (!endodata && dbt_rdump(&data)) {
+ if (!G(endodata) && dbt_rdump(dbenv, &data)) {
fmt: dbenv->errx(dbenv,
"odd number of key/data pairs");
goto err;
}
}
- if (endodata)
+ if (G(endodata))
break;
if (readp != writep) {
if (sscanf(readp->data, "%ud", &datarecno) != 1)
@@ -359,20 +420,19 @@ fmt: dbenv->errx(dbenv,
!keyflag ? recno : recno * 2 - 1);
}
retry: if (txn != NULL)
- if ((ret = txn_begin(dbenv, txn, &ctxn, 0)) != 0)
+ if ((ret = dbenv->txn_begin(dbenv, txn, &ctxn, 0)) != 0)
goto err;
- switch (ret =
- dbp->put(dbp, txn, writep, &data, db_nooverwrite)) {
+ switch (ret = dbp->put(dbp, ctxn, writep, &data, put_flags)) {
case 0:
if (ctxn != NULL) {
if ((ret =
- txn_commit(ctxn, DB_TXN_NOSYNC)) != 0)
+ ctxn->commit(ctxn, DB_TXN_NOSYNC)) != 0)
goto err;
ctxn = NULL;
}
break;
case DB_KEYEXIST:
- existed = 1;
+ *existedp = 1;
dbenv->errx(dbenv,
"%s: line %d: key already exists, not loaded:",
name,
@@ -384,7 +444,7 @@ retry: if (txn != NULL)
case DB_LOCK_DEADLOCK:
/* If we have a child txn, retry--else it's fatal. */
if (ctxn != NULL) {
- if ((ret = txn_abort(ctxn)) != 0)
+ if ((ret = ctxn->abort(ctxn)) != 0)
goto err;
ctxn = NULL;
goto retry;
@@ -393,20 +453,20 @@ retry: if (txn != NULL)
default:
dbenv->err(dbenv, ret, NULL);
if (ctxn != NULL) {
- (void)txn_abort(ctxn);
+ (void)ctxn->abort(ctxn);
ctxn = NULL;
}
goto err;
}
if (ctxn != NULL) {
- if ((ret = txn_abort(ctxn)) != 0)
+ if ((ret = ctxn->abort(ctxn)) != 0)
goto err;
ctxn = NULL;
}
}
done: rval = 0;
DB_ASSERT(ctxn == NULL);
- if (txn != NULL && (ret = txn_commit(txn, 0)) != 0) {
+ if (txn != NULL && (ret = txn->commit(txn, 0)) != 0) {
txn = NULL;
goto err;
}
@@ -415,15 +475,18 @@ done: rval = 0;
err: rval = 1;
DB_ASSERT(ctxn == NULL);
if (txn != NULL)
- (void)txn_abort(txn);
+ (void)txn->abort(txn);
}
/* Close the database. */
- if ((ret = dbp->close(dbp, 0)) != 0) {
- dbp->err(dbp, ret, "DB->close");
+ if (dbp != NULL && (ret = dbp->close(dbp, 0)) != 0) {
+ dbenv->err(dbenv, ret, "DB->close");
rval = 1;
}
+ if (G(hdrbuf) != NULL)
+ free(G(hdrbuf));
+ G(hdrbuf) = NULL;
/* Free allocated memory. */
if (subdb != NULL)
free(subdb);
@@ -441,12 +504,16 @@ err: rval = 1;
* Initialize the environment.
*/
int
-db_init(home)
+db_init(dbenv, home, cache, is_private)
+ DB_ENV *dbenv;
char *home;
+ u_int32_t cache;
+ int *is_private;
{
u_int32_t flags;
int ret;
+ *is_private = 0;
/* We may be loading into a live environment. Try and join. */
flags = DB_USE_ENVIRON |
DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN;
@@ -467,11 +534,16 @@ db_init(home)
*/
LF_CLR(DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN);
LF_SET(DB_CREATE | DB_PRIVATE);
+ *is_private = 1;
+ if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) != 0) {
+ dbenv->err(dbenv, ret, "set_cachesize");
+ return (1);
+ }
if ((ret = dbenv->open(dbenv, home, flags, 0)) == 0)
return (0);
/* An environment is required. */
- dbenv->err(dbenv, ret, "DBENV->open");
+ dbenv->err(dbenv, ret, "DB_ENV->open");
return (1);
}
@@ -481,14 +553,14 @@ db_init(home)
case '1': \
if ((ret = dbp->set_flags(dbp, flag)) != 0) { \
dbp->err(dbp, ret, "%s: set_flags: %s", \
- progname, name); \
+ G(progname), name); \
return (1); \
} \
break; \
case '0': \
break; \
default: \
- badnum(); \
+ badnum(dbenv); \
return (1); \
} \
continue; \
@@ -514,7 +586,8 @@ db_init(home)
* Handle command-line configuration options.
*/
int
-configure(dbp, clp, subdbp, keysp)
+configure(dbenv, dbp, clp, subdbp, keysp)
+ DB_ENV *dbenv;
DB *dbp;
char **clp, **subdbp;
int *keysp;
@@ -534,6 +607,8 @@ configure(dbp, clp, subdbp, keysp)
if (strcmp(name, "database") == 0 ||
strcmp(name, "subdatabase") == 0) {
+ if (*subdbp != NULL)
+ free(*subdbp);
if ((*subdbp = strdup(value)) == NULL) {
dbp->err(dbp, ENOMEM, NULL);
return (1);
@@ -546,7 +621,7 @@ configure(dbp, clp, subdbp, keysp)
else if (strcmp(value, "0") == 0)
*keysp = 0;
else {
- badnum();
+ badnum(dbenv);
return (1);
}
continue;
@@ -558,6 +633,7 @@ configure(dbp, clp, subdbp, keysp)
NUMBER(name, value, "bt_minkey", set_bt_minkey);
NUMBER(name, value, "db_lorder", set_lorder);
NUMBER(name, value, "db_pagesize", set_pagesize);
+ FLAG(name, value, "chksum", DB_CHKSUM_SHA1);
FLAG(name, value, "duplicates", DB_DUP);
FLAG(name, value, "dupsort", DB_DUPSORT);
NUMBER(name, value, "h_ffactor", set_h_ffactor);
@@ -568,13 +644,13 @@ configure(dbp, clp, subdbp, keysp)
FLAG(name, value, "renumber", DB_RENUMBER);
dbp->errx(dbp,
- "unknown command-line configuration keyword");
+ "unknown command-line configuration keyword \"%s\"", name);
return (1);
}
return (0);
nameerr:
- dbp->err(dbp, ret, "%s: %s=%s", progname, name, value);
+ dbp->err(dbp, ret, "%s: %s=%s", G(progname), name, value);
return (1);
}
@@ -583,35 +659,91 @@ nameerr:
* Read the header message.
*/
int
-rheader(dbp, dbtypep, subdbp, checkprintp, keysp)
+rheader(dbenv, dbp, dbtypep, subdbp, checkprintp, keysp)
+ DB_ENV *dbenv;
DB *dbp;
DBTYPE *dbtypep;
char **subdbp;
int *checkprintp, *keysp;
{
long val;
- int first, ret;
- char *name, *value, *p, buf[128];
+ int ch, first, hdr, linelen, buflen, ret, start;
+ char *buf, *name, *p, *value;
*dbtypep = DB_UNKNOWN;
*checkprintp = 0;
+ name = p = NULL;
+
+ /*
+ * We start with a smallish buffer; most headers are small.
+ * We may need to realloc it for a large subdatabase name.
+ */
+ buflen = 4096;
+ if (G(hdrbuf) == NULL) {
+ hdr = 0;
+ if ((buf = (char *)malloc(buflen)) == NULL) {
+memerr: dbp->errx(dbp, "could not allocate buffer %d", buflen);
+ return (1);
+ }
+ G(hdrbuf) = buf;
+ G(origline) = G(lineno);
+ } else {
+ hdr = 1;
+ buf = G(hdrbuf);
+ G(lineno) = G(origline);
+ }
+ start = 0;
for (first = 1;; first = 0) {
- ++lineno;
+ ++G(lineno);
+
+ /* Read a line, which may be of arbitrary length, into buf. */
+ linelen = 0;
+ buf = &G(hdrbuf)[start];
+ if (hdr == 0) {
+ for (;;) {
+ if ((ch = getchar()) == EOF) {
+ if (!first || ferror(stdin))
+ goto badfmt;
+ G(endofile) = 1;
+ break;
+ }
- /* If we don't see the expected information, it's an error. */
- if (fgets(buf, sizeof(buf), stdin) == NULL) {
- if (!first || ferror(stdin))
- goto badfmt;
- endofile = 1;
- break;
+ if (ch == '\n')
+ break;
+
+ buf[linelen++] = ch;
+
+ /* If the buffer is too small, double it. */
+ if (linelen + start == buflen) {
+ G(hdrbuf) = (char *)realloc(G(hdrbuf),
+ buflen *= 2);
+ if (G(hdrbuf) == NULL)
+ goto memerr;
+ buf = &G(hdrbuf)[start];
+ }
+ }
+ if (G(endofile) == 1)
+ break;
+ buf[linelen++] = '\0';
+ } else
+ linelen = strlen(buf) + 1;
+ start += linelen;
+
+ if (name != NULL) {
+ *p = '=';
+ free(name);
+ name = NULL;
}
- if ((p = strchr(name = buf, '=')) == NULL)
+ /* If we don't see the expected information, it's an error. */
+ if ((name = strdup(buf)) == NULL)
+ goto memerr;
+ if ((p = strchr(name, '=')) == NULL)
goto badfmt;
*p++ = '\0';
- if ((p = strchr(value = p, '\n')) == NULL)
- goto badfmt;
- *p = '\0';
+
+ value = p--;
+
if (name[0] == '\0' || value[0] == '\0')
goto badfmt;
@@ -622,13 +754,13 @@ rheader(dbp, dbtypep, subdbp, checkprintp, keysp)
* Version 1 didn't have a "VERSION" header line. We
* only support versions 1, 2, and 3 of the dump format.
*/
- version = atoi(value);
+ G(version) = atoi(value);
- if (version > 3) {
+ if (G(version) > 3) {
dbp->errx(dbp,
"line %lu: VERSION %d is unsupported",
- lineno, version);
- return (1);
+ G(lineno), G(version));
+ goto err;
}
continue;
}
@@ -660,14 +792,14 @@ rheader(dbp, dbtypep, subdbp, checkprintp, keysp)
*dbtypep = DB_QUEUE;
continue;
}
- dbp->errx(dbp, "line %lu: unknown type", lineno);
- return (1);
+ dbp->errx(dbp, "line %lu: unknown type", G(lineno));
+ goto err;
}
if (strcmp(name, "database") == 0 ||
strcmp(name, "subdatabase") == 0) {
- if ((*subdbp = strdup(value)) == NULL) {
- dbp->err(dbp, ENOMEM, NULL);
- return (1);
+ if ((ret = convprintable(dbenv, value, subdbp)) != 0) {
+ dbp->err(dbp, ret, "error reading db name");
+ goto err;
}
continue;
}
@@ -677,8 +809,8 @@ rheader(dbp, dbtypep, subdbp, checkprintp, keysp)
else if (strcmp(value, "0") == 0)
*keysp = 0;
else {
- badnum();
- return (1);
+ badnum(dbenv);
+ goto err;
}
continue;
}
@@ -689,6 +821,8 @@ rheader(dbp, dbtypep, subdbp, checkprintp, keysp)
NUMBER(name, value, "bt_minkey", set_bt_minkey);
NUMBER(name, value, "db_lorder", set_lorder);
NUMBER(name, value, "db_pagesize", set_pagesize);
+ NUMBER(name, value, "extentsize", set_q_extentsize);
+ FLAG(name, value, "chksum", DB_CHKSUM_SHA1);
FLAG(name, value, "duplicates", DB_DUP);
FLAG(name, value, "dupsort", DB_DUPSORT);
NUMBER(name, value, "h_ffactor", set_h_ffactor);
@@ -699,18 +833,81 @@ rheader(dbp, dbtypep, subdbp, checkprintp, keysp)
FLAG(name, value, "renumber", DB_RENUMBER);
dbp->errx(dbp,
- "unknown input-file header configuration keyword");
- return (1);
+ "unknown input-file header configuration keyword \"%s\"",
+ name);
+ goto err;
}
- return (0);
-
+ ret = 0;
+ if (0) {
nameerr:
- dbp->err(dbp, ret, "%s: %s=%s", progname, name, value);
- return (1);
-
+ dbp->err(dbp, ret, "%s: %s=%s", G(progname), name, value);
+ ret = 1;
+ }
+ if (0)
+err: ret = 1;
+ if (0) {
badfmt:
- dbp->errx(dbp, "line %lu: unexpected format", lineno);
- return (1);
+ dbp->errx(dbp, "line %lu: unexpected format", G(lineno));
+ ret = 1;
+ }
+ if (name != NULL) {
+ *p = '=';
+ free(name);
+ }
+ return (ret);
+}
+
+/*
+ * convprintable --
+ * Convert a printable-encoded string into a newly allocated string.
+ *
+ * In an ideal world, this would probably share code with dbt_rprint, but
+ * that's set up to read character-by-character (to avoid large memory
+ * allocations that aren't likely to be a problem here), and this has fewer
+ * special cases to deal with.
+ *
+ * Note that despite the printable encoding, the char * interface to this
+ * function (which is, not coincidentally, also used for database naming)
+ * means that outstr cannot contain any nuls.
+ */
+int
+convprintable(dbenv, instr, outstrp)
+ DB_ENV *dbenv;
+ char *instr, **outstrp;
+{
+ char c, *outstr;
+ int e1, e2;
+
+ /*
+ * Just malloc a string big enough for the whole input string;
+ * the output string will be smaller (or of equal length).
+ */
+ if ((outstr = (char *)malloc(strlen(instr))) == NULL)
+ return (ENOMEM);
+
+ *outstrp = outstr;
+
+ e1 = e2 = 0;
+ for ( ; *instr != '\0'; instr++)
+ if (*instr == '\\') {
+ if (*++instr == '\\') {
+ *outstr++ = '\\';
+ continue;
+ }
+ c = digitize(dbenv, *instr, &e1) << 4;
+ c |= digitize(dbenv, *++instr, &e2);
+ if (e1 || e2) {
+ badend(dbenv);
+ return (EINVAL);
+ }
+
+ *outstr++ = c;
+ } else
+ *outstr++ = *instr;
+
+ *outstr = '\0';
+
+ return (0);
}
/*
@@ -718,7 +915,8 @@ badfmt:
* Read a printable line into a DBT structure.
*/
int
-dbt_rprint(dbtp)
+dbt_rprint(dbenv, dbtp)
+ DB_ENV *dbenv;
DBT *dbtp;
{
u_int32_t len;
@@ -726,31 +924,31 @@ dbt_rprint(dbtp)
int c1, c2, e, escape, first;
char buf[32];
- ++lineno;
+ ++G(lineno);
first = 1;
e = escape = 0;
for (p = dbtp->data, len = 0; (c1 = getchar()) != '\n';) {
if (c1 == EOF) {
if (len == 0) {
- endofile = endodata = 1;
+ G(endofile) = G(endodata) = 1;
return (0);
}
- badend();
+ badend(dbenv);
return (1);
}
if (first) {
first = 0;
- if (version > 1) {
+ if (G(version) > 1) {
if (c1 != ' ') {
buf[0] = c1;
if (fgets(buf + 1,
sizeof(buf) - 1, stdin) == NULL ||
strcmp(buf, "DATA=END\n") != 0) {
- badend();
+ badend(dbenv);
return (1);
}
- endodata = 1;
+ G(endodata) = 1;
return (0);
}
continue;
@@ -759,10 +957,11 @@ dbt_rprint(dbtp)
if (escape) {
if (c1 != '\\') {
if ((c2 = getchar()) == EOF) {
- badend();
+ badend(dbenv);
return (1);
}
- c1 = digitize(c1, &e) << 4 | digitize(c2, &e);
+ c1 = digitize(dbenv,
+ c1, &e) << 4 | digitize(dbenv, c2, &e);
if (e)
return (1);
}
@@ -794,7 +993,8 @@ dbt_rprint(dbtp)
* Read a byte dump line into a DBT structure.
*/
int
-dbt_rdump(dbtp)
+dbt_rdump(dbenv, dbtp)
+ DB_ENV *dbenv;
DBT *dbtp;
{
u_int32_t len;
@@ -802,38 +1002,38 @@ dbt_rdump(dbtp)
int c1, c2, e, first;
char buf[32];
- ++lineno;
+ ++G(lineno);
first = 1;
e = 0;
for (p = dbtp->data, len = 0; (c1 = getchar()) != '\n';) {
if (c1 == EOF) {
if (len == 0) {
- endofile = endodata = 1;
+ G(endofile) = G(endodata) = 1;
return (0);
}
- badend();
+ badend(dbenv);
return (1);
}
if (first) {
first = 0;
- if (version > 1) {
+ if (G(version) > 1) {
if (c1 != ' ') {
buf[0] = c1;
if (fgets(buf + 1,
sizeof(buf) - 1, stdin) == NULL ||
strcmp(buf, "DATA=END\n") != 0) {
- badend();
+ badend(dbenv);
return (1);
}
- endodata = 1;
+ G(endodata) = 1;
return (0);
}
continue;
}
}
if ((c2 = getchar()) == EOF) {
- badend();
+ badend(dbenv);
return (1);
}
if (len >= dbtp->ulen - 10) {
@@ -846,7 +1046,7 @@ dbt_rdump(dbtp)
p = (u_int8_t *)dbtp->data + len;
}
++len;
- *p++ = digitize(c1, &e) << 4 | digitize(c2, &e);
+ *p++ = digitize(dbenv, c1, &e) << 4 | digitize(dbenv, c2, &e);
if (e)
return (1);
}
@@ -860,21 +1060,22 @@ dbt_rdump(dbtp)
* Read a record number dump line into a DBT structure.
*/
int
-dbt_rrecno(dbtp, ishex)
+dbt_rrecno(dbenv, dbtp, ishex)
+ DB_ENV *dbenv;
DBT *dbtp;
int ishex;
{
char buf[32], *p, *q;
- ++lineno;
+ ++G(lineno);
if (fgets(buf, sizeof(buf), stdin) == NULL) {
- endofile = endodata = 1;
+ G(endofile) = G(endodata) = 1;
return (0);
}
if (strcmp(buf, "DATA=END\n") == 0) {
- endodata = 1;
+ G(endodata) = 1;
return (0);
}
@@ -904,8 +1105,8 @@ dbt_rrecno(dbtp, ishex)
}
if (__db_getulong(NULL,
- progname, buf + 1, 0, 0, (u_long *)dbtp->data)) {
-bad: badend();
+ G(progname), buf + 1, 0, 0, (u_long *)dbtp->data)) {
+bad: badend(dbenv);
return (1);
}
@@ -918,7 +1119,8 @@ bad: badend();
* Convert a character to an integer.
*/
int
-digitize(c, errorp)
+digitize(dbenv, c, errorp)
+ DB_ENV *dbenv;
int c, *errorp;
{
switch (c) { /* Don't depend on ASCII ordering. */
@@ -951,7 +1153,8 @@ digitize(c, errorp)
* Display the bad number message.
*/
void
-badnum()
+badnum(dbenv)
+ DB_ENV *dbenv;
{
dbenv->errx(dbenv,
"boolean name=value pairs require a value of 0 or 1");
@@ -962,7 +1165,8 @@ badnum()
* Display the bad end to input message.
*/
void
-badend()
+badend(dbenv)
+ DB_ENV *dbenv;
{
dbenv->errx(dbenv, "unexpected end of input data or key/data pair");
}
@@ -971,17 +1175,18 @@ badend()
* usage --
* Display the usage message.
*/
-void
+int
usage()
{
(void)fprintf(stderr, "%s\n\t%s\n",
- "usage: db_load [-nTV]",
- "[-c name=value] [-f file] [-h home] [-t btree | hash | recno] db_file");
- exit(1);
+ "usage: db_load [-nTV] [-c name=value] [-f file]",
+ "[-h home] [-P password] [-t btree | hash | recno | queue] db_file");
+ return (EXIT_FAILURE);
}
-void
-version_check()
+int
+version_check(progname)
+ const char *progname;
{
int v_major, v_minor, v_patch;
@@ -993,6 +1198,35 @@ version_check()
"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
DB_VERSION_PATCH, v_major, v_minor, v_patch);
- exit (1);
+ return (EXIT_FAILURE);
}
+ return (0);
+}
+
+int
+env_create(dbenvp, ldg)
+ DB_ENV **dbenvp;
+ LDG *ldg;
+{
+ DB_ENV *dbenv;
+ int ret;
+
+ if ((ret = db_env_create(dbenvp, 0)) != 0) {
+ fprintf(stderr,
+ "%s: db_env_create: %s\n", ldg->progname, db_strerror(ret));
+ return (ret);
+ }
+ dbenv = *dbenvp;
+ dbenv->set_errfile(dbenv, stderr);
+ dbenv->set_errpfx(dbenv, ldg->progname);
+ if (ldg->passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
+ ldg->passwd, DB_ENCRYPT_AES)) != 0) {
+ dbenv->err(dbenv, ret, "set_passwd");
+ return (ret);
+ }
+ if ((ret = db_init(dbenv, ldg->home, ldg->cache, &ldg->private)) != 0)
+ return (ret);
+ dbenv->app_private = ldg;
+
+ return (0);
}