• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src/router/db-4.8.30/build_vxworks/db_dump/
1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 1996-2009 Oracle.  All rights reserved.
5 *
6 * $Id$
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-2009 Oracle.  All rights reserved.\n";
18#endif
19
20int	 db_dump_db_init __P((DB_ENV *, char *, int, u_int32_t, int *));
21int	 db_dump_dump_sub __P((DB_ENV *, DB *, char *, int, int));
22int	 db_dump_main __P((int, char *[]));
23int	 db_dump_show_subs __P((DB *));
24int	 db_dump_usage __P((void));
25int	 db_dump_version_check __P((void));
26
27const char *progname;
28
29int
30db_dump(args)
31	char *args;
32{
33	int argc;
34	char **argv;
35
36	__db_util_arg("db_dump", args, &argc, &argv);
37	return (db_dump_main(argc, argv) ? EXIT_FAILURE : EXIT_SUCCESS);
38}
39
40#include <stdio.h>
41#define	ERROR_RETURN	ERROR
42
43int
44db_dump_main(argc, argv)
45	int argc;
46	char *argv[];
47{
48	extern char *optarg;
49	extern int optind, __db_getopt_reset;
50	DB_ENV	*dbenv;
51	DB *dbp;
52	u_int32_t cache;
53	int ch;
54	int exitval, keyflag, lflag, mflag, nflag, pflag, sflag, private;
55	int ret, Rflag, rflag, resize;
56	char *dbname, *dopt, *filename, *home, *passwd;
57
58	if ((progname = __db_rpath(argv[0])) == NULL)
59		progname = argv[0];
60	else
61		++progname;
62
63	if ((ret = db_dump_version_check()) != 0)
64		return (ret);
65
66	dbenv = NULL;
67	dbp = NULL;
68	exitval = lflag = mflag = nflag = pflag = rflag = Rflag = sflag = 0;
69	keyflag = 0;
70	cache = MEGABYTE;
71	private = 0;
72	dbname = dopt = filename = home = passwd = NULL;
73	__db_getopt_reset = 1;
74	while ((ch = getopt(argc, argv, "d:f:h:klm:NpP:rRs:V")) != EOF)
75		switch (ch) {
76		case 'd':
77			dopt = optarg;
78			break;
79		case 'f':
80			if (freopen(optarg, "w", stdout) == NULL) {
81				fprintf(stderr, "%s: %s: reopen: %s\n",
82				    progname, optarg, strerror(errno));
83				return (EXIT_FAILURE);
84			}
85			break;
86		case 'h':
87			home = optarg;
88			break;
89		case 'k':
90			keyflag = 1;
91			break;
92		case 'l':
93			lflag = 1;
94			break;
95		case 'm':
96			mflag = 1;
97			dbname = optarg;
98			break;
99		case 'N':
100			nflag = 1;
101			break;
102		case 'P':
103			passwd = strdup(optarg);
104			memset(optarg, 0, strlen(optarg));
105			if (passwd == NULL) {
106				fprintf(stderr, "%s: strdup: %s\n",
107				    progname, strerror(errno));
108				return (EXIT_FAILURE);
109			}
110			break;
111		case 'p':
112			pflag = 1;
113			break;
114		case 's':
115			sflag = 1;
116			dbname = optarg;
117			break;
118		case 'R':
119			Rflag = 1;
120			/* DB_AGGRESSIVE requires DB_SALVAGE */
121			/* FALLTHROUGH */
122		case 'r':
123			rflag = 1;
124			break;
125		case 'V':
126			printf("%s\n", db_version(NULL, NULL, NULL));
127			return (EXIT_SUCCESS);
128		case '?':
129		default:
130			return (db_dump_usage());
131		}
132	argc -= optind;
133	argv += optind;
134
135	/*
136	 * A file name must be specified, unless we're looking for an in-memory
137	 * db,  in which case it must not.
138	 */
139	if (argc == 0 && mflag)
140		filename = NULL;
141	else if (argc == 1 && !mflag)
142		filename = argv[0];
143	else
144		return (db_dump_usage());
145
146	if (dopt != NULL && pflag) {
147		fprintf(stderr,
148		    "%s: the -d and -p options may not both be specified\n",
149		    progname);
150		return (EXIT_FAILURE);
151	}
152	if (lflag && sflag) {
153		fprintf(stderr,
154		    "%s: the -l and -s options may not both be specified\n",
155		    progname);
156		return (EXIT_FAILURE);
157	}
158	if ((lflag || sflag) && mflag) {
159		fprintf(stderr,
160		    "%s: the -m option may not be specified with -l or -s\n",
161		    progname);
162		return (EXIT_FAILURE);
163	}
164
165	if (keyflag && rflag) {
166		fprintf(stderr, "%s: %s",
167		    "the -k and -r or -R options may not both be specified\n",
168		    progname);
169		return (EXIT_FAILURE);
170	}
171
172	if ((mflag || sflag) && rflag) {
173		fprintf(stderr, "%s: %s",
174		    "the -r or R options may not be specified with -m or -s\n",
175		    progname);
176		return (EXIT_FAILURE);
177	}
178
179	/* Handle possible interruptions. */
180	__db_util_siginit();
181
182	/*
183	 * Create an environment object and initialize it for error
184	 * reporting.
185	 */
186retry:	if ((ret = db_env_create(&dbenv, 0)) != 0) {
187		fprintf(stderr,
188		    "%s: db_env_create: %s\n", progname, db_strerror(ret));
189		goto err;
190	}
191
192	dbenv->set_errfile(dbenv, stderr);
193	dbenv->set_errpfx(dbenv, progname);
194	if (nflag) {
195		if ((ret = dbenv->set_flags(dbenv, DB_NOLOCKING, 1)) != 0) {
196			dbenv->err(dbenv, ret, "set_flags: DB_NOLOCKING");
197			goto err;
198		}
199		if ((ret = dbenv->set_flags(dbenv, DB_NOPANIC, 1)) != 0) {
200			dbenv->err(dbenv, ret, "set_flags: DB_NOPANIC");
201			goto err;
202		}
203	}
204	if (passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
205	    passwd, DB_ENCRYPT_AES)) != 0) {
206		dbenv->err(dbenv, ret, "set_passwd");
207		goto err;
208	}
209
210	/* Initialize the environment. */
211	if (db_dump_db_init(dbenv, home, rflag, cache, &private) != 0)
212		goto err;
213
214	/* Create the DB object and open the file. */
215	if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
216		dbenv->err(dbenv, ret, "db_create");
217		goto err;
218	}
219
220#if 0
221	Set application-specific btree compression functions here. For example:
222	if ((ret = dbp->set_bt_compress(
223	    dbp, local_compress_func, local_decompress_func)) != 0) {
224		dbp->err(dbp, ret, "DB->set_bt_compress");
225		goto err;
226	}
227#endif
228
229	/*
230	 * If we're salvaging, don't do an open;  it might not be safe.
231	 * Dispatch now into the salvager.
232	 */
233	if (rflag) {
234		/* The verify method is a destructor. */
235		ret = dbp->verify(dbp, filename, NULL, stdout,
236		    DB_SALVAGE |
237		    (Rflag ? DB_AGGRESSIVE : 0) |
238		    (pflag ? DB_PRINTABLE : 0));
239		dbp = NULL;
240		if (ret != 0)
241			goto err;
242		goto done;
243	}
244
245	if ((ret = dbp->open(dbp, NULL,
246	    filename, dbname, DB_UNKNOWN, DB_RDWRMASTER|DB_RDONLY, 0)) != 0) {
247		dbp->err(dbp, ret, "open: %s",
248		    filename == NULL ? dbname : filename);
249		goto err;
250	}
251	if (private != 0) {
252		if ((ret = __db_util_cache(dbp, &cache, &resize)) != 0)
253			goto err;
254		if (resize) {
255			(void)dbp->close(dbp, 0);
256			dbp = NULL;
257
258			(void)dbenv->close(dbenv, 0);
259			dbenv = NULL;
260			goto retry;
261		}
262	}
263
264	if (dopt != NULL) {
265		if ((ret = __db_dumptree(dbp, NULL, dopt, NULL)) != 0) {
266			dbp->err(dbp, ret, "__db_dumptree: %s", filename);
267			goto err;
268		}
269	} else if (lflag) {
270		if (dbp->get_multiple(dbp)) {
271			if (db_dump_show_subs(dbp))
272				goto err;
273		} else {
274			dbp->errx(dbp,
275			    "%s: does not contain multiple databases",
276			    filename);
277			goto err;
278		}
279	} else {
280		if (dbname == NULL && dbp->get_multiple(dbp)) {
281			if (db_dump_dump_sub(dbenv, dbp, filename, pflag, keyflag))
282				goto err;
283		} else
284			if (dbp->dump(dbp, NULL,
285			    __db_pr_callback, stdout, pflag, keyflag))
286				goto err;
287	}
288
289	if (0) {
290err:		exitval = 1;
291	}
292done:	if (dbp != NULL && (ret = dbp->close(dbp, 0)) != 0) {
293		exitval = 1;
294		dbenv->err(dbenv, ret, "close");
295	}
296	if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0) {
297		exitval = 1;
298		fprintf(stderr,
299		    "%s: dbenv->close: %s\n", progname, db_strerror(ret));
300	}
301
302	if (passwd != NULL)
303		free(passwd);
304
305	/* Resend any caught signal. */
306	__db_util_sigresend();
307
308	return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
309}
310
311/*
312 * db_init --
313 *	Initialize the environment.
314 */
315int
316db_dump_db_init(dbenv, home, is_salvage, cache, is_privatep)
317	DB_ENV *dbenv;
318	char *home;
319	int is_salvage;
320	u_int32_t cache;
321	int *is_privatep;
322{
323	int ret;
324
325	/*
326	 * Try and use the underlying environment when opening a database.
327	 * We wish to use the buffer pool so our information is as up-to-date
328	 * as possible, even if the mpool cache hasn't been flushed.
329	 *
330	 * If we are not doing a salvage, we want to join the environment;
331	 * if a locking system is present, this will let us use it and be
332	 * safe to run concurrently with other threads of control.  (We never
333	 * need to use transactions explicitly, as we're read-only.)  Note
334	 * that in CDB, too, this will configure our environment
335	 * appropriately, and our cursors will (correctly) do locking as CDB
336	 * read cursors.
337	 *
338	 * If we are doing a salvage, the verification code will protest
339	 * if we initialize transactions, logging, or locking;  do an
340	 * explicit DB_INIT_MPOOL to try to join any existing environment
341	 * before we create our own.
342	 */
343	*is_privatep = 0;
344	if ((ret = dbenv->open(dbenv, home,
345	    DB_USE_ENVIRON | (is_salvage ? DB_INIT_MPOOL : 0), 0)) == 0)
346		return (0);
347	if (ret == DB_VERSION_MISMATCH)
348		goto err;
349
350	/*
351	 * An environment is required because we may be trying to look at
352	 * databases in directories other than the current one.  We could
353	 * avoid using an environment iff the -h option wasn't specified,
354	 * but that seems like more work than it's worth.
355	 *
356	 * No environment exists (or, at least no environment that includes
357	 * an mpool region exists).  Create one, but make it private so that
358	 * no files are actually created.
359	 */
360	*is_privatep = 1;
361	if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) == 0 &&
362	    (ret = dbenv->open(dbenv, home,
363	    DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0)) == 0)
364		return (0);
365
366	/* An environment is required. */
367err:	dbenv->err(dbenv, ret, "DB_ENV->open");
368	return (1);
369}
370
371/*
372 * dump_sub --
373 *	Dump out the records for a DB containing subdatabases.
374 */
375int
376db_dump_dump_sub(dbenv, parent_dbp, parent_name, pflag, keyflag)
377	DB_ENV *dbenv;
378	DB *parent_dbp;
379	char *parent_name;
380	int pflag, keyflag;
381{
382	DB *dbp;
383	DBC *dbcp;
384	DBT key, data;
385	int ret;
386	char *subdb;
387
388	/*
389	 * Get a cursor and step through the database, dumping out each
390	 * subdatabase.
391	 */
392	if ((ret = parent_dbp->cursor(parent_dbp, NULL, &dbcp, 0)) != 0) {
393		dbenv->err(dbenv, ret, "DB->cursor");
394		return (1);
395	}
396
397	memset(&key, 0, sizeof(key));
398	memset(&data, 0, sizeof(data));
399	while ((ret = dbcp->get(dbcp, &key, &data,
400	    DB_IGNORE_LEASE | DB_NEXT)) == 0) {
401		/* Nul terminate the subdatabase name. */
402		if ((subdb = malloc(key.size + 1)) == NULL) {
403			dbenv->err(dbenv, ENOMEM, NULL);
404			return (1);
405		}
406		memcpy(subdb, key.data, key.size);
407		subdb[key.size] = '\0';
408
409		/* Create the DB object and open the file. */
410		if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
411			dbenv->err(dbenv, ret, "db_create");
412			free(subdb);
413			return (1);
414		}
415
416#if 0
417		Set application-specific btree compression functions here.
418		For example:
419
420		if ((ret = dbp->set_bt_compress(
421		    dbp, local_compress_func, local_decompress_func)) != 0) {
422			dbp->err(dbp, ret, "DB->set_bt_compress");
423			goto err;
424		}
425#endif
426
427		if ((ret = dbp->open(dbp, NULL,
428		    parent_name, subdb, DB_UNKNOWN, DB_RDONLY, 0)) != 0)
429			dbp->err(dbp, ret,
430			    "DB->open: %s:%s", parent_name, subdb);
431		if (ret == 0 && dbp->dump(
432		    dbp, subdb, __db_pr_callback, stdout, pflag, keyflag))
433			ret = 1;
434		(void)dbp->close(dbp, 0);
435		free(subdb);
436		if (ret != 0)
437			return (1);
438	}
439	if (ret != DB_NOTFOUND) {
440		parent_dbp->err(parent_dbp, ret, "DBcursor->get");
441		return (1);
442	}
443
444	if ((ret = dbcp->close(dbcp)) != 0) {
445		parent_dbp->err(parent_dbp, ret, "DBcursor->close");
446		return (1);
447	}
448
449	return (0);
450}
451
452/*
453 * show_subs --
454 *	Display the subdatabases for a database.
455 */
456int
457db_dump_show_subs(dbp)
458	DB *dbp;
459{
460	DBC *dbcp;
461	DBT key, data;
462	int ret;
463
464	/*
465	 * Get a cursor and step through the database, printing out the key
466	 * of each key/data pair.
467	 */
468	if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) {
469		dbp->err(dbp, ret, "DB->cursor");
470		return (1);
471	}
472
473	memset(&key, 0, sizeof(key));
474	memset(&data, 0, sizeof(data));
475	while ((ret = dbcp->get(dbcp, &key, &data,
476	    DB_IGNORE_LEASE | DB_NEXT)) == 0) {
477		if ((ret = dbp->dbenv->prdbt(
478		    &key, 1, NULL, stdout, __db_pr_callback, 0)) != 0) {
479			dbp->errx(dbp, NULL);
480			return (1);
481		}
482	}
483	if (ret != DB_NOTFOUND) {
484		dbp->err(dbp, ret, "DBcursor->get");
485		return (1);
486	}
487
488	if ((ret = dbcp->close(dbcp)) != 0) {
489		dbp->err(dbp, ret, "DBcursor->close");
490		return (1);
491	}
492	return (0);
493}
494
495/*
496 * usage --
497 *	Display the usage message.
498 */
499int
500db_dump_usage()
501{
502	(void)fprintf(stderr, "usage: %s [-klNprRV]\n\t%s\n",
503	    progname,
504    "[-d ahr] [-f output] [-h home] [-P password] [-s database] db_file");
505	(void)fprintf(stderr, "usage: %s [-kNpV] %s\n",
506	    progname, "[-d ahr] [-f output] [-h home] -m database");
507	return (EXIT_FAILURE);
508}
509
510int
511db_dump_version_check()
512{
513	int v_major, v_minor, v_patch;
514
515	/* Make sure we're loaded with the right version of the DB library. */
516	(void)db_version(&v_major, &v_minor, &v_patch);
517	if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
518		fprintf(stderr,
519	"%s: version %d.%d doesn't match library version %d.%d\n",
520		    progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
521		    v_major, v_minor);
522		return (EXIT_FAILURE);
523	}
524	return (0);
525}
526