📄 dbz.c
字号:
*ep = -1; } return(atol(getbuf));}/* - putconf - write configuration to .dir file */static int /* 0 success, -1 failure */putconf(f, cp)register FILE *f;register struct dbzconfig *cp;{ register int i; register int ret = 0; if (fseek(f, 0, SEEK_SET) != 0) { DEBUG(("fseek failure in putconf\n")); ret = -1; } fprintf(f, "dbz %d %ld %d %c %ld %ld %d %d", dbzversion, (long)cp->tsize, cp->fieldsep, cp->casemap, (long)cp->tagenb, (long)cp->tagmask, cp->tagshift, cp->valuesize); for (i = 0; i < cp->valuesize; i++) fprintf(f, " %d", cp->bytemap[i]); fprintf(f, "\n"); for (i = 0; i < NUSEDS; i++) fprintf(f, "%ld%c", (long)cp->used[i], (i < NUSEDS-1) ? ' ' : '\n'); (void) fflush(f); if (ferror(f)) ret = -1; DEBUG(("putconf status %d\n", ret)); return(ret);}/* - getcore - try to set up an in-core copy of .pag file */static off_t * /* pointer to copy, or NULL */getcore(f)FILE *f;{ register off_t *p; register size_t i; register size_t nread; register char *it; it = malloc((size_t)conf.tsize * SOF); if (it == NULL) { DEBUG(("getcore: malloc failed\n")); return(NULL); } nread = fread(it, SOF, (size_t)conf.tsize, f); if (ferror(f)) { DEBUG(("getcore: read failed\n")); free(it); return(NULL); } p = (off_t *)it + nread; i = (size_t)conf.tsize - nread; while (i-- > 0) *p++ = VACANT; return((off_t *)it);}/* - putcore - try to rewrite an in-core table */static int /* 0 okay, -1 fail */putcore(tab, f)off_t *tab;FILE *f;{ if (fseek(f, 0, SEEK_SET) != 0) { DEBUG(("fseek failure in putcore\n")); return(-1); } (void) fwrite((char *)tab, SOF, (size_t)conf.tsize, f); (void) fflush(f); return((ferror(f)) ? -1 : 0);}/* - start - set up to start or restart a search */static voidstart(sp, kp, osp)register struct searcher *sp;register datum *kp;register struct searcher *osp; /* may be FRESH, i.e. NULL */{ register long h; h = hash(kp->dptr, kp->dsize); if (osp != FRESH && osp->hash == h) { if (sp != osp) *sp = *osp; DEBUG(("search restarted\n")); } else { sp->hash = h; sp->tag = MKTAG(h / conf.tsize); DEBUG(("tag 0x%lx\n", sp->tag)); sp->place = h % conf.tsize; sp->tabno = 0; sp->run = (conf.olddbz) ? conf.tsize : MAXRUN; sp->aborted = 0; } sp->seen = 0;}/* - search - conduct part of a search */static off_t /* NOTFOUND if we hit VACANT or error */search(sp)register struct searcher *sp;{ register off_t dest; register off_t value; off_t val; /* buffer for value (can't fread register) */ register off_t place; if (sp->aborted) return(NOTFOUND); for (;;) { /* determine location to be examined */ place = sp->place; if (sp->seen) { /* go to next location */ if (--sp->run <= 0) { sp->tabno++; sp->run = MAXRUN; } place = (place+1)%conf.tsize + sp->tabno*conf.tsize; sp->place = place; } else sp->seen = 1; /* now looking at current location */ DEBUG(("search @ %ld\n", place)); /* get the tagged value */ if (corepag != NULL && place < conf.tsize) { DEBUG(("search: in core\n")); value = MAPIN(corepag[place]); } else { /* seek, if necessary */ dest = place * SOF; if (pagpos != dest) { if (fseek(pagf, dest, SEEK_SET) != 0) { DEBUG(("search: seek failed\n")); pagpos = -1; sp->aborted = 1; return(NOTFOUND); } pagpos = dest; } /* read it */ if (fread((char *)&val, sizeof(val), 1, pagf) == 1) value = MAPIN(val); else if (ferror(pagf)) { DEBUG(("search: read failed\n")); pagpos = -1; sp->aborted = 1; return(NOTFOUND); } else value = VACANT; /* and finish up */ pagpos += sizeof(val); } /* vacant slot is always cause to return */ if (value == VACANT) { DEBUG(("search: empty slot\n")); return(NOTFOUND); }; /* check the tag */ value = UNBIAS(value); DEBUG(("got 0x%lx\n", value)); if (!HASTAG(value)) { DEBUG(("tagless\n")); return(value); } else if (TAG(value) == sp->tag) { DEBUG(("match\n")); return(NOTAG(value)); } else { DEBUG(("mismatch 0x%lx\n", TAG(value))); } } /* NOTREACHED */}/* - okayvalue - check that a value can be stored */static int /* predicate */okayvalue(value)off_t value;{ if (HASTAG(value)) return(0);#ifdef OVERFLOW if (value == LONG_MAX) /* BIAS() and UNBIAS() will overflow */ return(0);#endif return(1);}/* - set - store a value into a location previously found by search */static int /* 0 success, -1 failure */set(sp, value)register struct searcher *sp;off_t value;{ register off_t place = sp->place; register off_t v = value; if (sp->aborted) return(-1); if (CANTAG(v) && !conf.olddbz) { v |= sp->tag | taghere; if (v != UNBIAS(VACANT)) /* BIAS(v) won't look VACANT */#ifdef OVERFLOW if (v != LONG_MAX) /* and it won't overflow */#endif value = v; } DEBUG(("tagged value is 0x%lx\n", value)); value = BIAS(value); value = MAPOUT(value); /* If we have the index file in memory, use it */ if (corepag != NULL && place < conf.tsize) { corepag[place] = value; DEBUG(("set: incore\n")); return(0); } /* seek to spot */ pagpos = -1; /* invalidate position memory */ if (fseek(pagf, place * SOF, SEEK_SET) != 0) { DEBUG(("set: seek failed\n")); sp->aborted = 1; return(-1); } /* write in data */ if (fwrite((char *)&value, SOF, 1, pagf) != 1) { DEBUG(("set: write failed\n")); sp->aborted = 1; return(-1); } /* fflush improves robustness, and buffer re-use is rare anyway */ if (fflush(pagf) == EOF) { DEBUG(("set: fflush failed\n")); sp->aborted = 1; return(-1); } DEBUG(("set: succeeded\n")); return(0);}/* - mybytemap - determine this machine's byte map * * A byte map is an array of ints, sizeof(off_t) of them. The 0th int * is the byte number of the high-order byte in my off_t, and so forth. */static voidmybytemap(map)int map[]; /* -> int[SOF] */{ union { off_t o; char c[SOF]; } u; register int *mp = &map[SOF]; register int ntodo; register int i; u.o = 1; for (ntodo = (int)SOF; ntodo > 0; ntodo--) { for (i = 0; i < SOF; i++) if (u.c[i] != 0) break; if (i == SOF) { /* trouble -- set it to *something* consistent */ DEBUG(("mybytemap: nonexistent byte %d!!!\n", ntodo)); for (i = 0; i < SOF; i++) map[i] = i; return; } DEBUG(("mybytemap: byte %d\n", i)); *--mp = i; while (u.c[i] != 0) u.o <<= 1; }}/* - bytemap - transform an off_t from byte ordering map1 to map2 */static off_t /* transformed result */bytemap(ino, map1, map2)off_t ino;int *map1;int *map2;{ union oc { off_t o; char c[SOF]; }; union oc in; union oc out; register int i; in.o = ino; for (i = 0; i < SOF; i++) out.c[map2[i]] = in.c[map1[i]]; return(out.o);}/* * This is a simplified version of the pathalias hashing function. * Thanks to Steve Belovin and Peter Honeyman * * hash a string into a long int. 31 bit crc (from andrew appel). * the crc table is computed at run time by crcinit() -- we could * precompute, but it takes 1 clock tick on a 750. * * This fast table calculation works only if POLY is a prime polynomial * in the field of integers modulo 2. Since the coefficients of a * 32-bit polynomial won't fit in a 32-bit word, the high-order bit is * implicit. IT MUST ALSO BE THE CASE that the coefficients of orders * 31 down to 25 are zero. Happily, we have candidates, from * E. J. Watson, "Primitive Polynomials (Mod 2)", Math. Comp. 16 (1962): * x^32 + x^7 + x^5 + x^3 + x^2 + x^1 + x^0 * x^31 + x^3 + x^0 * * We reverse the bits to get: * 111101010000000000000000000000001 but drop the last 1 * f 5 0 0 0 0 0 0 * 010010000000000000000000000000001 ditto, for 31-bit crc * 4 8 0 0 0 0 0 0 */#define POLY 0x48000000L /* 31-bit polynomial (avoids sign problems) */static long CrcTable[128];/* - crcinit - initialize tables for hash function */static voidcrcinit(){ register int i, j; register long sum; for (i = 0; i < 128; ++i) { sum = 0L; for (j = 7 - 1; j >= 0; --j) if (i & (1 << j)) sum ^= POLY >> j; CrcTable[i] = sum; } DEBUG(("crcinit: done\n"));}/* - hash - Honeyman's nice hashing function */static longhash(name, size)register char *name;register int size;{ register long sum = 0L; while (size--) { sum = (sum >> 7) ^ CrcTable[(sum ^ (*name++)) & 0x7f]; } DEBUG(("hash: returns (%ld)\n", sum)); return(sum);}/* * case-mapping stuff * * Borrowed from C News, by permission of the authors. Somewhat modified. * * We exploit the fact that we are dealing only with headers here, and * headers are limited to the ASCII characters by RFC822. It is barely * possible that we might be dealing with a translation into another * character set, but in particular it's very unlikely for a header * character to be outside -128..255. * * Life would be a whole lot simpler if tolower() could safely and portably * be applied to any char. */#define OFFSET 128 /* avoid trouble with negative chars *//* must call casencmp before invoking TOLOW... */#define TOLOW(c) (cmap[(c)+OFFSET])/* ...but the use of it in CISTREQN is safe without the preliminary call (!) *//* CISTREQN is an optimised case-insensitive strncmp(a,b,n)==0; n > 0 */#define CISTREQN(a, b, n) \ (TOLOW((a)[0]) == TOLOW((b)[0]) && casencmp(a, b, n) == 0)#define MAPSIZE (256+OFFSET)static char cmap[MAPSIZE]; /* relies on init to '\0' */static int mprimed = 0; /* has cmap been set up? *//* - mapprime - set up case-mapping stuff */static voidmapprime(){ register char *lp; register char *up; register int c; register int i; static char lower[] = "abcdefghijklmnopqrstuvwxyz"; static char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; for (lp = lower, up = upper; *lp != '\0'; lp++, up++) { c = *lp; cmap[c+OFFSET] = c; cmap[*up+OFFSET] = c; } for (i = 0; i < MAPSIZE; i++) if (cmap[i] == '\0') cmap[i] = (char)(i-OFFSET); mprimed = 1;}/* - casencmp - case-independent strncmp */static int /* < == > 0 */casencmp(s1, s2, len)char *s1;char *s2;int len;{ register char *p1; register char *p2; register int n; if (!mprimed) mapprime(); p1 = s1; p2 = s2; n = len; while (--n >= 0 && *p1 != '\0' && TOLOW(*p1) == TOLOW(*p2)) { p1++; p2++; } if (n < 0) return(0); /* * The following case analysis is necessary so that characters * which look negative collate low against normal characters but * high against the end-of-string NUL. */ if (*p1 == '\0' && *p2 == '\0') return(0); else if (*p1 == '\0') return(-1); else if (*p2 == '\0') return(1); else return(TOLOW(*p1) - TOLOW(*p2));}/* - mapcase - do case-mapped copy */static char * /* returns src or dst */mapcase(dst, src, siz)char *dst; /* destination, used only if mapping needed */char *src; /* source; src == dst is legal */size_t siz;{ register char *s; register char *d; register char *c; /* case break */ register char *e; /* end of source */ c = cipoint(src, siz); if (c == NULL) return(src); if (!mprimed) mapprime(); s = src; e = s + siz; d = dst; while (s < c) *d++ = *s++; while (s < e) *d++ = TOLOW(*s++); return(dst);}/* - cipoint - where in this message-ID does it become case-insensitive? * * The RFC822 code is not quite complete. Absolute, total, full RFC822 * compliance requires a horrible parsing job, because of the arcane * quoting conventions -- abc"def"ghi is not equivalent to abc"DEF"ghi, * for example. There are three or four things that might occur in the * domain part of a message-id that are case-sensitive. They don't seem * to ever occur in real news, thank Cthulhu. (What? You were expecting * a merciful and forgiving deity to be invoked in connection with RFC822? * Forget it; none of them would come near it.) */static char * /* pointer into s, or NULL for "nowhere" */cipoint(s, siz)char *s;size_t siz;{ register char *p; static char post[] = "postmaster"; static int plen = sizeof(post)-1; switch (conf.casemap) { case '0': /* unmapped, sensible */ return(NULL); break; case 'C': /* C News, RFC 822 conformant (approx.) */ p = memchr(s, '@', siz); if (p == NULL) /* no local/domain split */ return(NULL); /* assume all local */ else if (p - (s+1) == plen && CISTREQN(s+1, post, plen)) { /* crazy -- "postmaster" is case-insensitive */ return(s); } else return(p); break; case '=': /* 2.11, neither sensible nor conformant */ return(s); /* all case-insensitive */ break; } DEBUG(("cipoint: unknown case mapping `%c'\n", conf.casemap)); return(NULL); /* just leave it alone */}/* - dbzdebug - control dbz debugging at run time */int /* old value */dbzdebug(value)int value;{#ifdef DBZDEBUG register int old = debug; debug = value; return(old);#else return(-1);#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -