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 alingment. 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, overwise, 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 # ifdef __MINGW32CE__
137 hFile = (HANDLE) _get_osfhandle(fd);
139 if (hFile == (HANDLE) -1)
141 hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
144 mem = (unsigned char *)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
147 cdbp->cdb_mapping = hMapping;
149 fsize = (unsigned int)(st.st_size & 0xffffffffu);
150 mem = (unsigned char*)mmap(NULL, fsize, PROT_READ, MAP_SHARED, fd, 0);
151 if (mem == MAP_FAILED)
156 cdbp->cdb_fsize = st.st_size;
160 /* XXX don't know well about madvise syscall -- is it legal
161 to set different options for parts of one mmap() region?
162 There is also posix_madvise() exist, with POSIX_MADV_RANDOM etc...
165 /* set madvise() parameters. Ignore errors for now if system
166 doesn't support it */
167 madvise(mem, 2048, MADV_WILLNEED);
168 madvise(mem + 2048, cdbp->cdb_fsize - 2048, MADV_RANDOM);
172 cdbp->cdb_vpos = cdbp->cdb_vlen = 0;
178 /* Frees the internal resources held by structure. Note that this
179 routine does not close the file. */
181 cdb_free(struct cdb *cdbp)
185 UnmapViewOfFile ((void*) cdbp->cdb_mem);
186 CloseHandle (cdbp->cdb_mapping);
187 cdbp->cdb_mapping = NULL;
189 munmap((void*)cdbp->cdb_mem, cdbp->cdb_fsize);
191 cdbp->cdb_mem = NULL;
197 /* Read data from cdb file, starting at position pos of length len,
198 placing result to buf. This routine may be used to get actual
199 value found by cdb_find() or other routines that returns position
200 and length of a data. Returns 0 on success or negative value on
203 cdb_read(const struct cdb *cdbp, void *buf, unsigned len, cdbi_t pos)
205 if (pos > cdbp->cdb_fsize || cdbp->cdb_fsize - pos < len) {
206 gpg_err_set_errno (EPROTO);
209 memcpy(buf, cdbp->cdb_mem + pos, len);
214 /* Attempts to find a key given by (key,klen) parameters. If key
215 exists in database, routine returns 1 and places position and
216 length of value associated with this key to internal fields inside
217 cdbp structure, to be accessible by cdb_datapos() and
218 cdb_datalen(). If key is not in database, routines returns 0. On
219 error, negative value is returned. Note that using cdb_find() it
220 is possible to lookup only first record with a given key. */
222 cdb_find(struct cdb *cdbp, const void *key, cdbi_t klen)
224 const unsigned char *htp; /* hash table pointer */
225 const unsigned char *htab; /* hash table */
226 const unsigned char *htend; /* end of hash table */
227 cdbi_t httodo; /* ht bytes left to look */
232 if (klen > cdbp->cdb_fsize) /* if key size is larger than file */
235 hval = cdb_hash(key, klen);
237 /* find (pos,n) hash table to use */
238 /* first 2048 bytes (toc) are always available */
239 /* (hval % 256) * 8 */
240 htp = cdbp->cdb_mem + ((hval << 3) & 2047); /* index in toc (256x8) */
241 n = cdb_unpack(htp + 4); /* table size */
242 if (!n) /* empty table */
243 return 0; /* not found */
244 httodo = n << 3; /* bytes of htab to lookup */
245 pos = cdb_unpack(htp); /* htab position */
246 if (n > (cdbp->cdb_fsize >> 3) /* overflow of httodo ? */
247 || pos > cdbp->cdb_fsize /* htab start within file ? */
248 || httodo > cdbp->cdb_fsize - pos) /* entrie htab within file ? */
250 gpg_err_set_errno (EPROTO);
254 htab = cdbp->cdb_mem + pos; /* htab pointer */
255 htend = htab + httodo; /* after end of htab */
256 /* htab starting position: rest of hval modulo htsize, 8bytes per elt */
257 htp = htab + (((hval >> 8) % n) << 3);
260 pos = cdb_unpack(htp + 4); /* record position */
263 if (cdb_unpack(htp) == hval) {
264 if (pos > cdbp->cdb_fsize - 8) { /* key+val lengths */
265 gpg_err_set_errno (EPROTO);
268 if (cdb_unpack(cdbp->cdb_mem + pos) == klen) {
269 if (cdbp->cdb_fsize - klen < pos + 8) {
270 gpg_err_set_errno (EPROTO);
273 if (memcmp(key, cdbp->cdb_mem + pos + 8, klen) == 0) {
274 n = cdb_unpack(cdbp->cdb_mem + pos + 4);
276 if (cdbp->cdb_fsize < n || cdbp->cdb_fsize - n < pos) {
277 gpg_err_set_errno (EPROTO);
280 cdbp->cdb_vpos = pos;
289 if ((htp += 8) >= htend)
297 /* Sequential-find routines that used separate structure. It is
298 possible to have many than one record with the same key in a
299 database, and these routines allows to enumerate all them.
300 cdb_findinit() initializes search structure pointed to by cdbfp.
301 It will return negative value on error or 0 on success. cdb_findÂ
302 next() attempts to find next matching key, setting value position
303 and length in cdbfp structure. It will return positive value if
304 given key was found, 0 if there is no more such key(s), or negative
305 value on error. To access value position and length after
306 successeful call to cdb_findnext() (when it returned positive
307 result), use cdb_datapos() and cdb_datalen() macros with cdbp
308 pointer. It is error to use cdb_findnext() after it returned 0 or
309 error condition. These routines is a bit slower than
312 Setting KEY to NULL will start a sequential search through the
316 cdb_findinit(struct cdb_find *cdbfp, struct cdb *cdbp,
317 const void *key, cdbi_t klen)
321 cdbfp->cdb_cdbp = cdbp;
322 cdbfp->cdb_key = key;
323 cdbfp->cdb_klen = klen;
324 cdbfp->cdb_hval = key? cdb_hash(key, klen) : 0;
328 cdbfp->cdb_htp = cdbp->cdb_mem + ((cdbfp->cdb_hval << 3) & 2047);
329 n = cdb_unpack(cdbfp->cdb_htp + 4);
330 cdbfp->cdb_httodo = n << 3; /* Set to size of hash table. */
332 return 0; /* The hash table is empry. */
333 pos = cdb_unpack(cdbfp->cdb_htp);
334 if (n > (cdbp->cdb_fsize >> 3)
335 || pos > cdbp->cdb_fsize
336 || cdbfp->cdb_httodo > cdbp->cdb_fsize - pos)
338 gpg_err_set_errno (EPROTO);
342 cdbfp->cdb_htab = cdbp->cdb_mem + pos;
343 cdbfp->cdb_htend = cdbfp->cdb_htab + cdbfp->cdb_httodo;
344 cdbfp->cdb_htp = cdbfp->cdb_htab + (((cdbfp->cdb_hval >> 8) % n) << 3);
346 else /* Walk over all entries. */
349 /* Force stepping in findnext. */
350 cdbfp->cdb_htp = cdbfp->cdb_htend = cdbp->cdb_mem;
356 /* See cdb_findinit. */
358 cdb_findnext(struct cdb_find *cdbfp)
361 struct cdb *cdbp = cdbfp->cdb_cdbp;
365 while(cdbfp->cdb_httodo) {
366 pos = cdb_unpack(cdbfp->cdb_htp + 4);
369 n = cdb_unpack(cdbfp->cdb_htp) == cdbfp->cdb_hval;
370 if ((cdbfp->cdb_htp += 8) >= cdbfp->cdb_htend)
371 cdbfp->cdb_htp = cdbfp->cdb_htab;
372 cdbfp->cdb_httodo -= 8;
374 if (pos > cdbp->cdb_fsize - 8) {
375 gpg_err_set_errno (EPROTO);
378 if (cdb_unpack(cdbp->cdb_mem + pos) == cdbfp->cdb_klen) {
379 if (cdbp->cdb_fsize - cdbfp->cdb_klen < pos + 8) {
380 gpg_err_set_errno (EPROTO);
383 if (memcmp(cdbfp->cdb_key,
384 cdbp->cdb_mem + pos + 8, cdbfp->cdb_klen) == 0) {
385 n = cdb_unpack(cdbp->cdb_mem + pos + 4);
386 pos += 8 + cdbfp->cdb_klen;
387 if (cdbp->cdb_fsize < n || cdbp->cdb_fsize - n < pos) {
388 gpg_err_set_errno (EPROTO);
391 cdbp->cdb_vpos = pos;
399 else /* Walk over all entries. */
403 while (cdbfp->cdb_htp >= cdbfp->cdb_htend)
405 if (cdbfp->cdb_hval > 255)
406 return 0; /* No more items. */
408 cdbfp->cdb_htp = cdbp->cdb_mem + cdbfp->cdb_hval * 8;
409 cdbfp->cdb_hval++; /* Advance for next round. */
410 pos = cdb_unpack (cdbfp->cdb_htp); /* Offset of table. */
411 n = cdb_unpack (cdbfp->cdb_htp + 4); /* Number of entries. */
412 cdbfp->cdb_httodo = n * 8; /* Size of table. */
413 if (n > (cdbp->cdb_fsize / 8)
414 || pos > cdbp->cdb_fsize
415 || cdbfp->cdb_httodo > cdbp->cdb_fsize - pos)
417 gpg_err_set_errno (EPROTO);
421 cdbfp->cdb_htab = cdbp->cdb_mem + pos;
422 cdbfp->cdb_htend = cdbfp->cdb_htab + cdbfp->cdb_httodo;
423 cdbfp->cdb_htp = cdbfp->cdb_htab;
426 pos = cdb_unpack (cdbfp->cdb_htp + 4); /* Offset of record. */
430 if (pos > cdbp->cdb_fsize - 8)
432 gpg_err_set_errno (EPROTO);
436 cdbp->cdb_kpos = pos + 8;
437 cdbp->cdb_klen = cdb_unpack(cdbp->cdb_mem + pos);
438 cdbp->cdb_vpos = pos + 8 + cdbp->cdb_klen;
439 cdbp->cdb_vlen = cdb_unpack(cdbp->cdb_mem + pos + 4);
440 n = 8 + cdbp->cdb_klen + cdbp->cdb_vlen;
441 if ( pos > cdbp->cdb_fsize || pos > cdbp->cdb_fsize - n)
443 gpg_err_set_errno (EPROTO);
446 return 1; /* Found. */
451 /* Read a chunk from file, ignoring interrupts (EINTR) */
453 cdb_bread(int fd, void *buf, int len)
457 do l = read(fd, buf, len);
458 while(l < 0 && errno == EINTR);
461 gpg_err_set_errno (EIO);
464 buf = (char*)buf + l;
470 /* Find a given key in cdb file, seek a file pointer to it's value and
471 place data length to *dlenp. */
473 cdb_seek(int fd, const void *key, unsigned klen, cdbi_t *dlenp)
475 cdbi_t htstart; /* hash table start position */
476 cdbi_t htsize; /* number of elements in a hash table */
477 cdbi_t httodo; /* hash table elements left to look */
478 cdbi_t hti; /* hash table index */
479 cdbi_t pos; /* position in a file */
480 cdbi_t hval; /* key's hash value */
481 unsigned char rbuf[64]; /* read buffer */
482 int needseek = 1; /* if we should seek to a hash slot */
484 hval = cdb_hash(key, klen);
485 pos = (hval & 0xff) << 3; /* position in TOC */
486 /* read the hash table parameters */
487 if (lseek(fd, pos, SEEK_SET) < 0 || cdb_bread(fd, rbuf, 8) < 0)
489 if ((htsize = cdb_unpack(rbuf + 4)) == 0)
491 hti = (hval >> 8) % htsize; /* start position in hash table */
493 htstart = cdb_unpack(rbuf);
496 if (needseek && lseek(fd, htstart + (hti << 3), SEEK_SET) < 0)
498 if (cdb_bread(fd, rbuf, 8) < 0)
500 if ((pos = cdb_unpack(rbuf + 4)) == 0) /* not found */
503 if (cdb_unpack(rbuf) != hval) /* hash value not matched */
505 else { /* hash value matched */
506 if (lseek(fd, pos, SEEK_SET) < 0 || cdb_bread(fd, rbuf, 8) < 0)
508 if (cdb_unpack(rbuf) == klen) { /* key length matches */
509 /* read the key from file and compare with wanted */
511 const char *k = (const char*)key;
513 *dlenp = cdb_unpack(rbuf + 4); /* save value length */
515 if (!l) /* the whole key read and matches, return */
517 c = l > sizeof(rbuf) ? sizeof(rbuf) : l;
518 if (cdb_bread(fd, rbuf, c) < 0)
520 if (memcmp(rbuf, k, c) != 0) /* no, it differs, stop here */
525 needseek = 1; /* we're looked to other place, should seek back */
529 if (++hti == htsize) {
537 cdb_unpack(const unsigned char buf[4])
540 n <<= 8; n |= buf[2];
541 n <<= 8; n |= buf[1];
542 n <<= 8; n |= buf[0];
546 /* Add record with key (KEY,KLEN) and value (VAL,VLEN) to a database.
547 Returns 0 on success or negative value on error. Note that this
548 routine does not checks if given key already exists, but cdb_find()
549 will not see second record with the same key. It is not possible
550 to continue building a database if cdb_make_add() returned an error
553 cdb_make_add(struct cdb_make *cdbmp,
554 const void *key, cdbi_t klen,
555 const void *val, cdbi_t vlen)
557 unsigned char rlen[8];
560 if (klen > 0xffffffff - (cdbmp->cdb_dpos + 8) ||
561 vlen > 0xffffffff - (cdbmp->cdb_dpos + klen + 8)) {
562 gpg_err_set_errno (ENOMEM);
565 hval = cdb_hash(key, klen);
566 rl = cdbmp->cdb_rec[hval&255];
567 if (!rl || rl->cnt >= sizeof(rl->rec)/sizeof(rl->rec[0])) {
568 rl = (struct cdb_rl*)malloc(sizeof(struct cdb_rl));
570 gpg_err_set_errno (ENOMEM);
574 rl->next = cdbmp->cdb_rec[hval&255];
575 cdbmp->cdb_rec[hval&255] = rl;
577 rl->rec[rl->cnt].hval = hval;
578 rl->rec[rl->cnt].rpos = cdbmp->cdb_dpos;
581 cdb_pack(klen, rlen);
582 cdb_pack(vlen, rlen + 4);
583 if (make_write(cdbmp, rlen, 8) < 0 ||
584 make_write(cdbmp, key, klen) < 0 ||
585 make_write(cdbmp, val, vlen) < 0)
591 cdb_make_put(struct cdb_make *cdbmp,
592 const void *key, cdbi_t klen,
593 const void *val, cdbi_t vlen,
596 unsigned char rlen[8];
597 cdbi_t hval = cdb_hash(key, klen);
602 case CDB_PUT_REPLACE:
605 c = make_find(cdbmp, key, klen, hval, &rl);
609 if (flags == CDB_PUT_INSERT) {
610 gpg_err_set_errno (EEXIST);
613 else if (flags == CDB_PUT_REPLACE) {
624 rl = cdbmp->cdb_rec[hval&255];
625 if (!rl || rl->cnt >= sizeof(rl->rec)/sizeof(rl->rec[0])) {
626 rl = (struct cdb_rl*)malloc(sizeof(struct cdb_rl));
628 gpg_err_set_errno (ENOMEM);
632 rl->next = cdbmp->cdb_rec[hval&255];
633 cdbmp->cdb_rec[hval&255] = rl;
640 gpg_err_set_errno (EINVAL);
644 if (klen > 0xffffffff - (cdbmp->cdb_dpos + 8) ||
645 vlen > 0xffffffff - (cdbmp->cdb_dpos + klen + 8)) {
646 gpg_err_set_errno (ENOMEM);
649 rl->rec[c].hval = hval;
650 rl->rec[c].rpos = cdbmp->cdb_dpos;
655 cdb_pack(klen, rlen);
656 cdb_pack(vlen, rlen + 4);
657 if (make_write(cdbmp, rlen, 8) < 0 ||
658 make_write(cdbmp, key, klen) < 0 ||
659 make_write(cdbmp, val, vlen) < 0)
666 match(int fd, cdbi_t pos, const char *key, cdbi_t klen)
668 unsigned char buf[64]; /*XXX cdb_buf may be used here instead */
669 if (lseek(fd, pos, SEEK_SET) < 0 || read(fd, buf, 8) != 8)
671 if (cdb_unpack(buf) != klen)
674 while(klen > sizeof(buf)) {
675 if (read(fd, buf, sizeof(buf)) != sizeof(buf))
677 if (memcmp(buf, key, sizeof(buf)) != 0)
683 if (read(fd, buf, klen) != klen)
685 if (memcmp(buf, key, klen) != 0)
693 make_find (struct cdb_make *cdbmp,
694 const void *key, cdbi_t klen, cdbi_t hval,
697 struct cdb_rl *rl = cdbmp->cdb_rec[hval&255];
701 for(i = rl->cnt - 1; i >= 0; --i) { /* search backward */
702 if (rl->rec[i].hval != hval)
704 /*XXX this explicit flush may be unnecessary having
705 * smarter match() that looks to cdb_buf too, but
706 * most of a time here spent in finding hash values
707 * (above), not keys */
708 if (cdbmp->cdb_bpos != cdbmp->cdb_buf) {
709 if (write(cdbmp->cdb_fd, cdbmp->cdb_buf,
710 cdbmp->cdb_bpos - cdbmp->cdb_buf) < 0)
712 cdbmp->cdb_bpos = cdbmp->cdb_buf;
715 r = match(cdbmp->cdb_fd, rl->rec[i].rpos, key, klen);
720 if (lseek(cdbmp->cdb_fd, cdbmp->cdb_dpos, SEEK_SET) < 0)
728 if (sought && lseek(cdbmp->cdb_fd, cdbmp->cdb_dpos, SEEK_SET) < 0)
734 cdb_make_exists(struct cdb_make *cdbmp,
735 const void *key, cdbi_t klen)
737 return make_find(cdbmp, key, klen, cdb_hash(key, klen), NULL);
742 cdb_pack(cdbi_t num, unsigned char buf[4])
744 buf[0] = num & 255; num >>= 8;
745 buf[1] = num & 255; num >>= 8;
751 /* Initializes structure to create a database. File FD should be
752 opened read-write and should be seekable. Returns 0 on success or
753 negative value on error. */
755 cdb_make_start(struct cdb_make *cdbmp, int fd)
757 memset (cdbmp, 0, sizeof *cdbmp);
759 cdbmp->cdb_dpos = 2048;
760 cdbmp->cdb_bpos = cdbmp->cdb_buf + 2048;
766 ewrite(int fd, const char *buf, int len)
769 int l = write(fd, buf, len);
770 if (l < 0 && errno != EINTR)
782 make_write(struct cdb_make *cdbmp, const char *ptr, cdbi_t len)
784 cdbi_t l = sizeof(cdbmp->cdb_buf) - (cdbmp->cdb_bpos - cdbmp->cdb_buf);
785 cdbmp->cdb_dpos += len;
787 memcpy(cdbmp->cdb_bpos, ptr, l);
788 if (ewrite(cdbmp->cdb_fd, cdbmp->cdb_buf, sizeof(cdbmp->cdb_buf)) < 0)
791 l = len / sizeof(cdbmp->cdb_buf);
793 l *= sizeof(cdbmp->cdb_buf);
794 if (ewrite(cdbmp->cdb_fd, ptr, l) < 0)
798 cdbmp->cdb_bpos = cdbmp->cdb_buf;
801 memcpy(cdbmp->cdb_bpos, ptr, len);
802 cdbmp->cdb_bpos += len;
808 cdb_make_finish_internal(struct cdb_make *cdbmp)
810 cdbi_t hcnt[256]; /* hash table counts */
811 cdbi_t hpos[256]; /* hash table positions */
812 struct cdb_rec *htab;
818 if (((0xffffffff - cdbmp->cdb_dpos) >> 3) < cdbmp->cdb_rcnt) {
819 gpg_err_set_errno (ENOMEM);
823 /* count htab sizes and reorder reclists */
825 for (t = 0; t < 256; ++t) {
826 struct cdb_rl *rlt = NULL;
828 rl = cdbmp->cdb_rec[t];
830 struct cdb_rl *rln = rl->next;
836 cdbmp->cdb_rec[t] = rlt;
837 if (hsize < (hcnt[t] = i << 1))
841 /* allocate memory to hold max htable */
842 htab = (struct cdb_rec*)malloc((hsize + 2) * sizeof(struct cdb_rec));
844 gpg_err_set_errno (ENOENT);
847 p = (unsigned char *)htab;
850 /* build hash tables */
851 for (t = 0; t < 256; ++t) {
853 hpos[t] = cdbmp->cdb_dpos;
854 if ((len = hcnt[t]) == 0)
856 for (i = 0; i < len; ++i)
857 htab[i].hval = htab[i].rpos = 0;
858 for (rl = cdbmp->cdb_rec[t]; rl; rl = rl->next)
859 for (i = 0; i < rl->cnt; ++i) {
860 hi = (rl->rec[i].hval >> 8) % len;
864 htab[hi] = rl->rec[i];
866 for (i = 0; i < len; ++i) {
867 cdb_pack(htab[i].hval, p + (i << 3));
868 cdb_pack(htab[i].rpos, p + (i << 3) + 4);
870 if (make_write(cdbmp, p, len << 3) < 0) {
876 if (cdbmp->cdb_bpos != cdbmp->cdb_buf &&
877 ewrite(cdbmp->cdb_fd, cdbmp->cdb_buf,
878 cdbmp->cdb_bpos - cdbmp->cdb_buf) != 0)
881 for (t = 0; t < 256; ++t) {
882 cdb_pack(hpos[t], p + (t << 3));
883 cdb_pack(hcnt[t], p + (t << 3) + 4);
885 if (lseek(cdbmp->cdb_fd, 0, 0) != 0 ||
886 ewrite(cdbmp->cdb_fd, p, 2048) != 0)
893 cdb_make_free(struct cdb_make *cdbmp)
896 for(t = 0; t < 256; ++t) {
897 struct cdb_rl *rl = cdbmp->cdb_rec[t];
899 struct cdb_rl *tm = rl;
908 /* Finalizes database file, constructing all needed indexes, and frees
909 memory structures. It does not close the file descriptor. Returns
910 0 on success or a negative value on error. */
912 cdb_make_finish(struct cdb_make *cdbmp)
914 int r = cdb_make_finish_internal(cdbmp);
915 cdb_make_free(cdbmp);
921 cdb_hash(const void *buf, cdbi_t len)
923 register const unsigned char *p = (const unsigned char *)buf;
924 register const unsigned char *end = p + len;
925 register cdbi_t hash = 5381; /* start value */
927 hash = (hash + (hash << 5)) ^ *p++;