1 /* mdb_load.c - memory-mapped database load tool */
3 * Copyright 2011-2014 Howard Chu, Symas Corp.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted only as authorized by the OpenLDAP
10 * A copy of this license is available in the file LICENSE in the
11 * top-level directory of the distribution or, alternatively, at
12 * <http://www.OpenLDAP.org/license.html>.
26 static char *subname = NULL;
37 static MDB_val kbuf, dbuf;
39 #define STRLENOF(s) (sizeof(s)-1)
41 typedef struct flagbit {
47 #define S(s) s, STRLENOF(s)
50 { MDB_REVERSEKEY, S("reversekey") },
51 { MDB_DUPSORT, S("dupsort") },
52 { MDB_INTEGERKEY, S("integerkey") },
53 { MDB_DUPFIXED, S("dupfixed") },
54 { MDB_INTEGERDUP, S("integerdup") },
55 { MDB_REVERSEDUP, S("reversedup") },
59 static const char hexc[] = "0123456789abcdef";
65 while (fgets(dbuf.mv_data, dbuf.mv_size, stdin) != NULL) {
67 if (!strncmp(dbuf.mv_data, "VERSION=", STRLENOF("VERSION="))) {
68 version=atoi(dbuf.mv_data+STRLENOF("VERSION="));
70 fprintf(stderr, "%s: line %zd: unsupported VERSION %d\n",
71 prog, lineno, version);
74 } else if (!strncmp(dbuf.mv_data, "HEADER=END", STRLENOF("HEADER=END"))) {
76 } else if (!strncmp(dbuf.mv_data, "format=", STRLENOF("format="))) {
77 if (!strncmp(dbuf.mv_data+STRLENOF("FORMAT="), "print", STRLENOF("print")))
79 else if (strncmp(dbuf.mv_data+STRLENOF("FORMAT="), "bytevalue", STRLENOF("bytevalue"))) {
80 fprintf(stderr, "%s: line %zd: unsupported FORMAT %s\n",
81 prog, lineno, (char *)dbuf.mv_data+STRLENOF("FORMAT="));
84 } else if (!strncmp(dbuf.mv_data, "database=", STRLENOF("database="))) {
85 ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size);
87 if (subname) free(subname);
88 subname = strdup(dbuf.mv_data+STRLENOF("database="));
89 } else if (!strncmp(dbuf.mv_data, "type=", STRLENOF("type="))) {
90 if (strncmp(dbuf.mv_data+STRLENOF("type="), "btree", STRLENOF("btree"))) {
91 fprintf(stderr, "%s: line %zd: unsupported type %s\n",
92 prog, lineno, (char *)dbuf.mv_data+STRLENOF("type="));
97 for (i=0; dbflags[i].bit; i++) {
98 if (!strncmp(dbuf.mv_data, dbflags[i].name, dbflags[i].len) &&
99 ((char *)dbuf.mv_data)[dbflags[i].len] == '=') {
100 flags |= dbflags[i].bit;
104 if (!dbflags[i].bit) {
105 ptr = memchr(dbuf.mv_data, '=', dbuf.mv_size);
107 fprintf(stderr, "%s: line %zd: unexpected format\n",
112 fprintf(stderr, "%s: line %zd: unrecognized keyword ignored: %s\n",
113 prog, lineno, (char *)dbuf.mv_data);
122 fprintf(stderr, "%s: line %zd: unexpected end of input\n",
126 static int unhex(unsigned char *c2)
140 static int readline(MDB_val *out, MDB_val *buf)
142 unsigned char *c1, *c2, *end;
146 if (!(mode & NOHDR)) {
153 if (fgets(buf->mv_data, buf->mv_size, stdin) == NULL) {
159 if (c == 'D' && !strncmp(buf->mv_data, "ATA=END", STRLENOF("ATA=END")))
164 if (fgets(buf->mv_data, buf->mv_size, stdin) == NULL) {
171 len = strlen((char *)c1);
173 /* Is buffer too short? */
174 while (c1[len-1] != '\n') {
175 buf->mv_data = realloc(buf->mv_data, buf->mv_size*2);
178 fprintf(stderr, "%s: line %zd: out of memory, line too long\n",
184 if (fgets((char *)c1, buf->mv_size, stdin) == NULL) {
190 len = strlen((char *)c1);
192 c1 = c2 = buf->mv_data;
193 len = strlen((char *)c1);
203 if (c2+3 >= end || !isxdigit(c2[1]) || !isxdigit(c2[2])) {
216 /* odd length not allowed */
223 if (!isxdigit(*c2) || !isxdigit(c2[1])) {
232 c2 = out->mv_data = buf->mv_data;
233 out->mv_size = c1 - c2;
240 fprintf(stderr, "usage: %s dbpath [-V] [-f input] [-n] [-s name] [-N] [-T]\n", prog);
244 int main(int argc, char *argv[])
252 int envflags = 0, putflags = 0;
260 /* -f: load file instead of stdin
261 * -n: use NOSUBDIR flag on env_open
262 * -s: load into named subDB
263 * -N: use NOOVERWRITE on puts
265 * -V: print version and exit
267 while ((i = getopt(argc, argv, "f:ns:NTV")) != EOF) {
270 printf("%s\n", MDB_VERSION_STRING);
274 if (freopen(optarg, "r", stdin) == NULL) {
275 fprintf(stderr, "%s: %s: reopen: %s\n",
276 prog, optarg, strerror(errno));
281 envflags |= MDB_NOSUBDIR;
284 subname = strdup(optarg);
287 putflags = MDB_NOOVERWRITE|MDB_NODUPDATA;
297 if (optind != argc - 1)
300 envname = argv[optind];
301 rc = mdb_env_create(&env);
304 mdb_env_set_maxdbs(env, 2);
307 rc = mdb_env_open(env, envname, envflags, 0664);
309 printf("mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc));
313 kbuf.mv_size = mdb_env_get_maxkeysize(env) * 2 + 2;
314 kbuf.mv_data = malloc(kbuf.mv_size);
316 dbuf.mv_data = malloc(dbuf.mv_size);
326 rc = mdb_txn_begin(env, NULL, 0, &txn);
328 printf("mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc));
332 rc = mdb_open(txn, subname, flags, &dbi);
334 printf("mdb_open failed, error %d %s\n", rc, mdb_strerror(rc));
338 rc = mdb_cursor_open(txn, dbi, &mc);
340 printf("mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
345 rc = readline(&key, &kbuf);
351 rc = readline(&data, &dbuf);
355 rc = mdb_cursor_put(mc, &key, &data, putflags);
356 if (rc == MDB_KEYEXIST && putflags)
362 rc = mdb_txn_commit(txn);
364 fprintf(stderr, "%s: line %zd: txn_commit: %s\n",
365 prog, lineno, mdb_strerror(rc));
368 rc = mdb_txn_begin(env, NULL, 0, &txn);
370 printf("mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc));
373 rc = mdb_cursor_open(txn, dbi, &mc);
375 printf("mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
381 rc = mdb_txn_commit(txn);
384 fprintf(stderr, "%s: line %zd: txn_commit: %s\n",
385 prog, lineno, mdb_strerror(rc));
388 mdb_dbi_close(env, dbi);
396 return rc ? EXIT_FAILURE : EXIT_SUCCESS;