1 /* cdblib.c - all CDB library functions.
3 * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
6 * Taken from tinycdb-0.73 and merged into one file for easier
7 * inclusion into Dirmngr. By Werner Koch <wk@gnupg.org> 2003-12-12.
10 /* A cdb database is a single file used to map 'keys' to 'values',
11 having records of (key,value) pairs. File consists of 3 parts: toc
12 (table of contents), data and index (hash tables).
14 Toc has fixed length of 2048 bytes, containing 256 pointers to hash
15 tables inside index sections. Every pointer consists of position
16 of a hash table in bytes from the beginning of a file, and a size
17 of a hash table in entries, both are 4-bytes (32 bits) unsigned
18 integers in little-endian form. Hash table length may have zero
19 length, meaning that corresponding hash table is empty.
21 Right after toc section, data section follows without any
22 alignment. It consists of series of records, each is a key length,
23 value (data) length, key and value. Again, key and value length
24 are 4-byte unsigned integers. Each next record follows previous
25 without any special alignment.
27 After data section, index (hash tables) section follows. It should
28 be looked to in conjunction with toc section, where each of max 256
29 hash tables are defined. Index section consists of series of hash
30 tables, with starting position and length defined in toc section.
31 Every hash table is a sequence of records each holds two numbers:
32 key's hash value and record position inside data section (bytes
33 from the beginning of a file to first byte of key length starting
34 data record). If record position is zero, then this is an empty
35 hash table slot, pointed to nowhere.
38 hv = ((hv << 5) + hv) ^ c
39 for every single c byte of a key, starting with hv = 5381.
41 Toc section indexed by (hv % 256), i.e. hash value modulo 256
42 (number of entries in toc section).
44 In order to find a record, one should: first, compute the hash
45 value (hv) of a key. Second, look to hash table number hv modulo
46 256. If it is empty, then there is no such key exists. If it is
47 not empty, then third, loop by slots inside that hash table,
48 starting from slot with number hv divided by 256 modulo length of
49 that table, or ((hv / 256) % htlen), searching for this hv in hash
50 table. Stop search on empty slot (if record position is zero) or
51 when all slots was probed (note cyclic search, jumping from end to
52 beginning of a table). When hash value in question is found in
53 hash table, look to key of corresponding record, comparing it with
54 key in question. If them of the same length and equals to each
55 other, then record is found, otherwise, repeat with next hash table
56 slot. Note that there may be several records with the same key.
66 #include <sys/types.h>
70 # include <sys/mman.h>
72 # define MAP_FAILED ((void*)-1)
77 #include "dirmngr-err.h"
81 # define EPROTO EINVAL
96 struct cdb_rec rec[254];
99 static int make_find(struct cdb_make *cdbmp,
100 const void *key, cdbi_t klen, cdbi_t hval,
101 struct cdb_rl **rlp);
102 static int make_write(struct cdb_make *cdbmp,
103 const char *ptr, cdbi_t len);
107 /* Initializes structure given by CDBP pointer and associates it with
108 the open file descriptor FD. Allocate memory for the structure
109 itself if needed and file open operation should be done by
110 application. File FD should be opened at least read-only, and
111 should be seekable. Routine returns 0 on success or negative value
114 cdb_init(struct cdb *cdbp, int fd)
119 HANDLE hFile, hMapping;
125 if (fstat(fd, &st) < 0)
127 /* trivial sanity check: at least toc should be here */
128 if (st.st_size < 2048) {
129 gpg_err_set_errno (EPROTO);
132 /* memory-map file */
134 hFile = (HANDLE) _get_osfhandle(fd);
135 if (hFile == (HANDLE) -1)
137 hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
140 mem = (unsigned char *)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
143 cdbp->cdb_mapping = hMapping;
145 fsize = (unsigned int)(st.st_size & 0xffffffffu);
146 mem = (unsigned char*)mmap(NULL, fsize, PROT_READ, MAP_SHARED, fd, 0);
147 if (mem == MAP_FAILED)
152 cdbp->cdb_fsize = st.st_size;
156 /* XXX don't know well about madvise syscall -- is it legal
157 to set different options for parts of one mmap() region?
158 There is also posix_madvise() exist, with POSIX_MADV_RANDOM etc...
161 /* set madvise() parameters. Ignore errors for now if system
162 doesn't support it */
163 madvise(mem, 2048, MADV_WILLNEED);
164 madvise(mem + 2048, cdbp->cdb_fsize - 2048, MADV_RANDOM);
168 cdbp->cdb_vpos = cdbp->cdb_vlen = 0;
174 /* Frees the internal resources held by structure. Note that this
175 routine does not close the file. */
177 cdb_free(struct cdb *cdbp)
181 UnmapViewOfFile ((void*) cdbp->cdb_mem);
182 CloseHandle (cdbp->cdb_mapping);
183 cdbp->cdb_mapping = NULL;
185 munmap((void*)cdbp->cdb_mem, cdbp->cdb_fsize);
187 cdbp->cdb_mem = NULL;
193 /* Read data from cdb file, starting at position pos of length len,
194 placing result to buf. This routine may be used to get actual
195 value found by cdb_find() or other routines that returns position
196 and length of a data. Returns 0 on success or negative value on
199 cdb_read(const struct cdb *cdbp, void *buf, unsigned len, cdbi_t pos)
201 if (pos > cdbp->cdb_fsize || cdbp->cdb_fsize - pos < len) {
202 gpg_err_set_errno (EPROTO);
205 memcpy(buf, cdbp->cdb_mem + pos, len);
210 /* Attempts to find a key given by (key,klen) parameters. If key
211 exists in database, routine returns 1 and places position and
212 length of value associated with this key to internal fields inside
213 cdbp structure, to be accessible by cdb_datapos() and
214 cdb_datalen(). If key is not in database, routines returns 0. On
215 error, negative value is returned. Note that using cdb_find() it
216 is possible to lookup only first record with a given key. */
218 cdb_find(struct cdb *cdbp, const void *key, cdbi_t klen)
220 const unsigned char *htp; /* hash table pointer */
221 const unsigned char *htab; /* hash table */
222 const unsigned char *htend; /* end of hash table */
223 cdbi_t httodo; /* ht bytes left to look */
228 if (klen > cdbp->cdb_fsize) /* if key size is larger than file */
231 hval = cdb_hash(key, klen);
233 /* find (pos,n) hash table to use */
234 /* first 2048 bytes (toc) are always available */
235 /* (hval % 256) * 8 */
236 htp = cdbp->cdb_mem + ((hval << 3) & 2047); /* index in toc (256x8) */
237 n = cdb_unpack(htp + 4); /* table size */
238 if (!n) /* empty table */
239 return 0; /* not found */
240 httodo = n << 3; /* bytes of htab to lookup */
241 pos = cdb_unpack(htp); /* htab position */
242 if (n > (cdbp->cdb_fsize >> 3) /* overflow of httodo ? */
243 || pos > cdbp->cdb_fsize /* htab start within file ? */
244 || httodo > cdbp->cdb_fsize - pos) /* htab entry within file ? */
246 gpg_err_set_errno (EPROTO);
250 htab = cdbp->cdb_mem + pos; /* htab pointer */
251 htend = htab + httodo; /* after end of htab */
252 /* htab starting position: rest of hval modulo htsize, 8bytes per elt */
253 htp = htab + (((hval >> 8) % n) << 3);
256 pos = cdb_unpack(htp + 4); /* record position */
259 if (cdb_unpack(htp) == hval) {
260 if (pos > cdbp->cdb_fsize - 8) { /* key+val lengths */
261 gpg_err_set_errno (EPROTO);
264 if (cdb_unpack(cdbp->cdb_mem + pos) == klen) {
265 if (cdbp->cdb_fsize - klen < pos + 8) {
266 gpg_err_set_errno (EPROTO);
269 if (memcmp(key, cdbp->cdb_mem + pos + 8, klen) == 0) {
270 n = cdb_unpack(cdbp->cdb_mem + pos + 4);
272 if (cdbp->cdb_fsize < n || cdbp->cdb_fsize - n < pos) {
273 gpg_err_set_errno (EPROTO);
276 cdbp->cdb_vpos = pos;
285 if ((htp += 8) >= htend)
293 /* Sequential-find routines that used separate structure. It is
294 possible to have many than one record with the same key in a
295 database, and these routines allow enumeration of all of them.
296 cdb_findinit() initializes search structure pointed to by cdbfp.
297 It will return negative value on error or 0 on success.
298 cdb_findnext() attempts to find next matching key, setting value
299 position and length in cdbfp structure. It will return positive
300 value if given key was found, 0 if there is no more such key(s), or
301 negative value on error. To access value position and length after
302 successeful call to cdb_findnext() (when it returned positive
303 result), use cdb_datapos() and cdb_datalen() macros with cdbp
304 pointer. It is error to use cdb_findnext() after it returned 0 or
305 error condition. These routines is a bit slower than cdb_find().
307 Setting KEY to NULL will start a sequential search through the
311 cdb_findinit(struct cdb_find *cdbfp, struct cdb *cdbp,
312 const void *key, cdbi_t klen)
316 cdbfp->cdb_cdbp = cdbp;
317 cdbfp->cdb_key = key;
318 cdbfp->cdb_klen = klen;
319 cdbfp->cdb_hval = key? cdb_hash(key, klen) : 0;
323 cdbfp->cdb_htp = cdbp->cdb_mem + ((cdbfp->cdb_hval << 3) & 2047);
324 n = cdb_unpack(cdbfp->cdb_htp + 4);
325 cdbfp->cdb_httodo = n << 3; /* Set to size of hash table. */
327 return 0; /* The hash table is empry. */
328 pos = cdb_unpack(cdbfp->cdb_htp);
329 if (n > (cdbp->cdb_fsize >> 3)
330 || pos > cdbp->cdb_fsize
331 || cdbfp->cdb_httodo > cdbp->cdb_fsize - pos)
333 gpg_err_set_errno (EPROTO);
337 cdbfp->cdb_htab = cdbp->cdb_mem + pos;
338 cdbfp->cdb_htend = cdbfp->cdb_htab + cdbfp->cdb_httodo;
339 cdbfp->cdb_htp = cdbfp->cdb_htab + (((cdbfp->cdb_hval >> 8) % n) << 3);
341 else /* Walk over all entries. */
344 /* Force stepping in findnext. */
345 cdbfp->cdb_htp = cdbfp->cdb_htend = cdbp->cdb_mem;
351 /* See cdb_findinit. */
353 cdb_findnext(struct cdb_find *cdbfp)
356 struct cdb *cdbp = cdbfp->cdb_cdbp;
360 while(cdbfp->cdb_httodo) {
361 pos = cdb_unpack(cdbfp->cdb_htp + 4);
364 n = cdb_unpack(cdbfp->cdb_htp) == cdbfp->cdb_hval;
365 if ((cdbfp->cdb_htp += 8) >= cdbfp->cdb_htend)
366 cdbfp->cdb_htp = cdbfp->cdb_htab;
367 cdbfp->cdb_httodo -= 8;
369 if (pos > cdbp->cdb_fsize - 8) {
370 gpg_err_set_errno (EPROTO);
373 if (cdb_unpack(cdbp->cdb_mem + pos) == cdbfp->cdb_klen) {
374 if (cdbp->cdb_fsize - cdbfp->cdb_klen < pos + 8) {
375 gpg_err_set_errno (EPROTO);
378 if (memcmp(cdbfp->cdb_key,
379 cdbp->cdb_mem + pos + 8, cdbfp->cdb_klen) == 0) {
380 n = cdb_unpack(cdbp->cdb_mem + pos + 4);
381 pos += 8 + cdbfp->cdb_klen;
382 if (cdbp->cdb_fsize < n || cdbp->cdb_fsize - n < pos) {
383 gpg_err_set_errno (EPROTO);
386 cdbp->cdb_vpos = pos;
394 else /* Walk over all entries. */
398 while (cdbfp->cdb_htp >= cdbfp->cdb_htend)
400 if (cdbfp->cdb_hval > 255)
401 return 0; /* No more items. */
403 cdbfp->cdb_htp = cdbp->cdb_mem + cdbfp->cdb_hval * 8;
404 cdbfp->cdb_hval++; /* Advance for next round. */
405 pos = cdb_unpack (cdbfp->cdb_htp); /* Offset of table. */
406 n = cdb_unpack (cdbfp->cdb_htp + 4); /* Number of entries. */
407 cdbfp->cdb_httodo = n * 8; /* Size of table. */
408 if (n > (cdbp->cdb_fsize / 8)
409 || pos > cdbp->cdb_fsize
410 || cdbfp->cdb_httodo > cdbp->cdb_fsize - pos)
412 gpg_err_set_errno (EPROTO);
416 cdbfp->cdb_htab = cdbp->cdb_mem + pos;
417 cdbfp->cdb_htend = cdbfp->cdb_htab + cdbfp->cdb_httodo;
418 cdbfp->cdb_htp = cdbfp->cdb_htab;
421 pos = cdb_unpack (cdbfp->cdb_htp + 4); /* Offset of record. */
425 if (pos > cdbp->cdb_fsize - 8)
427 gpg_err_set_errno (EPROTO);
431 cdbp->cdb_kpos = pos + 8;
432 cdbp->cdb_klen = cdb_unpack(cdbp->cdb_mem + pos);
433 cdbp->cdb_vpos = pos + 8 + cdbp->cdb_klen;
434 cdbp->cdb_vlen = cdb_unpack(cdbp->cdb_mem + pos + 4);
435 n = 8 + cdbp->cdb_klen + cdbp->cdb_vlen;
436 if ( pos > cdbp->cdb_fsize || pos > cdbp->cdb_fsize - n)
438 gpg_err_set_errno (EPROTO);
441 return 1; /* Found. */
446 /* Read a chunk from file, ignoring interrupts (EINTR) */
448 cdb_bread(int fd, void *buf, int len)
452 do l = read(fd, buf, len);
453 while(l < 0 && errno == EINTR);
456 gpg_err_set_errno (EIO);
459 buf = (char*)buf + l;
465 /* Find a given key in cdb file, seek a file pointer to it's value and
466 place data length to *dlenp. */
468 cdb_seek(int fd, const void *key, unsigned klen, cdbi_t *dlenp)
470 cdbi_t htstart; /* hash table start position */
471 cdbi_t htsize; /* number of elements in a hash table */
472 cdbi_t httodo; /* hash table elements left to look */
473 cdbi_t hti; /* hash table index */
474 cdbi_t pos; /* position in a file */
475 cdbi_t hval; /* key's hash value */
476 unsigned char rbuf[64]; /* read buffer */
477 int needseek = 1; /* if we should seek to a hash slot */
479 hval = cdb_hash(key, klen);
480 pos = (hval & 0xff) << 3; /* position in TOC */
481 /* read the hash table parameters */
482 if (lseek(fd, pos, SEEK_SET) < 0 || cdb_bread(fd, rbuf, 8) < 0)
484 if ((htsize = cdb_unpack(rbuf + 4)) == 0)
486 hti = (hval >> 8) % htsize; /* start position in hash table */
488 htstart = cdb_unpack(rbuf);
491 if (needseek && lseek(fd, htstart + (hti << 3), SEEK_SET) < 0)
493 if (cdb_bread(fd, rbuf, 8) < 0)
495 if ((pos = cdb_unpack(rbuf + 4)) == 0) /* not found */
498 if (cdb_unpack(rbuf) != hval) /* hash value not matched */
500 else { /* hash value matched */
501 if (lseek(fd, pos, SEEK_SET) < 0 || cdb_bread(fd, rbuf, 8) < 0)
503 if (cdb_unpack(rbuf) == klen) { /* key length matches */
504 /* read the key from file and compare with wanted */
506 const char *k = (const char*)key;
508 *dlenp = cdb_unpack(rbuf + 4); /* save value length */
510 if (!l) /* the whole key read and matches, return */
512 c = l > sizeof(rbuf) ? sizeof(rbuf) : l;
513 if (cdb_bread(fd, rbuf, c) < 0)
515 if (memcmp(rbuf, k, c) != 0) /* no, it differs, stop here */
520 needseek = 1; /* we're looked to other place, should seek back */
524 if (++hti == htsize) {
532 cdb_unpack(const unsigned char buf[4])
535 n <<= 8; n |= buf[2];
536 n <<= 8; n |= buf[1];
537 n <<= 8; n |= buf[0];
541 /* Add record with key (KEY,KLEN) and value (VAL,VLEN) to a database.
542 Returns 0 on success or negative value on error. Note that this
543 routine does not checks if given key already exists, but cdb_find()
544 will not see second record with the same key. It is not possible
545 to continue building a database if cdb_make_add() returned an error
548 cdb_make_add(struct cdb_make *cdbmp,
549 const void *key, cdbi_t klen,
550 const void *val, cdbi_t vlen)
552 unsigned char rlen[8];
555 if (klen > 0xffffffff - (cdbmp->cdb_dpos + 8) ||
556 vlen > 0xffffffff - (cdbmp->cdb_dpos + klen + 8)) {
557 gpg_err_set_errno (ENOMEM);
560 hval = cdb_hash(key, klen);
561 rl = cdbmp->cdb_rec[hval&255];
562 if (!rl || rl->cnt >= sizeof(rl->rec)/sizeof(rl->rec[0])) {
563 rl = (struct cdb_rl*)malloc(sizeof(struct cdb_rl));
565 gpg_err_set_errno (ENOMEM);
569 rl->next = cdbmp->cdb_rec[hval&255];
570 cdbmp->cdb_rec[hval&255] = rl;
572 rl->rec[rl->cnt].hval = hval;
573 rl->rec[rl->cnt].rpos = cdbmp->cdb_dpos;
576 cdb_pack(klen, rlen);
577 cdb_pack(vlen, rlen + 4);
578 if (make_write(cdbmp, rlen, 8) < 0 ||
579 make_write(cdbmp, key, klen) < 0 ||
580 make_write(cdbmp, val, vlen) < 0)
586 cdb_make_put(struct cdb_make *cdbmp,
587 const void *key, cdbi_t klen,
588 const void *val, cdbi_t vlen,
591 unsigned char rlen[8];
592 cdbi_t hval = cdb_hash(key, klen);
597 case CDB_PUT_REPLACE:
600 c = make_find(cdbmp, key, klen, hval, &rl);
604 if (flags == CDB_PUT_INSERT) {
605 gpg_err_set_errno (EEXIST);
608 else if (flags == CDB_PUT_REPLACE) {
619 rl = cdbmp->cdb_rec[hval&255];
620 if (!rl || rl->cnt >= sizeof(rl->rec)/sizeof(rl->rec[0])) {
621 rl = (struct cdb_rl*)malloc(sizeof(struct cdb_rl));
623 gpg_err_set_errno (ENOMEM);
627 rl->next = cdbmp->cdb_rec[hval&255];
628 cdbmp->cdb_rec[hval&255] = rl;
635 gpg_err_set_errno (EINVAL);
639 if (klen > 0xffffffff - (cdbmp->cdb_dpos + 8) ||
640 vlen > 0xffffffff - (cdbmp->cdb_dpos + klen + 8)) {
641 gpg_err_set_errno (ENOMEM);
644 rl->rec[c].hval = hval;
645 rl->rec[c].rpos = cdbmp->cdb_dpos;
650 cdb_pack(klen, rlen);
651 cdb_pack(vlen, rlen + 4);
652 if (make_write(cdbmp, rlen, 8) < 0 ||
653 make_write(cdbmp, key, klen) < 0 ||
654 make_write(cdbmp, val, vlen) < 0)
661 match(int fd, cdbi_t pos, const char *key, cdbi_t klen)
663 unsigned char buf[64]; /*XXX cdb_buf may be used here instead */
664 if (lseek(fd, pos, SEEK_SET) < 0 || read(fd, buf, 8) != 8)
666 if (cdb_unpack(buf) != klen)
669 while(klen > sizeof(buf)) {
670 if (read(fd, buf, sizeof(buf)) != sizeof(buf))
672 if (memcmp(buf, key, sizeof(buf)) != 0)
678 if (read(fd, buf, klen) != klen)
680 if (memcmp(buf, key, klen) != 0)
688 make_find (struct cdb_make *cdbmp,
689 const void *key, cdbi_t klen, cdbi_t hval,
692 struct cdb_rl *rl = cdbmp->cdb_rec[hval&255];
696 for(i = rl->cnt - 1; i >= 0; --i) { /* search backward */
697 if (rl->rec[i].hval != hval)
699 /*XXX this explicit flush may be unnecessary having
700 * smarter match() that looks to cdb_buf too, but
701 * most of a time here spent in finding hash values
702 * (above), not keys */
703 if (cdbmp->cdb_bpos != cdbmp->cdb_buf) {
704 if (write(cdbmp->cdb_fd, cdbmp->cdb_buf,
705 cdbmp->cdb_bpos - cdbmp->cdb_buf) < 0)
707 cdbmp->cdb_bpos = cdbmp->cdb_buf;
710 r = match(cdbmp->cdb_fd, rl->rec[i].rpos, key, klen);
715 if (lseek(cdbmp->cdb_fd, cdbmp->cdb_dpos, SEEK_SET) < 0)
723 if (sought && lseek(cdbmp->cdb_fd, cdbmp->cdb_dpos, SEEK_SET) < 0)
729 cdb_make_exists(struct cdb_make *cdbmp,
730 const void *key, cdbi_t klen)
732 return make_find(cdbmp, key, klen, cdb_hash(key, klen), NULL);
737 cdb_pack(cdbi_t num, unsigned char buf[4])
739 buf[0] = num & 255; num >>= 8;
740 buf[1] = num & 255; num >>= 8;
746 /* Initializes structure to create a database. File FD should be
747 opened read-write and should be seekable. Returns 0 on success or
748 negative value on error. */
750 cdb_make_start(struct cdb_make *cdbmp, int fd)
752 memset (cdbmp, 0, sizeof *cdbmp);
754 cdbmp->cdb_dpos = 2048;
755 cdbmp->cdb_bpos = cdbmp->cdb_buf + 2048;
761 ewrite(int fd, const char *buf, int len)
764 int l = write(fd, buf, len);
765 if (l < 0 && errno != EINTR)
777 make_write(struct cdb_make *cdbmp, const char *ptr, cdbi_t len)
779 cdbi_t l = sizeof(cdbmp->cdb_buf) - (cdbmp->cdb_bpos - cdbmp->cdb_buf);
780 cdbmp->cdb_dpos += len;
782 memcpy(cdbmp->cdb_bpos, ptr, l);
783 if (ewrite(cdbmp->cdb_fd, cdbmp->cdb_buf, sizeof(cdbmp->cdb_buf)) < 0)
786 l = len / sizeof(cdbmp->cdb_buf);
788 l *= sizeof(cdbmp->cdb_buf);
789 if (ewrite(cdbmp->cdb_fd, ptr, l) < 0)
793 cdbmp->cdb_bpos = cdbmp->cdb_buf;
796 memcpy(cdbmp->cdb_bpos, ptr, len);
797 cdbmp->cdb_bpos += len;
803 cdb_make_finish_internal(struct cdb_make *cdbmp)
805 cdbi_t hcnt[256]; /* hash table counts */
806 cdbi_t hpos[256]; /* hash table positions */
807 struct cdb_rec *htab;
813 if (((0xffffffff - cdbmp->cdb_dpos) >> 3) < cdbmp->cdb_rcnt) {
814 gpg_err_set_errno (ENOMEM);
818 /* count htab sizes and reorder reclists */
820 for (t = 0; t < 256; ++t) {
821 struct cdb_rl *rlt = NULL;
823 rl = cdbmp->cdb_rec[t];
825 struct cdb_rl *rln = rl->next;
831 cdbmp->cdb_rec[t] = rlt;
832 if (hsize < (hcnt[t] = i << 1))
836 /* allocate memory to hold max htable */
837 htab = (struct cdb_rec*)malloc((hsize + 2) * sizeof(struct cdb_rec));
839 gpg_err_set_errno (ENOENT);
842 p = (unsigned char *)htab;
845 /* build hash tables */
846 for (t = 0; t < 256; ++t) {
848 hpos[t] = cdbmp->cdb_dpos;
849 if ((len = hcnt[t]) == 0)
851 for (i = 0; i < len; ++i)
852 htab[i].hval = htab[i].rpos = 0;
853 for (rl = cdbmp->cdb_rec[t]; rl; rl = rl->next)
854 for (i = 0; i < rl->cnt; ++i) {
855 hi = (rl->rec[i].hval >> 8) % len;
859 htab[hi] = rl->rec[i];
861 for (i = 0; i < len; ++i) {
862 cdb_pack(htab[i].hval, p + (i << 3));
863 cdb_pack(htab[i].rpos, p + (i << 3) + 4);
865 if (make_write(cdbmp, p, len << 3) < 0) {
871 if (cdbmp->cdb_bpos != cdbmp->cdb_buf &&
872 ewrite(cdbmp->cdb_fd, cdbmp->cdb_buf,
873 cdbmp->cdb_bpos - cdbmp->cdb_buf) != 0)
876 for (t = 0; t < 256; ++t) {
877 cdb_pack(hpos[t], p + (t << 3));
878 cdb_pack(hcnt[t], p + (t << 3) + 4);
880 if (lseek(cdbmp->cdb_fd, 0, 0) != 0 ||
881 ewrite(cdbmp->cdb_fd, p, 2048) != 0)
888 cdb_make_free(struct cdb_make *cdbmp)
891 for(t = 0; t < 256; ++t) {
892 struct cdb_rl *rl = cdbmp->cdb_rec[t];
894 struct cdb_rl *tm = rl;
903 /* Finalizes database file, constructing all needed indexes, and frees
904 memory structures. It does not close the file descriptor. Returns
905 0 on success or a negative value on error. */
907 cdb_make_finish(struct cdb_make *cdbmp)
909 int r = cdb_make_finish_internal(cdbmp);
910 cdb_make_free(cdbmp);
916 cdb_hash(const void *buf, cdbi_t len)
918 register const unsigned char *p = (const unsigned char *)buf;
919 register const unsigned char *end = p + len;
920 register cdbi_t hash = 5381; /* start value */
922 hash = (hash + (hash << 5)) ^ *p++;