|
|
1.1 root 1: /*
2: * dbz - use and test dbz in various ways
3: *
4: * -Log-
5: */
6:
7: #include <stdio.h>
8: #include <sys/types.h>
9: #include <sys/stat.h>
10: #include <string.h>
11: #include <dbz.h>
12:
13: #ifdef FUNNYSEEKS
14: #include <unistd.h>
15: #else
16: #define SEEK_SET 0
17: #endif
18:
19: #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
20:
21: #ifndef lint
22: static char RCSid[] = "$Header: /rel/cvsfiles/devo/libio/dbz/dbzmain.c,v 1.2 1993/10/25 20:02:41 bothner Exp $";
23: #endif
24:
25: char *progname;
26:
27: char *inname = "(no file)"; /* filename for messages etc. */
28: long lineno; /* line number for messages etc. */
29:
30: char *basename;
31: char *pagname;
32: char *dirname;
33: char *str2dup();
34: FILE *base;
35:
36: int op = 'b'; /* what to do, default build a new table */
37: int baseinput = 1; /* is the base file also the input? */
38:
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 */
58:
59: #define DEFBUF 1024 /* default line-buffer size */
60: int buflen = DEFBUF; /* line length limit */
61: char lbuf[DEFBUF];
62: char *line = lbuf;
63: char cbuf[DEFBUF];
64: char *cmp = cbuf;
65:
66: void fail();
67: void dofile();
68: void runs();
69: void dosweep();
70: void mkfiles();
71: void crfile();
72: void doline();
73: void process();
74:
75: #ifdef HAVERFCIZE
76: extern char *rfc822ize();
77: #else
78: #define rfc822ize(n) (n)
79: #endif
80:
81: extern char *malloc();
82:
83: /*
84: - main - parse arguments and handle options
85: */
86: main(argc, argv)
87: int argc;
88: char *argv[];
89: {
90: int c;
91: int errflg = 0;
92: extern int optind;
93: extern char *optarg;
94: int doruns = 0;
95: extern long atol();
96:
97: progname = argv[0];
98:
99: while ((c = getopt(argc, argv, "axcmt:l:R0E:SqOiX:Yuf:p:eMUC:d")) != EOF)
100: switch (c) {
101: case 'a': /* append to existing table */
102: if (op != 'b')
103: fail("only one of -a -x -c -m can be given", "");
104: op = 'a';
105: baseinput = 0;
106: break;
107: case 'x': /* extract from existing table */
108: if (op != 'b')
109: fail("only one of -a -x -c -m can be given", "");
110: op = 'x';
111: baseinput = 0;
112: break;
113: case 'c': /* check existing table */
114: if (op != 'b')
115: fail("only one of -a -x -c -m can be given", "");
116: op = 'c';
117: break;
118: case 'm': /* extract missing (complement of -x) */
119: if (op != 'b')
120: fail("only one of -a -x -c -m can be given", "");
121: op = 'm';
122: baseinput = 0;
123: break;
124: case 't': /* set field separator */
125: if (strlen(optarg) > 1)
126: fail("only one field separator allowed", "");
127: fs = *optarg;
128: break;
129: case 'l': /* override line-length limit */
130: buflen = atoi(optarg) + 1;
131: if (buflen <= 2)
132: fail("bad -l value `%s'", optarg);
133: line = malloc(buflen);
134: cmp = malloc(buflen);
135: if (line == NULL || cmp == NULL)
136: fail("cannot allocate %s-byte buffers", optarg);
137: break;
138: case 'R': /* print run statistics */
139: doruns = 1;
140: break;
141: case '0': /* omit lines tagged (by fake -t) with 0 */
142: omitzero = 1;
143: break;
144: case 'E': /* report every n items */
145: every = atol(optarg);
146: break;
147: case 'S': /* dbzsync() on each -E report */
148: syncs = 1;
149: break;
150: case 'q': /* quick check or extract */
151: quick = 1;
152: break;
153: case 'O': /* sweep file checking all offsets */
154: sweep = 1;
155: break;
156: case 'i': /* don't use incore */
157: useincore = 0;
158: break;
159: case 'X': /* set xxx */
160: xxx = atoi(optarg);
161: break;
162: case 'Y': /* print xxx afterward */
163: printx = 1;
164: break;
165: case 'u': /* don't check uniqueness */
166: unique = 0;
167: break;
168: case 'f': /* init from existing table's parameters */
169: from = optarg;
170: break;
171: case 'p': /* parameters for dbzfresh */
172: if (sscanf(optarg, "%ld %1s %lx", &siz, &map, &tag) != 3) {
173: map = '?';
174: tag = 0;
175: if (sscanf(optarg, "%ld", &siz) != 1)
176: fail("bad -n value `%s'", optarg);
177: }
178: usefresh = 1;
179: break;
180: case 'e': /* -p size is exact, don't dbzsize() it */
181: exact = 1;
182: break;
183: case 'M': /* use old dbm interface + rfc822ize */
184: dbzint = 0;
185: break;
186: case 'U': /* make base unopenable during init */
187: unopen = 1;
188: break;
189: case 'C': /* change directories before dbmclose */
190: change = optarg;
191: break;
192: case 'd': /* Debugging. */
193: if (dbzdebug(1) < 0)
194: fail("dbz debugging not available", "");
195: break;
196: case '?':
197: default:
198: errflg++;
199: break;
200: }
201: if (errflg || optind >= argc || (optind+1 < argc && baseinput)) {
202: fprintf(stderr, "usage: %s ", progname);
203: fprintf(stderr, "[-a] [-x] [-c] database [file] ...\n");
204: exit(2);
205: }
206:
207: (void) dbzincore(useincore);
208: basename = argv[optind];
209: pagname = str2dup(basename, ".pag");
210: dirname = str2dup(basename, ".dir");
211: mkfiles();
212: optind++;
213:
214: if (baseinput) /* implies no further arguments */
215: process(base, basename);
216: else if (optind >= argc)
217: process(stdin, "stdin");
218: else
219: for (; optind < argc; optind++)
220: dofile(argv[optind]);
221:
222: if (change != NULL)
223: (void) chdir(change);
224: if (dbmclose() < 0)
225: fail("dbmclose failed", "");
226: if (doruns)
227: runs(pagname);
228: if (sweep)
229: dosweep(basename, pagname);
230: if (printx)
231: printf("%ld\n", xxx);
232: #ifdef DBZ_FINISH
233: DBZ_FINISH;
234: #endif
235: exit(0);
236: }
237:
238: /*
239: - dofile - open a file and invoke process()
240: */
241: void
242: dofile(name)
243: char *name;
244: {
245: register FILE *in;
246:
247: if (STREQ(name, "-"))
248: process(stdin, "-");
249: else {
250: in = fopen(name, "r");
251: if (in == NULL)
252: fail("cannot open `%s'", name);
253: process(in, name);
254: (void) fclose(in);
255: }
256: }
257:
258: /*
259: - mkfiles - create empty files and open them up
260: */
261: void
262: mkfiles()
263: {
264: if (op == 'b' && !dbzint) {
265: crfile(dirname);
266: crfile(pagname);
267: }
268:
269: base = fopen(basename, (op == 'a') ? "a" : "r");
270: if (base == NULL)
271: fail("cannot open `%s'", basename);
272: if (unopen)
273: (void) chmod(basename, 0);
274: if (from != NULL) {
275: if (dbzagain(basename, from) < 0)
276: fail("dbzagain(`%s'...) failed", basename);
277: } else if (op == 'b' && dbzint) {
278: if (!exact)
279: siz = dbzsize(siz);
280: if (dbzfresh(basename, siz, (int)fs, map, tag) < 0)
281: fail("dbzfresh(`%s'...) failed", basename);
282: } else if (dbminit(basename) < 0)
283: fail("dbminit(`%s') failed", basename);
284: if (unopen)
285: (void) chmod(basename, 0600); /* hard to restore original */
286: }
287:
288: /*
289: - crfile - create a file
290: */
291: void
292: crfile(name)
293: char *name;
294: {
295: register int f;
296:
297: f = creat(name, 0666);
298: if (f < 0)
299: fail("cannot create `%s'", name);
300: (void) close(f);
301: }
302:
303: /*
304: - process - process input file
305: */
306: void
307: process(in, name)
308: FILE *in;
309: char *name;
310: {
311: register off_t place;
312:
313: inname = name;
314: lineno = 0;
315:
316: for (;;) {
317: place = ftell(in);
318: if (fgets(line, buflen, in) == NULL)
319: return;
320: lineno++;
321: if (every > 0 && lineno%every == 0) {
322: fprintf(stderr, "%ld\n", lineno);
323: if (dbzsync() < 0)
324: fail("dbzsync failed", "");
325: }
326: doline(line, place);
327: }
328: /* NOTREACHED */
329: }
330:
331: /*
332: - doline - process input line
333: */
334: void
335: doline(lp, inoffset)
336: char *lp;
337: off_t inoffset;
338: {
339: register char *p;
340: register char pc;
341: datum key, value;
342: off_t place = inoffset;
343: register int shouldfind;
344: register int llen;
345: char keytext[DBZMAXKEY+1];
346:
347: p = NULL;
348: if (fs != '\0')
349: p = strchr(lp, fs);
350: if (p == NULL)
351: p = lp + strlen(lp);
352: if (p > lp && *(p-1) == '\n')
353: p--;
354: if (p - lp > DBZMAXKEY)
355: fail("key of `%.40s...' too long", lp);
356: pc = *p;
357: *p = '\0';
358: (void) strcpy(keytext, lp);
359: *p = pc;
360: key.dptr = (dbzint) ? keytext : rfc822ize(keytext);
361: key.dsize = strlen(keytext)+1;
362:
363: switch (op) {
364: case 'a':
365: place = ftell(base);
366: llen = strlen(lp);
367: if (fwrite(lp, 1, llen, base) != llen)
368: fail("write error in `%s'", basename);
369: /* FALLTHROUGH */
370: case 'b':
371: if (omitzero && p != NULL && *(p+1) == '0')
372: return;
373: if (unique) {
374: value = (dbzint) ? dbzfetch(key) : fetch(key);
375: if (value.dptr != NULL)
376: fail("`%.40s...' already present", lp);
377: }
378: value.dptr = (char *)&place;
379: value.dsize = (int)sizeof(off_t);
380: if (((dbzint) ? dbzstore(key, value) : store(key, value)) < 0)
381: fail("store failed on `%.40s...'", lp);
382: break;
383: case 'c':
384: value = (dbzint) ? dbzfetch(key) : fetch(key);
385: shouldfind = (omitzero && p != NULL && *(p+1) == '0') ? 0 : 1;
386: if (!shouldfind && (value.dptr != NULL || value.dsize != 0))
387: fail("`%.40s...' found, shouldn't be", lp);
388: if (shouldfind && (value.dptr == NULL ||
389: value.dsize != sizeof(off_t)))
390: fail("can't find `%.40s...'", lp);
391: if (shouldfind && !quick) {
392: (void) memcpy((char *)&place, value.dptr, sizeof(off_t));
393: if (place != inoffset)
394: fail("offset mismatch on `%.40s...'", lp);
395: if (fseek(base, place, SEEK_SET) == -1)
396: fail("fseek failed on `%.40s...'", lp);
397: if (fgets(cmp, buflen, base) == NULL)
398: fail("can't read line for `%.40s...'", lp);
399: if (!STREQ(lp, cmp))
400: fail("compare failed on `%.40s...'", lp);
401: }
402: break;
403: case 'x':
404: value = (dbzint) ? dbzfetch(key) : fetch(key);
405: if (value.dptr != NULL && !quick) {
406: (void) memcpy((char *)&place, value.dptr, sizeof(off_t));
407: if (fseek(base, place, SEEK_SET) == -1)
408: fail("fseek failed on `%.40s...'", lp);
409: if (fgets(cmp, buflen, base) == NULL)
410: fail("can't read line for `%.40s...'", lp);
411: fputs(cmp, stdout);
412: } else if (value.dptr != NULL)
413: fputs(lp, stdout);
414: break;
415: case 'm':
416: value = (dbzint) ? dbzfetch(key) : fetch(key);
417: if (value.dptr == NULL) {
418: fputs(keytext, stdout);
419: putchar('\n');
420: }
421: break;
422: default:
423: fail("unknown operator -- can't happen", "");
424: break;
425: }
426: }
427:
428: /*
429: - runs - print run statistics
430: */
431: void
432: runs(file)
433: char *file;
434: {
435: register FILE *fd;
436: off_t it;
437: register long run;
438:
439: fd = fopen(file, "r");
440: if (fd == NULL)
441: fail("cannot reopen `%s'", file);
442: run = 0;
443: while (fread((char *)&it, sizeof(off_t), 1, fd) == 1) {
444: if (it != 0)
445: run++;
446: else if (run > 0) {
447: printf("%ld\n", run);
448: run = 0;
449: }
450: }
451: (void) fclose(fd);
452: }
453:
454: /*
455: - dosweep - sweep pag file checking for valid offsets
456: */
457: void
458: dosweep(fn, pn)
459: char *fn;
460: char *pn;
461: {
462: register FILE *pf;
463: off_t it;
464: char nl;
465: register FILE *hf;
466:
467: hf = fopen(fn, "r");
468: if (hf == NULL)
469: fail("cannot reopen `%s'", fn);
470: pf = fopen(pn, "r");
471: if (pf == NULL)
472: fail("cannot reopen `%s'", pn);
473: while (fread((char *)&it, sizeof(off_t), 1, pf) == 1) {
474: it = (it & ((off_t)0x80000000)) ? (it&~((off_t)0xff000000)) : it;
475: if (it != 0 && it != 1) { /* 0 empty, 1 known okay */
476: it--; /* get rid of bias */
477: (void) fseek(hf, it-1, SEEK_SET);
478: nl = getc(hf);
479: if (nl != '\n')
480: fprintf(stderr, "offset 0%lo does not point to line\n",
481: (long)it);
482: }
483: }
484: (void) fclose(hf);
485: (void) fclose(pf);
486: }
487:
488: /*
489: - fail - complain and die
490: */
491: void
492: fail(s1, s2)
493: char *s1;
494: char *s2;
495: {
496: fprintf(stderr, "%s: (file `%s', line %ld) ", progname, inname, lineno);
497: fprintf(stderr, s1, s2);
498: fprintf(stderr, "\n");
499: exit(1);
500: }
501:
502: /*
503: - str2dup - concatenate strings and malloc result
504: */
505: char *
506: str2dup(s1, s2)
507: char *s1;
508: char *s2;
509: {
510: register char *p;
511:
512: p = malloc((size_t)strlen(s1) + strlen(s2) + 1);
513: if (p == NULL)
514: fail("can't allocate space for strings", "");
515: (void) strcpy(p, s1);
516: (void) strcat(p, s2);
517: return(p);
518: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.