1 /* mdb_load.c - memory-mapped database load tool */
3 * Copyright 2011-2018 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;
28 static mdb_size_t lineno;
37 static MDB_envinfo info;
39 static MDB_val kbuf, dbuf;
41 #define Yu MDB_PRIy(u)
43 #define STRLENOF(s) (sizeof(s)-1)
45 typedef struct flagbit {
51 #define S(s) s, STRLENOF(s)
54 { MDB_REVERSEKEY, S("reversekey") },
55 { MDB_DUPSORT, S("dupsort") },
56 { MDB_INTEGERKEY, S("integerkey") },
57 { MDB_DUPFIXED, S("dupfixed") },
58 { MDB_INTEGERDUP, S("integerdup") },
59 { MDB_REVERSEDUP, S("reversedup") },
63 static void readhdr(void)
67 while (fgets(dbuf.mv_data, dbuf.mv_size, stdin) != NULL) {
69 if (!strncmp(dbuf.mv_data, "VERSION=", STRLENOF("VERSION="))) {
70 version=atoi((char *)dbuf.mv_data+STRLENOF("VERSION="));
72 fprintf(stderr, "%s: line %"Yu": unsupported VERSION %d\n",
73 prog, lineno, version);
76 } else if (!strncmp(dbuf.mv_data, "HEADER=END", STRLENOF("HEADER=END"))) {
78 } else if (!strncmp(dbuf.mv_data, "format=", STRLENOF("format="))) {
79 if (!strncmp((char *)dbuf.mv_data+STRLENOF("FORMAT="), "print", STRLENOF("print")))
81 else if (strncmp((char *)dbuf.mv_data+STRLENOF("FORMAT="), "bytevalue", STRLENOF("bytevalue"))) {
82 fprintf(stderr, "%s: line %"Yu": unsupported FORMAT %s\n",
83 prog, lineno, (char *)dbuf.mv_data+STRLENOF("FORMAT="));
86 } else if (!strncmp(dbuf.mv_data, "database=", STRLENOF("database="))) {
87 ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size);
89 if (subname) free(subname);
90 subname = strdup((char *)dbuf.mv_data+STRLENOF("database="));
91 } else if (!strncmp(dbuf.mv_data, "type=", STRLENOF("type="))) {
92 if (strncmp((char *)dbuf.mv_data+STRLENOF("type="), "btree", STRLENOF("btree"))) {
93 fprintf(stderr, "%s: line %"Yu": unsupported type %s\n",
94 prog, lineno, (char *)dbuf.mv_data+STRLENOF("type="));
97 } else if (!strncmp(dbuf.mv_data, "mapaddr=", STRLENOF("mapaddr="))) {
99 ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size);
100 if (ptr) *ptr = '\0';
101 i = sscanf((char *)dbuf.mv_data+STRLENOF("mapaddr="), "%p", &info.me_mapaddr);
103 fprintf(stderr, "%s: line %"Yu": invalid mapaddr %s\n",
104 prog, lineno, (char *)dbuf.mv_data+STRLENOF("mapaddr="));
107 } else if (!strncmp(dbuf.mv_data, "mapsize=", STRLENOF("mapsize="))) {
109 ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size);
110 if (ptr) *ptr = '\0';
111 i = sscanf((char *)dbuf.mv_data+STRLENOF("mapsize="),
112 "%" MDB_SCNy(u), &info.me_mapsize);
114 fprintf(stderr, "%s: line %"Yu": invalid mapsize %s\n",
115 prog, lineno, (char *)dbuf.mv_data+STRLENOF("mapsize="));
118 } else if (!strncmp(dbuf.mv_data, "maxreaders=", STRLENOF("maxreaders="))) {
120 ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size);
121 if (ptr) *ptr = '\0';
122 i = sscanf((char *)dbuf.mv_data+STRLENOF("maxreaders="), "%u", &info.me_maxreaders);
124 fprintf(stderr, "%s: line %"Yu": invalid maxreaders %s\n",
125 prog, lineno, (char *)dbuf.mv_data+STRLENOF("maxreaders="));
130 for (i=0; dbflags[i].bit; i++) {
131 if (!strncmp(dbuf.mv_data, dbflags[i].name, dbflags[i].len) &&
132 ((char *)dbuf.mv_data)[dbflags[i].len] == '=') {
133 flags |= dbflags[i].bit;
137 if (!dbflags[i].bit) {
138 ptr = memchr(dbuf.mv_data, '=', dbuf.mv_size);
140 fprintf(stderr, "%s: line %"Yu": unexpected format\n",
145 fprintf(stderr, "%s: line %"Yu": unrecognized keyword ignored: %s\n",
146 prog, lineno, (char *)dbuf.mv_data);
153 static void badend(void)
155 fprintf(stderr, "%s: line %"Yu": unexpected end of input\n",
159 static int unhex(unsigned char *c2)
173 static int readline(MDB_val *out, MDB_val *buf)
175 unsigned char *c1, *c2, *end;
179 if (!(mode & NOHDR)) {
187 if (fgets(buf->mv_data, buf->mv_size, stdin) == NULL) {
193 if (c == 'D' && !strncmp(buf->mv_data, "ATA=END", STRLENOF("ATA=END")))
198 if (fgets(buf->mv_data, buf->mv_size, stdin) == NULL) {
205 len = strlen((char *)c1);
208 /* Is buffer too short? */
209 while (c1[len-1] != '\n') {
210 buf->mv_data = realloc(buf->mv_data, buf->mv_size*2);
213 fprintf(stderr, "%s: line %"Yu": out of memory, line too long\n",
219 if (fgets((char *)c1, buf->mv_size+1, stdin) == NULL) {
225 len = strlen((char *)c1);
228 c1 = c2 = buf->mv_data;
239 if (c2+3 > end || !isxdigit(c2[1]) || !isxdigit(c2[2])) {
248 /* copies are redundant when no escapes were used */
253 /* odd length not allowed */
260 if (!isxdigit(*c2) || !isxdigit(c2[1])) {
269 c2 = out->mv_data = buf->mv_data;
270 out->mv_size = c1 - c2;
275 static void usage(void)
277 fprintf(stderr, "usage: %s [-V] [-f input] [-n] [-s name] [-N] [-T] dbpath\n", prog);
281 int main(int argc, char *argv[])
289 int envflags = 0, putflags = 0;
298 /* -f: load file instead of stdin
299 * -n: use NOSUBDIR flag on env_open
300 * -s: load into named subDB
301 * -N: use NOOVERWRITE on puts
303 * -V: print version and exit
305 while ((i = getopt(argc, argv, "f:ns:NTV")) != EOF) {
308 printf("%s\n", MDB_VERSION_STRING);
312 if (freopen(optarg, "r", stdin) == NULL) {
313 fprintf(stderr, "%s: %s: reopen: %s\n",
314 prog, optarg, strerror(errno));
319 envflags |= MDB_NOSUBDIR;
322 subname = strdup(optarg);
325 putflags = MDB_NOOVERWRITE|MDB_NODUPDATA;
328 mode |= NOHDR | PRINT;
335 if (optind != argc - 1)
339 dbuf.mv_data = malloc(dbuf.mv_size);
344 envname = argv[optind];
345 rc = mdb_env_create(&env);
347 fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc));
351 mdb_env_set_maxdbs(env, 2);
353 if (info.me_maxreaders)
354 mdb_env_set_maxreaders(env, info.me_maxreaders);
357 mdb_env_set_mapsize(env, info.me_mapsize);
360 envflags |= MDB_FIXEDMAP;
362 rc = mdb_env_open(env, envname, envflags, 0664);
364 fprintf(stderr, "mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc));
368 kbuf.mv_size = mdb_env_get_maxkeysize(env) * 2 + 2;
369 kbuf.mv_data = malloc(kbuf.mv_size);
378 } else if (!(mode & NOHDR))
381 rc = mdb_txn_begin(env, NULL, 0, &txn);
383 fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc));
387 rc = mdb_open(txn, subname, flags|MDB_CREATE, &dbi);
389 fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc));
393 rc = mdb_cursor_open(txn, dbi, &mc);
395 fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
400 rc = readline(&key, &kbuf);
401 if (rc) /* rc == EOF */
404 rc = readline(&data, &dbuf);
406 fprintf(stderr, "%s: line %"Yu": failed to read key value\n", prog, lineno);
410 rc = mdb_cursor_put(mc, &key, &data, putflags);
411 if (rc == MDB_KEYEXIST && putflags)
414 fprintf(stderr, "mdb_cursor_put failed, error %d %s\n", rc, mdb_strerror(rc));
419 rc = mdb_txn_commit(txn);
421 fprintf(stderr, "%s: line %"Yu": txn_commit: %s\n",
422 prog, lineno, mdb_strerror(rc));
425 rc = mdb_txn_begin(env, NULL, 0, &txn);
427 fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc));
430 rc = mdb_cursor_open(txn, dbi, &mc);
432 fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
438 rc = mdb_txn_commit(txn);
441 fprintf(stderr, "%s: line %"Yu": txn_commit: %s\n",
442 prog, lineno, mdb_strerror(rc));
445 mdb_dbi_close(env, dbi);
453 return rc ? EXIT_FAILURE : EXIT_SUCCESS;