2 * dbz - use and test dbz in various ways
19 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
22 static char RCSid[] = "$Header: /egcs/carton/cvsfiles/egcs/./libio/dbz/dbzmain.c,v 1.1.1.1 1997/08/21 22:58:23 jason Exp $";
27 char *inname = "(no file)"; /* filename for messages etc. */
28 long lineno; /* line number for messages etc. */
36 int op = 'b'; /* what to do, default build a new table */
37 int baseinput = 1; /* is the base file also the input? */
39 char *from = NULL; /* old table to use for dbzagain() */
40 int omitzero = 0; /* omit lines tagged with 0 */
41 long every = 0; /* report every n lines */
42 int syncs = 0; /* dbzsync() on each report */
43 int quick = 0; /* quick checking, not too thorough */
44 int sweep = 0; /* sweep file checking all offsets */
45 int useincore = 1; /* should we use incore facility? */
46 long xxx = 0; /* debugging variable */
47 int printx = 0; /* print xxx after all is done */
48 int unique = 1; /* before store(), check with fetch() */
49 int usefresh = 0; /* use dbzfresh? */
50 long siz = 0; /* -p size */
51 char map = 'C'; /* -p map */
52 long tag = 0; /* -p tag mask */
53 int exact = 0; /* do not run dbzsize(siz) */
54 int dbzint = 1; /* use new interface? */
55 char fs = '\t'; /* field separator, default tab */
56 int unopen = 0; /* make base unopenable during dbminit? */
57 char *change = NULL; /* chdir here before dbmclose */
59 #define DEFBUF 1024 /* default line-buffer size */
60 int buflen = DEFBUF; /* line length limit */
76 extern char *rfc822ize();
78 #define rfc822ize(n) (n)
81 extern char *malloc();
84 - main - parse arguments and handle options
100 while ((c = getopt(argc, argv, "axcmt:l:R0E:SqOiX:Yuf:p:eMUC:d")) != EOF)
102 case 'a': /* append to existing table */
104 fail("only one of -a -x -c -m can be given", "");
108 case 'x': /* extract from existing table */
110 fail("only one of -a -x -c -m can be given", "");
114 case 'c': /* check existing table */
116 fail("only one of -a -x -c -m can be given", "");
119 case 'm': /* extract missing (complement of -x) */
121 fail("only one of -a -x -c -m can be given", "");
125 case 't': /* set field separator */
126 if (strlen(optarg) > 1)
127 fail("only one field separator allowed", "");
130 case 'l': /* override line-length limit */
131 buflen = atoi(optarg) + 1;
133 fail("bad -l value `%s'", optarg);
134 line = malloc(buflen);
135 cmp = malloc(buflen);
136 if (line == NULL || cmp == NULL)
137 fail("cannot allocate %s-byte buffers", optarg);
139 case 'R': /* print run statistics */
142 case '0': /* omit lines tagged (by fake -t) with 0 */
145 case 'E': /* report every n items */
146 every = atol(optarg);
148 case 'S': /* dbzsync() on each -E report */
151 case 'q': /* quick check or extract */
154 case 'O': /* sweep file checking all offsets */
157 case 'i': /* don't use incore */
160 case 'X': /* set xxx */
163 case 'Y': /* print xxx afterward */
166 case 'u': /* don't check uniqueness */
169 case 'f': /* init from existing table's parameters */
172 case 'p': /* parameters for dbzfresh */
173 if (sscanf(optarg, "%ld %1s %lx", &siz, &map, &tag) != 3) {
176 if (sscanf(optarg, "%ld", &siz) != 1)
177 fail("bad -n value `%s'", optarg);
181 case 'e': /* -p size is exact, don't dbzsize() it */
184 case 'M': /* use old dbm interface + rfc822ize */
187 case 'U': /* make base unopenable during init */
190 case 'C': /* change directories before dbmclose */
193 case 'd': /* Debugging. */
195 fail("dbz debugging not available", "");
202 if (errflg || optind >= argc || (optind+1 < argc && baseinput)) {
203 fprintf(stderr, "usage: %s ", progname);
204 fprintf(stderr, "[-a] [-x] [-c] database [file] ...\n");
208 (void) dbzincore(useincore);
209 my_basename = argv[optind];
210 pagname = str2dup(my_basename, ".pag");
211 dir_name = str2dup(my_basename, ".dir");
215 if (baseinput) /* implies no further arguments */
216 process(base, my_basename);
217 else if (optind >= argc)
218 process(stdin, "stdin");
220 for (; optind < argc; optind++)
221 dofile(argv[optind]);
224 (void) chdir(change);
226 fail("dbmclose failed", "");
230 dosweep(my_basename, pagname);
232 printf("%ld\n", xxx);
240 - dofile - open a file and invoke process()
248 if (STREQ(name, "-"))
251 in = fopen(name, "r");
253 fail("cannot open `%s'", name);
260 - mkfiles - create empty files and open them up
265 if (op == 'b' && !dbzint) {
270 base = fopen(my_basename, (op == 'a') ? "a" : "r");
272 fail("cannot open `%s'", my_basename);
274 (void) chmod(my_basename, 0);
276 if (dbzagain(my_basename, from) < 0)
277 fail("dbzagain(`%s'...) failed", my_basename);
278 } else if (op == 'b' && dbzint) {
281 if (dbzfresh(my_basename, siz, (int)fs, map, (off_t)tag) < 0)
282 fail("dbzfresh(`%s'...) failed", my_basename);
283 } else if (dbminit(my_basename) < 0)
284 fail("dbminit(`%s') failed", my_basename);
286 (void) chmod(my_basename, 0600); /* hard to restore original */
290 - crfile - create a file
298 f = creat(name, 0666);
300 fail("cannot create `%s'", name);
305 - process - process input file
312 register off_t place;
319 if (fgets(line, buflen, in) == NULL)
322 if (every > 0 && lineno%every == 0) {
323 fprintf(stderr, "%ld\n", lineno);
325 fail("dbzsync failed", "");
333 - doline - process input line
343 off_t place = inoffset;
344 register int shouldfind;
346 char keytext[DBZMAXKEY+1];
353 if (p > lp && *(p-1) == '\n')
355 if (p - lp > DBZMAXKEY)
356 fail("key of `%.40s...' too long", lp);
359 (void) strcpy(keytext, lp);
361 key.dptr = (dbzint) ? keytext : rfc822ize(keytext);
362 key.dsize = strlen(keytext)+1;
368 if (fwrite(lp, 1, llen, base) != llen)
369 fail("write error in `%s'", my_basename);
372 if (omitzero && p != NULL && *(p+1) == '0')
375 value = (dbzint) ? dbzfetch(key) : fetch(key);
376 if (value.dptr != NULL)
377 fail("`%.40s...' already present", lp);
379 value.dptr = (char *)&place;
380 value.dsize = (int)sizeof(off_t);
381 if (((dbzint) ? dbzstore(key, value) : store(key, value)) < 0)
382 fail("store failed on `%.40s...'", lp);
385 value = (dbzint) ? dbzfetch(key) : fetch(key);
386 shouldfind = (omitzero && p != NULL && *(p+1) == '0') ? 0 : 1;
387 if (!shouldfind && (value.dptr != NULL || value.dsize != 0))
388 fail("`%.40s...' found, shouldn't be", lp);
389 if (shouldfind && (value.dptr == NULL ||
390 value.dsize != sizeof(off_t)))
391 fail("can't find `%.40s...'", lp);
392 if (shouldfind && !quick) {
393 (void) memcpy((char *)&place, value.dptr, sizeof(off_t));
394 if (place != inoffset)
395 fail("offset mismatch on `%.40s...'", lp);
396 if (fseek(base, place, SEEK_SET) == -1)
397 fail("fseek failed on `%.40s...'", lp);
398 if (fgets(cmp, buflen, base) == NULL)
399 fail("can't read line for `%.40s...'", lp);
401 fail("compare failed on `%.40s...'", lp);
405 value = (dbzint) ? dbzfetch(key) : fetch(key);
406 if (value.dptr != NULL && !quick) {
407 (void) memcpy((char *)&place, value.dptr, sizeof(off_t));
408 if (fseek(base, place, SEEK_SET) == -1)
409 fail("fseek failed on `%.40s...'", lp);
410 if (fgets(cmp, buflen, base) == NULL)
411 fail("can't read line for `%.40s...'", lp);
413 } else if (value.dptr != NULL)
417 value = (dbzint) ? dbzfetch(key) : fetch(key);
418 if (value.dptr == NULL) {
419 fputs(keytext, stdout);
424 fail("unknown operator -- can't happen", "");
430 - runs - print run statistics
440 fd = fopen(file, "r");
442 fail("cannot reopen `%s'", file);
444 while (fread((char *)&it, sizeof(off_t), 1, fd) == 1) {
448 printf("%ld\n", run);
456 - dosweep - sweep pag file checking for valid offsets
470 fail("cannot reopen `%s'", fn);
473 fail("cannot reopen `%s'", pn);
474 while (fread((char *)&it, sizeof(off_t), 1, pf) == 1) {
475 it = (it & ((off_t)0x80000000)) ? (it&~((off_t)0xff000000)) : it;
476 if (it != 0 && it != 1) { /* 0 empty, 1 known okay */
477 it--; /* get rid of bias */
478 (void) fseek(hf, it-1, SEEK_SET);
481 fprintf(stderr, "offset 0%lo does not point to line\n",
490 - fail - complain and die
497 fprintf(stderr, "%s: (file `%s', line %ld) ", progname, inname, lineno);
498 fprintf(stderr, s1, s2);
499 fprintf(stderr, "\n");
504 - str2dup - concatenate strings and malloc result
513 p = malloc((size_t)strlen(s1) + strlen(s2) + 1);
515 fail("can't allocate space for strings", "");
516 (void) strcpy(p, s1);
517 (void) strcat(p, s2);