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