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 allow enumeration of all of them.
300 cdb_findinit() initializes search structure pointed to by cdbfp.
301 It will return negative value on error or 0 on success.
302 cdb_findnext() attempts to find next matching key, setting value
303 position and length in cdbfp structure. It will return positive
304 value if given key was found, 0 if there is no more such key(s), or
305 negative 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 cdb_find().
311 Setting KEY to NULL will start a sequential search through the
315 cdb_findinit(struct cdb_find *cdbfp, struct cdb *cdbp,
316 const void *key, cdbi_t klen)
320 cdbfp->cdb_cdbp = cdbp;
321 cdbfp->cdb_key = key;
322 cdbfp->cdb_klen = klen;
323 cdbfp->cdb_hval = key? cdb_hash(key, klen) : 0;
327 cdbfp->cdb_htp = cdbp->cdb_mem + ((cdbfp->cdb_hval << 3) & 2047);
328 n = cdb_unpack(cdbfp->cdb_htp + 4);
329 cdbfp->cdb_httodo = n << 3; /* Set to size of hash table. */
331 return 0; /* The hash table is empry. */
332 pos = cdb_unpack(cdbfp->cdb_htp);
333 if (n > (cdbp->cdb_fsize >> 3)
334 || pos > cdbp->cdb_fsize
335 || cdbfp->cdb_httodo > cdbp->cdb_fsize - pos)
337 gpg_err_set_errno (EPROTO);
341 cdbfp->cdb_htab = cdbp->cdb_mem + pos;
342 cdbfp->cdb_htend = cdbfp->cdb_htab + cdbfp->cdb_httodo;
343 cdbfp->cdb_htp = cdbfp->cdb_htab + (((cdbfp->cdb_hval >> 8) % n) << 3);
345 else /* Walk over all entries. */
348 /* Force stepping in findnext. */
349 cdbfp->cdb_htp = cdbfp->cdb_htend = cdbp->cdb_mem;
355 /* See cdb_findinit. */
357 cdb_findnext(struct cdb_find *cdbfp)
360 struct cdb *cdbp = cdbfp->cdb_cdbp;
364 while(cdbfp->cdb_httodo) {
365 pos = cdb_unpack(cdbfp->cdb_htp + 4);
368 n = cdb_unpack(cdbfp->cdb_htp) == cdbfp->cdb_hval;
369 if ((cdbfp->cdb_htp += 8) >= cdbfp->cdb_htend)
370 cdbfp->cdb_htp = cdbfp->cdb_htab;
371 cdbfp->cdb_httodo -= 8;
373 if (pos > cdbp->cdb_fsize - 8) {
374 gpg_err_set_errno (EPROTO);
377 if (cdb_unpack(cdbp->cdb_mem + pos) == cdbfp->cdb_klen) {
378 if (cdbp->cdb_fsize - cdbfp->cdb_klen < pos + 8) {
379 gpg_err_set_errno (EPROTO);
382 if (memcmp(cdbfp->cdb_key,
383 cdbp->cdb_mem + pos + 8, cdbfp->cdb_klen) == 0) {
384 n = cdb_unpack(cdbp->cdb_mem + pos + 4);
385 pos += 8 + cdbfp->cdb_klen;
386 if (cdbp->cdb_fsize < n || cdbp->cdb_fsize - n < pos) {
387 gpg_err_set_errno (EPROTO);
390 cdbp->cdb_vpos = pos;
398 else /* Walk over all entries. */
402 while (cdbfp->cdb_htp >= cdbfp->cdb_htend)
404 if (cdbfp->cdb_hval > 255)
405 return 0; /* No more items. */
407 cdbfp->cdb_htp = cdbp->cdb_mem + cdbfp->cdb_hval * 8;
408 cdbfp->cdb_hval++; /* Advance for next round. */
409 pos = cdb_unpack (cdbfp->cdb_htp); /* Offset of table. */
410 n = cdb_unpack (cdbfp->cdb_htp + 4); /* Number of entries. */
411 cdbfp->cdb_httodo = n * 8; /* Size of table. */
412 if (n > (cdbp->cdb_fsize / 8)
413 || pos > cdbp->cdb_fsize
414 || cdbfp->cdb_httodo > cdbp->cdb_fsize - pos)
416 gpg_err_set_errno (EPROTO);
420 cdbfp->cdb_htab = cdbp->cdb_mem + pos;
421 cdbfp->cdb_htend = cdbfp->cdb_htab + cdbfp->cdb_httodo;
422 cdbfp->cdb_htp = cdbfp->cdb_htab;
425 pos = cdb_unpack (cdbfp->cdb_htp + 4); /* Offset of record. */
429 if (pos > cdbp->cdb_fsize - 8)
431 gpg_err_set_errno (EPROTO);
435 cdbp->cdb_kpos = pos + 8;
436 cdbp->cdb_klen = cdb_unpack(cdbp->cdb_mem + pos);
437 cdbp->cdb_vpos = pos + 8 + cdbp->cdb_klen;
438 cdbp->cdb_vlen = cdb_unpack(cdbp->cdb_mem + pos + 4);
439 n = 8 + cdbp->cdb_klen + cdbp->cdb_vlen;
440 if ( pos > cdbp->cdb_fsize || pos > cdbp->cdb_fsize - n)
442 gpg_err_set_errno (EPROTO);
445 return 1; /* Found. */
450 /* Read a chunk from file, ignoring interrupts (EINTR) */
452 cdb_bread(int fd, void *buf, int len)
456 do l = read(fd, buf, len);
457 while(l < 0 && errno == EINTR);
460 gpg_err_set_errno (EIO);
463 buf = (char*)buf + l;
469 /* Find a given key in cdb file, seek a file pointer to it's value and
470 place data length to *dlenp. */
472 cdb_seek(int fd, const void *key, unsigned klen, cdbi_t *dlenp)
474 cdbi_t htstart; /* hash table start position */
475 cdbi_t htsize; /* number of elements in a hash table */
476 cdbi_t httodo; /* hash table elements left to look */
477 cdbi_t hti; /* hash table index */
478 cdbi_t pos; /* position in a file */
479 cdbi_t hval; /* key's hash value */
480 unsigned char rbuf[64]; /* read buffer */
481 int needseek = 1; /* if we should seek to a hash slot */
483 hval = cdb_hash(key, klen);
484 pos = (hval & 0xff) << 3; /* position in TOC */
485 /* read the hash table parameters */
486 if (lseek(fd, pos, SEEK_SET) < 0 || cdb_bread(fd, rbuf, 8) < 0)
488 if ((htsize = cdb_unpack(rbuf + 4)) == 0)
490 hti = (hval >> 8) % htsize; /* start position in hash table */
492 htstart = cdb_unpack(rbuf);
495 if (needseek && lseek(fd, htstart + (hti << 3), SEEK_SET) < 0)
497 if (cdb_bread(fd, rbuf, 8) < 0)
499 if ((pos = cdb_unpack(rbuf + 4)) == 0) /* not found */
502 if (cdb_unpack(rbuf) != hval) /* hash value not matched */
504 else { /* hash value matched */
505 if (lseek(fd, pos, SEEK_SET) < 0 || cdb_bread(fd, rbuf, 8) < 0)
507 if (cdb_unpack(rbuf) == klen) { /* key length matches */
508 /* read the key from file and compare with wanted */
510 const char *k = (const char*)key;
512 *dlenp = cdb_unpack(rbuf + 4); /* save value length */
514 if (!l) /* the whole key read and matches, return */
516 c = l > sizeof(rbuf) ? sizeof(rbuf) : l;
517 if (cdb_bread(fd, rbuf, c) < 0)
519 if (memcmp(rbuf, k, c) != 0) /* no, it differs, stop here */
524 needseek = 1; /* we're looked to other place, should seek back */
528 if (++hti == htsize) {
536 cdb_unpack(const unsigned char buf[4])
539 n <<= 8; n |= buf[2];
540 n <<= 8; n |= buf[1];
541 n <<= 8; n |= buf[0];
545 /* Add record with key (KEY,KLEN) and value (VAL,VLEN) to a database.
546 Returns 0 on success or negative value on error. Note that this
547 routine does not checks if given key already exists, but cdb_find()
548 will not see second record with the same key. It is not possible
549 to continue building a database if cdb_make_add() returned an error
552 cdb_make_add(struct cdb_make *cdbmp,
553 const void *key, cdbi_t klen,
554 const void *val, cdbi_t vlen)
556 unsigned char rlen[8];
559 if (klen > 0xffffffff - (cdbmp->cdb_dpos + 8) ||
560 vlen > 0xffffffff - (cdbmp->cdb_dpos + klen + 8)) {
561 gpg_err_set_errno (ENOMEM);
564 hval = cdb_hash(key, klen);
565 rl = cdbmp->cdb_rec[hval&255];
566 if (!rl || rl->cnt >= sizeof(rl->rec)/sizeof(rl->rec[0])) {
567 rl = (struct cdb_rl*)malloc(sizeof(struct cdb_rl));
569 gpg_err_set_errno (ENOMEM);
573 rl->next = cdbmp->cdb_rec[hval&255];
574 cdbmp->cdb_rec[hval&255] = rl;
576 rl->rec[rl->cnt].hval = hval;
577 rl->rec[rl->cnt].rpos = cdbmp->cdb_dpos;
580 cdb_pack(klen, rlen);
581 cdb_pack(vlen, rlen + 4);
582 if (make_write(cdbmp, rlen, 8) < 0 ||
583 make_write(cdbmp, key, klen) < 0 ||
584 make_write(cdbmp, val, vlen) < 0)
590 cdb_make_put(struct cdb_make *cdbmp,
591 const void *key, cdbi_t klen,
592 const void *val, cdbi_t vlen,
595 unsigned char rlen[8];
596 cdbi_t hval = cdb_hash(key, klen);
601 case CDB_PUT_REPLACE:
604 c = make_find(cdbmp, key, klen, hval, &rl);
608 if (flags == CDB_PUT_INSERT) {
609 gpg_err_set_errno (EEXIST);
612 else if (flags == CDB_PUT_REPLACE) {
623 rl = cdbmp->cdb_rec[hval&255];
624 if (!rl || rl->cnt >= sizeof(rl->rec)/sizeof(rl->rec[0])) {
625 rl = (struct cdb_rl*)malloc(sizeof(struct cdb_rl));
627 gpg_err_set_errno (ENOMEM);
631 rl->next = cdbmp->cdb_rec[hval&255];
632 cdbmp->cdb_rec[hval&255] = rl;
639 gpg_err_set_errno (EINVAL);
643 if (klen > 0xffffffff - (cdbmp->cdb_dpos + 8) ||
644 vlen > 0xffffffff - (cdbmp->cdb_dpos + klen + 8)) {
645 gpg_err_set_errno (ENOMEM);
648 rl->rec[c].hval = hval;
649 rl->rec[c].rpos = cdbmp->cdb_dpos;
654 cdb_pack(klen, rlen);
655 cdb_pack(vlen, rlen + 4);
656 if (make_write(cdbmp, rlen, 8) < 0 ||
657 make_write(cdbmp, key, klen) < 0 ||
658 make_write(cdbmp, val, vlen) < 0)
665 match(int fd, cdbi_t pos, const char *key, cdbi_t klen)
667 unsigned char buf[64]; /*XXX cdb_buf may be used here instead */
668 if (lseek(fd, pos, SEEK_SET) < 0 || read(fd, buf, 8) != 8)
670 if (cdb_unpack(buf) != klen)
673 while(klen > sizeof(buf)) {
674 if (read(fd, buf, sizeof(buf)) != sizeof(buf))
676 if (memcmp(buf, key, sizeof(buf)) != 0)
682 if (read(fd, buf, klen) != klen)
684 if (memcmp(buf, key, klen) != 0)
692 make_find (struct cdb_make *cdbmp,
693 const void *key, cdbi_t klen, cdbi_t hval,
696 struct cdb_rl *rl = cdbmp->cdb_rec[hval&255];
700 for(i = rl->cnt - 1; i >= 0; --i) { /* search backward */
701 if (rl->rec[i].hval != hval)
703 /*XXX this explicit flush may be unnecessary having
704 * smarter match() that looks to cdb_buf too, but
705 * most of a time here spent in finding hash values
706 * (above), not keys */
707 if (cdbmp->cdb_bpos != cdbmp->cdb_buf) {
708 if (write(cdbmp->cdb_fd, cdbmp->cdb_buf,
709 cdbmp->cdb_bpos - cdbmp->cdb_buf) < 0)
711 cdbmp->cdb_bpos = cdbmp->cdb_buf;
714 r = match(cdbmp->cdb_fd, rl->rec[i].rpos, key, klen);
719 if (lseek(cdbmp->cdb_fd, cdbmp->cdb_dpos, SEEK_SET) < 0)
727 if (sought && lseek(cdbmp->cdb_fd, cdbmp->cdb_dpos, SEEK_SET) < 0)
733 cdb_make_exists(struct cdb_make *cdbmp,
734 const void *key, cdbi_t klen)
736 return make_find(cdbmp, key, klen, cdb_hash(key, klen), NULL);
741 cdb_pack(cdbi_t num, unsigned char buf[4])
743 buf[0] = num & 255; num >>= 8;
744 buf[1] = num & 255; num >>= 8;
750 /* Initializes structure to create a database. File FD should be
751 opened read-write and should be seekable. Returns 0 on success or
752 negative value on error. */
754 cdb_make_start(struct cdb_make *cdbmp, int fd)
756 memset (cdbmp, 0, sizeof *cdbmp);
758 cdbmp->cdb_dpos = 2048;
759 cdbmp->cdb_bpos = cdbmp->cdb_buf + 2048;
765 ewrite(int fd, const char *buf, int len)
768 int l = write(fd, buf, len);
769 if (l < 0 && errno != EINTR)
781 make_write(struct cdb_make *cdbmp, const char *ptr, cdbi_t len)
783 cdbi_t l = sizeof(cdbmp->cdb_buf) - (cdbmp->cdb_bpos - cdbmp->cdb_buf);
784 cdbmp->cdb_dpos += len;
786 memcpy(cdbmp->cdb_bpos, ptr, l);
787 if (ewrite(cdbmp->cdb_fd, cdbmp->cdb_buf, sizeof(cdbmp->cdb_buf)) < 0)
790 l = len / sizeof(cdbmp->cdb_buf);
792 l *= sizeof(cdbmp->cdb_buf);
793 if (ewrite(cdbmp->cdb_fd, ptr, l) < 0)
797 cdbmp->cdb_bpos = cdbmp->cdb_buf;
800 memcpy(cdbmp->cdb_bpos, ptr, len);
801 cdbmp->cdb_bpos += len;
807 cdb_make_finish_internal(struct cdb_make *cdbmp)
809 cdbi_t hcnt[256]; /* hash table counts */
810 cdbi_t hpos[256]; /* hash table positions */
811 struct cdb_rec *htab;
817 if (((0xffffffff - cdbmp->cdb_dpos) >> 3) < cdbmp->cdb_rcnt) {
818 gpg_err_set_errno (ENOMEM);
822 /* count htab sizes and reorder reclists */
824 for (t = 0; t < 256; ++t) {
825 struct cdb_rl *rlt = NULL;
827 rl = cdbmp->cdb_rec[t];
829 struct cdb_rl *rln = rl->next;
835 cdbmp->cdb_rec[t] = rlt;
836 if (hsize < (hcnt[t] = i << 1))
840 /* allocate memory to hold max htable */
841 htab = (struct cdb_rec*)malloc((hsize + 2) * sizeof(struct cdb_rec));
843 gpg_err_set_errno (ENOENT);
846 p = (unsigned char *)htab;
849 /* build hash tables */
850 for (t = 0; t < 256; ++t) {
852 hpos[t] = cdbmp->cdb_dpos;
853 if ((len = hcnt[t]) == 0)
855 for (i = 0; i < len; ++i)
856 htab[i].hval = htab[i].rpos = 0;
857 for (rl = cdbmp->cdb_rec[t]; rl; rl = rl->next)
858 for (i = 0; i < rl->cnt; ++i) {
859 hi = (rl->rec[i].hval >> 8) % len;
863 htab[hi] = rl->rec[i];
865 for (i = 0; i < len; ++i) {
866 cdb_pack(htab[i].hval, p + (i << 3));
867 cdb_pack(htab[i].rpos, p + (i << 3) + 4);
869 if (make_write(cdbmp, p, len << 3) < 0) {
875 if (cdbmp->cdb_bpos != cdbmp->cdb_buf &&
876 ewrite(cdbmp->cdb_fd, cdbmp->cdb_buf,
877 cdbmp->cdb_bpos - cdbmp->cdb_buf) != 0)
880 for (t = 0; t < 256; ++t) {
881 cdb_pack(hpos[t], p + (t << 3));
882 cdb_pack(hcnt[t], p + (t << 3) + 4);
884 if (lseek(cdbmp->cdb_fd, 0, 0) != 0 ||
885 ewrite(cdbmp->cdb_fd, p, 2048) != 0)
892 cdb_make_free(struct cdb_make *cdbmp)
895 for(t = 0; t < 256; ++t) {
896 struct cdb_rl *rl = cdbmp->cdb_rec[t];
898 struct cdb_rl *tm = rl;
907 /* Finalizes database file, constructing all needed indexes, and frees
908 memory structures. It does not close the file descriptor. Returns
909 0 on success or a negative value on error. */
911 cdb_make_finish(struct cdb_make *cdbmp)
913 int r = cdb_make_finish_internal(cdbmp);
914 cdb_make_free(cdbmp);
920 cdb_hash(const void *buf, cdbi_t len)
922 register const unsigned char *p = (const unsigned char *)buf;
923 register const unsigned char *end = p + len;
924 register cdbi_t hash = 5381; /* start value */
926 hash = (hash + (hash << 5)) ^ *p++;