]> git.ipfire.org Git - thirdparty/glibc.git/blame - db2/progs/db_load/db_load.c
Update.
[thirdparty/glibc.git] / db2 / progs / db_load / db_load.c
CommitLineData
92f1da4d
UD
1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 1996, 1997
5 * Sleepycat Software. All rights reserved.
6 */
7
8#include "config.h"
9
10#ifndef lint
11static const char copyright[] =
12"@(#) Copyright (c) 1997\n\
13 Sleepycat Software Inc. All rights reserved.\n";
af69217f 14static const char sccsid[] = "@(#)db_load.c 10.15 (Sleepycat) 12/29/97";
92f1da4d
UD
15#endif
16
17#ifndef NO_SYSTEM_INCLUDES
18#include <sys/types.h>
19#include <sys/stat.h>
20
21#include <errno.h>
92f1da4d
UD
22#include <limits.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26b4d766 26#include <unistd.h>
92f1da4d
UD
27#endif
28
29#include "db_int.h"
30#include "clib_ext.h"
31
32void badnum __P((void));
33void configure __P((DB_INFO *, char **));
34DB_ENV *db_init __P((char *));
35int dbt_rdump __P((DBT *));
36int dbt_rprint __P((DBT *));
37int digitize __P((int));
26b4d766 38int main __P((int, char *[]));
92f1da4d
UD
39void rheader __P((DBTYPE *, int *, DB_INFO *));
40void usage __P((void));
92f1da4d 41
26b4d766
UD
42const char
43 *progname = "db_load"; /* Program name. */
92f1da4d
UD
44
45int
46main(argc, argv)
47 int argc;
48 char *argv[];
49{
50 extern char *optarg;
51 extern int optind;
52 DB *dbp;
53 DBT key, data;
af69217f 54 DBTYPE argtype, dbtype;
92f1da4d
UD
55 DB_ENV *dbenv;
56 DB_INFO dbinfo;
57 db_recno_t recno;
af69217f 58 int ch, no_header, pflag;
92f1da4d
UD
59 char **clist, **clp, *home;
60
61 /* Allocate enough room for configuration arguments. */
a5a0310d 62 if ((clp = clist = (char **)calloc(argc + 1, sizeof(char *))) == NULL)
92f1da4d
UD
63 err(1, NULL);
64
65 home = NULL;
af69217f
UD
66 no_header = 0;
67 argtype = dbtype = DB_UNKNOWN;
68 while ((ch = getopt(argc, argv, "c:f:h:Tt:")) != EOF)
92f1da4d
UD
69 switch (ch) {
70 case 'c':
71 *clp++ = optarg;
72 break;
73 case 'f':
74 if (freopen(optarg, "r", stdin) == NULL)
75 err(1, "%s", optarg);
76 break;
77 case 'h':
78 home = optarg;
79 break;
af69217f
UD
80 case 'T':
81 no_header = pflag = 1;
82 break;
92f1da4d
UD
83 case 't':
84 if (strcmp(optarg, "btree") == 0) {
85 argtype = DB_BTREE;
86 break;
87 }
88 if (strcmp(optarg, "hash") == 0) {
89 argtype = DB_HASH;
90 break;
91 }
af69217f
UD
92 if (strcmp(optarg, "recno") == 0) {
93 argtype = DB_RECNO;
94 break;
95 }
92f1da4d
UD
96 usage();
97 /* NOTREACHED */
98 case '?':
99 default:
100 usage();
101 }
102 argc -= optind;
103 argv += optind;
104
105 if (argc != 1)
106 usage();
107
108 /* Initialize the environment. */
109 dbenv = db_init(home);
110 memset(&dbinfo, 0, sizeof(DB_INFO));
111
af69217f
UD
112 /*
113 * Read the header. If there isn't any header, we're expecting flat
114 * text, set the pflag appropriately.
115 */
116 if (no_header)
117 dbtype = argtype;
118 else {
119 rheader(&dbtype, &pflag, &dbinfo);
120 if (argtype != DB_UNKNOWN) {
121 /* Conversion to/from recno is prohibited. */
122 if ((dbtype == DB_RECNO && argtype != DB_RECNO) ||
123 (argtype == DB_RECNO && dbtype != DB_RECNO))
124 errx(1,
125 "databases of type recno may not be converted");
126 dbtype = argtype;
127 }
128 }
129 if (dbtype == DB_UNKNOWN)
130 errx(1, "no database type specified");
92f1da4d
UD
131
132 /* Apply command-line configuration changes. */
133 configure(&dbinfo, clist);
134
92f1da4d 135 /* Open the DB file. */
af69217f 136 if ((errno = db_open(argv[0], dbtype, DB_CREATE | DB_TRUNCATE,
92f1da4d
UD
137 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
138 dbenv, &dbinfo, &dbp)) != 0)
139 err(1, "%s", argv[0]);
140
141 /* Initialize the key/data pair. */
142 memset(&key, 0, sizeof(DBT));
143 if ((key.data = (void *)malloc(key.ulen = 1024)) == NULL) {
144 errno = ENOMEM;
145 err(1, NULL);
146 }
147 memset(&data, 0, sizeof(DBT));
148 if ((data.data = (void *)malloc(data.ulen = 1024)) == NULL) {
149 errno = ENOMEM;
150 err(1, NULL);
151 }
152
153 /* Get each key/data pair and add them to the database. */
af69217f 154 if (dbtype == DB_RECNO) {
92f1da4d
UD
155 key.data = &recno;
156 key.size = sizeof(recno);
157 for (recno = 1;; ++recno) {
158 if (pflag) {
159 if (dbt_rprint(&data))
160 break;
161 } else
162 if (dbt_rdump(&data))
163 break;
164 if ((errno = dbp->put(dbp, NULL, &key, &data, 0)) != 0)
165 err(1, "%s", argv[0]);
166 }
167 } else
168 for (;;) {
169 if (pflag) {
170 if (dbt_rprint(&key))
171 break;
172 if (dbt_rprint(&data))
173 goto fmt;
174 } else {
175 if (dbt_rdump(&key))
176 break;
177 if (dbt_rdump(&data))
178fmt: err(1, "odd number of key/data pairs");
179 }
180 if ((errno = dbp->put(dbp, NULL, &key, &data, 0)) != 0)
181 err(1, "%s", argv[0]);
182 }
183
184 if ((errno = dbp->close(dbp, 0)) != 0)
185 err(1, "%s", argv[0]);
186 return (0);
187}
188
189/*
190 * db_init --
191 * Initialize the environment.
192 */
193DB_ENV *
194db_init(home)
195 char *home;
196{
197 DB_ENV *dbenv;
198
199 if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) {
200 errno = ENOMEM;
201 err(1, NULL);
202 }
203 dbenv->db_errfile = stderr;
204 dbenv->db_errpfx = progname;
205
206 if ((errno =
207 db_appinit(home, NULL, dbenv, DB_CREATE | DB_USE_ENVIRON)) != 0)
208 err(1, "db_appinit");
209 return (dbenv);
210}
211
212#define FLAG(name, value, keyword, flag) \
213 if (strcmp(name, keyword) == 0) { \
214 switch (*value) { \
215 case '1': \
216 dbinfop->flags |= (flag); \
217 break; \
218 case '0': \
219 dbinfop->flags &= ~(flag); \
220 break; \
221 default: \
222 badnum(); \
223 /* NOTREACHED */ \
224 } \
225 continue; \
226 }
227#define NUMBER(name, value, keyword, field, flag) \
228 if (strcmp(name, keyword) == 0) { \
229 get_long(value, 1, LONG_MAX, &val); \
230 dbinfop->field = val; \
231 if (flag != 0) \
232 dbinfop->flags |= (flag); \
233 continue; \
234 }
235#define STRING(name, value, keyword, field, flag) \
236 if (strcmp(name, keyword) == 0) { \
237 dbinfop->field = value[0]; \
238 if (flag != 0) \
239 dbinfop->flags |= (flag); \
240 continue; \
241 }
242
243/*
244 * configure --
245 * Handle command-line configuration options.
246 */
247void
248configure(dbinfop, clp)
249 DB_INFO *dbinfop;
250 char **clp;
251{
252 long val;
253 char *name, *value;
254
255 for (; (name = *clp) != NULL; ++clp) {
256 if ((value = strchr(name, '=')) == NULL)
257 errx(1,
258 "command-line configuration uses name=value format");
259 *value++ = '\0';
260
261 NUMBER(name, value, "bt_maxkey", bt_maxkey, 0);
262 NUMBER(name, value, "bt_minkey", bt_minkey, 0);
263 NUMBER(name, value, "db_lorder", db_lorder, 0);
264 NUMBER(name, value, "db_pagesize", db_pagesize, 0);
265 FLAG(name, value, "duplicates", DB_DUP);
266 NUMBER(name, value, "h_ffactor", h_ffactor, 0);
267 NUMBER(name, value, "h_nelem", h_nelem, 0);
268 NUMBER(name, value, "re_len", re_len, DB_FIXEDLEN);
269 STRING(name, value, "re_pad", re_pad, DB_PAD);
270 FLAG(name, value, "recnum", DB_RECNUM);
271 FLAG(name, value, "renumber", DB_RENUMBER);
272
273 errx(1, "unknown command-line configuration keyword");
274 }
275}
276
277/*
278 * rheader --
279 * Read the header message.
280 */
281void
282rheader(dbtypep, pflagp, dbinfop)
283 DBTYPE *dbtypep;
284 int *pflagp;
285 DB_INFO *dbinfop;
286{
287 long lineno, val;
288 char name[256], value[256];
289
290 *dbtypep = DB_UNKNOWN;
291 *pflagp = 0;
292
293 for (lineno = 1;; ++lineno) {
af69217f 294 /* If we don't see the expected information, it's an error. */
92f1da4d 295 if (fscanf(stdin, "%[^=]=%s\n", name, value) != 2)
26b4d766 296 errx(1, "line %lu: unexpected format", lineno);
af69217f
UD
297
298 /* Check for the end of the header lines. */
92f1da4d
UD
299 if (strcmp(name, "HEADER") == 0)
300 break;
301
302 if (strcmp(name, "format") == 0) {
303 if (strcmp(value, "bytevalue") == 0) {
304 *pflagp = 0;
305 continue;
306 }
307 if (strcmp(value, "print") == 0) {
308 *pflagp = 1;
309 continue;
310 }
311 errx(1, "line %d: unknown format", lineno);
312 }
313 if (strcmp(name, "type") == 0) {
314 if (strcmp(value, "btree") == 0) {
315 *dbtypep = DB_BTREE;
316 continue;
317 }
318 if (strcmp(value, "hash") == 0) {
319 *dbtypep = DB_HASH;
320 continue;
321 }
322 if (strcmp(value, "recno") == 0) {
323 *dbtypep = DB_RECNO;
324 continue;
325 }
326 errx(1, "line %d: unknown type", lineno);
327 }
328 NUMBER(name, value, "bt_maxkey", bt_maxkey, 0);
329 NUMBER(name, value, "bt_minkey", bt_minkey, 0);
330 NUMBER(name, value, "db_lorder", db_lorder, 0);
331 NUMBER(name, value, "db_pagesize", db_pagesize, 0);
332 FLAG(name, value, "duplicates", DB_DUP);
333 NUMBER(name, value, "h_ffactor", h_ffactor, 0);
334 NUMBER(name, value, "h_nelem", h_nelem, 0);
335 NUMBER(name, value, "re_len", re_len, DB_FIXEDLEN);
336 STRING(name, value, "re_pad", re_pad, DB_PAD);
337 FLAG(name, value, "recnum", DB_RECNUM);
338 FLAG(name, value, "renumber", DB_RENUMBER);
339
340 errx(1, "unknown input-file header configuration keyword");
341 }
342}
343
344/*
345 * dbt_rprint --
346 * Read a printable line into a DBT structure.
347 */
348int
349dbt_rprint(dbtp)
350 DBT *dbtp;
351{
352 u_int32_t len;
353 u_int8_t *p;
354 int c1, c2, escape;
355
356 escape = 0;
357 for (p = dbtp->data, len = 0; (c1 = getchar()) != '\n';) {
358 if (c1 == EOF) {
359 if (len == 0)
360 return (1);
361 err(1, "unexpected end of key/data pair");
362 }
363 if (escape) {
364 if (c1 != '\\') {
365 if ((c2 = getchar()) == EOF)
366 err(1,
367 "unexpected end of key/data pair");
368 c1 = digitize(c1) << 4 | digitize(c2);
369 }
370 escape = 0;
371 } else
372 if (c1 == '\\') {
373 escape = 1;
374 continue;
375 }
cc3fa755 376 if (len >= dbtp->ulen - 10) {
92f1da4d
UD
377 dbtp->ulen *= 2;
378 if ((dbtp->data =
379 (void *)realloc(dbtp->data, dbtp->ulen)) == NULL) {
380 errno = ENOMEM;
381 err(1, NULL);
382 }
383 p = (u_int8_t *)dbtp->data + len;
384 }
cc3fa755 385 ++len;
92f1da4d
UD
386 *p++ = c1;
387 }
388 dbtp->size = len;
389 return (0);
390}
391
392/*
393 * digitize --
394 * Convert a character to an integer.
395 */
396int
397digitize(c)
398 int c;
399{
400 switch (c) { /* Don't depend on ASCII ordering. */
401 case '0': return (0);
402 case '1': return (1);
403 case '2': return (2);
404 case '3': return (3);
405 case '4': return (4);
406 case '5': return (5);
407 case '6': return (6);
408 case '7': return (7);
409 case '8': return (8);
410 case '9': return (9);
411 case 'a': return (10);
412 case 'b': return (11);
413 case 'c': return (12);
414 case 'd': return (13);
415 case 'e': return (14);
416 case 'f': return (15);
417 }
418
419 err(1, "unexpected hexadecimal value");
420 /* NOTREACHED */
421
422 return (0);
423}
424
425/*
426 * dbt_rdump --
427 * Read a byte dump line into a DBT structure.
428 */
429int
430dbt_rdump(dbtp)
431 DBT *dbtp;
432{
433 u_int32_t len;
434 u_int8_t *p;
435 int c1, c2;
436
437 for (p = dbtp->data, len = 0; (c1 = getchar()) != '\n';) {
438 if (c1 == EOF) {
439 if (len == 0)
440 return (1);
441 err(1, "unexpected end of key/data pair");
442 }
443 if ((c2 = getchar()) == EOF)
444 err(1, "unexpected end of key/data pair");
cc3fa755 445 if (len >= dbtp->ulen - 10) {
92f1da4d
UD
446 dbtp->ulen *= 2;
447 if ((dbtp->data =
448 (void *)realloc(dbtp->data, dbtp->ulen)) == NULL) {
449 errno = ENOMEM;
450 err(1, NULL);
451 }
452 p = (u_int8_t *)dbtp->data + len;
453 }
cc3fa755 454 ++len;
92f1da4d
UD
455 *p++ = digitize(c1) << 4 | digitize(c2);
456 }
457 dbtp->size = len;
458 return (0);
459}
460
461/*
462 * badnum --
463 * Display the bad number message.
464 */
465void
466badnum()
467{
468 err(1, "boolean name=value pairs require a value of 0 or 1");
469}
470
471/*
472 * usage --
473 * Display the usage message.
474 */
475void
476usage()
477{
478 (void)fprintf(stderr,
af69217f 479"usage: db_load [-T]\n\t[-c name=value] [-f file] [-h home] [-t btree | hash] db_file\n");
92f1da4d
UD
480 exit(1);
481}