📄 dbz.c
字号:
return(-1); f = fopen(fn, "w"); free((POINTER)fn); if (f == NULL) { DEBUG(("dbzfresh: unable to create/truncate .pag file\n")); return(-1); } else (void) fclose(f); /* and punt to dbminit for the hard work */ return(dbminit(name));}/* - dbzsize - what's a good table size to hold this many entries? */longdbzsize(contents)long contents; /* 0 means what's the default */{ register long n; if (contents <= 0) { /* foulup or default inquiry */ DEBUG(("dbzsize: preposterous input (%ld)\n", contents)); return(DEFSIZE); } n = (contents/2)*3; /* try to keep table at most 2/3 full */ if (!(n&01)) /* make it odd */ n++; DEBUG(("dbzsize: tentative size %ld\n", n)); while (!isprime(n)) /* and look for a prime */ n += 2; DEBUG(("dbzsize: final size %ld\n", n)); return(n);}/* - isprime - is a number prime? * * This is not a terribly efficient approach. */static int /* predicate */isprime(x)register long x;{ static int quick[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 0 }; register int *ip; register long div; register long stop; /* hit the first few primes quickly to eliminate easy ones */ /* this incidentally prevents ridiculously small tables */ for (ip = quick; (div = *ip) != 0; ip++) if (x%div == 0) { DEBUG(("isprime: quick result on %ld\n", (long)x)); return(0); } /* approximate square root of x */ for (stop = x; x/stop < stop; stop >>= 1) continue; stop <<= 1; /* try odd numbers up to stop */ for (div = *--ip; div < stop; div += 2) if (x%div == 0) return(0); return(1);}/* - dbzagain - set up a new database to be a rebuild of an old one */int /* 0 success, -1 failure */dbzagain(name, oldname)char *name; /* base name; .dir and .pag must exist */char *oldname; /* base name; all must exist */{ register char *fn; struct dbzconfig c; register int i; register long top; register FILE *f; register int newtable; register of_t newsize; struct stat sb; register of_t m; if (pagf != NULL) { DEBUG(("dbzagain: database already open\n")); return(-1); } /* pick up the old configuration */ fn = enstring(oldname, dir); if (fn == NULL) return(-1); f = fopen(fn, "r"); free((POINTER)fn); if (f == NULL) { DEBUG(("dbzagain: cannot open old .dir file\n")); return(-1); } i = getconf(f, (FILE *)NULL, &c); (void) fclose(f); if (i < 0) { DEBUG(("dbzagain: getconf failed\n")); return(-1); } /* calculate tagging from old file */ if (stat(oldname, &sb) != -1) { for (m = 1, i = 0; m < sb.st_size; i++, m <<= 1) continue; /* if we had more tags than the default, use the new data */ if ((c.tagmask | c.tagenb) && m > (1 << TAGSHIFT)) { c.tagshift = i; c.tagmask = (~(unsigned long)0) >> (i + 1); c.tagenb = (c.tagmask << 1) & ~c.tagmask; } } /* tinker with it */ top = 0; newtable = 0; for (i = 0; i < NUSEDS; i++) { if (top < c.used[i]) top = c.used[i]; if (c.used[i] == 0) newtable = 1; /* hasn't got full usage history yet */ } if (top == 0) { DEBUG(("dbzagain: old table has no contents!\n")); newtable = 1; } for (i = NUSEDS-1; i > 0; i--) c.used[i] = c.used[i-1]; c.used[0] = 0; newsize = dbzsize(top); if (!newtable || newsize > c.tsize) /* don't shrink new table */ c.tsize = newsize; /* write it out */ fn = enstring(name, dir); if (fn == NULL) return(-1); f = fopen(fn, "w"); free((POINTER)fn); if (f == NULL) { DEBUG(("dbzagain: unable to write new .dir\n")); return(-1); } i = putconf(f, &c); (void) fclose(f); if (i < 0) { DEBUG(("dbzagain: putconf failed\n")); return(-1); } /* create/truncate .pag */ fn = enstring(name, pag); if (fn == NULL) return(-1); f = fopen(fn, "w"); free((POINTER)fn); if (f == NULL) { DEBUG(("dbzagain: unable to create/truncate .pag file\n")); return(-1); } else (void) fclose(f); /* and let dbminit do the work */ return(dbminit(name));}/* - dbminit - open a database, creating it (using defaults) if necessary * * We try to leave errno set plausibly, to the extent that underlying * functions permit this, since many people consult it if dbminit() fails. */int /* 0 success, -1 failure */dbminit(name)char *name;{ register int i; register size_t s; register char *dirfname; register char *pagfname; if (pagf != NULL) { DEBUG(("dbminit: dbminit already called once\n")); errno = 0; return(-1); } /* open the .dir file */ dirfname = enstring(name, dir); if (dirfname == NULL) return(-1); dirf = fopen(dirfname, "r+"); if (dirf == NULL) { dirf = fopen(dirfname, "r"); dirronly = 1; } else dirronly = 0; free((POINTER)dirfname); if (dirf == NULL) { DEBUG(("dbminit: can't open .dir file\n")); return(-1); } CloseOnExec((int)fileno(dirf), 1); /* open the .pag file */ pagfname = enstring(name, pag); if (pagfname == NULL) { (void) fclose(dirf); return(-1); } pagf = fopen(pagfname, "r+b"); if (pagf == NULL) { pagf = fopen(pagfname, "rb"); if (pagf == NULL) { DEBUG(("dbminit: .pag open failed\n")); (void) fclose(dirf); free((POINTER)pagfname); return(-1); } pagronly = 1; } else if (dirronly) pagronly = 1; else pagronly = 0; if (pagf != NULL) CloseOnExec((int)fileno(pagf), 1);#ifdef NOBUFFER /* * B News does not do adequate locking on its database accesses. * Why it doesn't get into trouble using dbm is a mystery. In any * case, doing unbuffered i/o does not cure the problem, but does * enormously reduce its incidence. */ (void) setbuf(pagf, (char *)NULL);#else#ifdef _IOFBF (void) setvbuf(pagf, (char *)pagbuf, _IOFBF, sizeof(pagbuf));#endif#endif pagpos = -1; /* don't free pagfname, need it below */ /* open the base file */ basef = fopen(name, "r"); if (basef == NULL) { DEBUG(("dbminit: basefile open failed\n")); basefname = enstring(name, ""); if (basefname == NULL) { (void) fclose(pagf); (void) fclose(dirf); free((POINTER)pagfname); pagf = NULL; return(-1); } } else basefname = NULL; if (basef != NULL) CloseOnExec((int)fileno(basef), 1);#ifdef _IOFBF if (basef != NULL) (void) setvbuf(basef, basebuf, _IOFBF, sizeof(basebuf));#endif /* pick up configuration */ if (getconf(dirf, pagf, &conf) < 0) { DEBUG(("dbminit: getconf failure\n")); (void) fclose(basef); (void) fclose(pagf); (void) fclose(dirf); free((POINTER)pagfname); pagf = NULL; errno = EDOM; /* kind of a kludge, but very portable */ return(-1); } tagbits = conf.tagmask << conf.tagshift; taghere = conf.tagenb << conf.tagshift; tagboth = tagbits | taghere; mybytemap(mybmap); bytesame = 1; for (i = 0; i < SOF; i++) if (mybmap[i] != conf.bytemap[i]) bytesame = 0; /* get first table into core, if it looks desirable and feasible */ s = (size_t)conf.tsize * SOF; if (incore && (of_t)(s/SOF) == conf.tsize) { bufpagf = fopen(pagfname, (pagronly) ? "rb" : "r+b"); if (bufpagf != NULL) { corepag = getcore(bufpagf); CloseOnExec((int)fileno(bufpagf), 1); } } else { bufpagf = NULL; corepag = NULL; } free((POINTER)pagfname); /* misc. setup */ crcinit(); written = 0; prevp = FRESH; DEBUG(("dbminit: succeeded\n")); return(0);}/* - enstring - concatenate two strings into a malloced area */static char * /* NULL if malloc fails */enstring(s1, s2)char *s1;char *s2;{ register char *p; p = malloc((size_t)strlen(s1) + (size_t)strlen(s2) + 1); if (p != NULL) { (void) strcpy(p, s1); (void) strcat(p, s2); } else { DEBUG(("enstring(%s, %s) out of memory\n", s1, s2)); } return(p);}/* - dbmclose - close a database */intdbmclose(){ register int ret = 0; if (pagf == NULL) { DEBUG(("dbmclose: not opened!\n")); return(-1); } if (fclose(pagf) == EOF) { DEBUG(("dbmclose: fclose(pagf) failed\n")); ret = -1; } pagf = basef; /* ensure valid pointer; dbzsync checks it */ if (dbzsync() < 0) ret = -1; if (bufpagf != NULL && fclose(bufpagf) == EOF) { DEBUG(("dbmclose: fclose(bufpagf) failed\n")); ret = -1; } if (corepag != NULL)#ifdef MMAP if (munmap(corepag, (int)conf.tsize * SOF) == -1) { DEBUG(("dbmclose: munmap failed\n")); ret = -1; }#else free((POINTER)corepag);#endif corepag = NULL; if (fclose(basef) == EOF) { DEBUG(("dbmclose: fclose(basef) failed\n")); ret = -1; } if (basefname != NULL) free((POINTER)basefname); basef = NULL; pagf = NULL; if (fclose(dirf) == EOF) { DEBUG(("dbmclose: fclose(dirf) failed\n")); ret = -1; } DEBUG(("dbmclose: %s\n", (ret == 0) ? "succeeded" : "failed")); return(ret);}/* - dbzsync - push all in-core data out to disk */intdbzsync(){ register int ret = 0; if (pagf == NULL) { DEBUG(("dbzsync: not opened!\n")); return(-1); } if (!written) return(0);#ifndef MMAP if (corepag != NULL && !writethrough) { if (putcore(corepag, bufpagf) < 0) { DEBUG(("dbzsync: putcore failed\n")); ret = -1; } }#endif if (!conf.olddbz) if (putconf(dirf, &conf) < 0) ret = -1; DEBUG(("dbzsync: %s\n", (ret == 0) ? "succeeded" : "failed")); return(ret);}/* - dbzcancel - cancel writing of in-core data * Mostly for use from child processes. * Note that we don't need to futz around with stdio buffers, because we * always fflush them immediately anyway and so they never have stale data. */intdbzcancel(){ if (pagf == NULL) { DEBUG(("dbzcancel: not opened!\n")); return(-1); } written = 0; return(0);}/* - dbzfetch - fetch() with case mapping built in */datumdbzfetch(key)datum key;{ char buffer[DBZMAXKEY + 1]; datum mappedkey; register size_t keysize; DEBUG(("dbzfetch: (%s)\n", key.dptr)); /* Key is supposed to be less than DBZMAXKEY */ keysize = key.dsize; if (keysize >= DBZMAXKEY) { keysize = DBZMAXKEY; DEBUG(("keysize is %d - truncated to %d\n", key.dsize, DBZMAXKEY)); } mappedkey.dptr = mapcase(buffer, key.dptr, keysize); buffer[keysize] = '\0'; /* just a debug aid */ mappedkey.dsize = keysize; return(fetch(mappedkey));}/* - fetch - get an entry from the database * * Disgusting fine point, in the name of backward compatibility: if the * last character of "key" is a NUL, that character is (effectively) not * part of the comparison against the stored keys. */datum /* dptr NULL, dsize 0 means failure */fetch(key)datum key;{ char buffer[DBZMAXKEY + 1]; static of_t key_ptr; /* return value points here */ datum output; register size_t keysize; register size_t cmplen;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -