s/qmail  3.3.23
Next generation secure email transport
cdb_make.c
Go to the documentation of this file.
1 /* Public domain. */
2 
3 #include "readwrite.h"
4 #include "seek.h"
5 #include "error.h"
6 #include "alloc.h"
7 #include "cdb.h"
8 #include "cdb_make.h"
9 
10 int cdb_make_start(struct cdb_make *c,int fd)
11 {
12  c->head = 0;
13  c->split = 0;
14  c->hash = 0;
15  c->numentries = 0;
16  c->fd = fd;
17  c->pos = sizeof(c->final);
18  buffer_init(&c->b,write,fd,c->bspace,sizeof(c->bspace));
19  return seek_set(fd,c->pos);
20 }
21 
22 static int posplus(struct cdb_make *c,uint32 len)
23 {
24  uint32 newpos = c->pos + len;
25  if (newpos < len) { errno = error_nomem; return -1; }
26  c->pos = newpos;
27  return 0;
28 }
29 
30 int cdb_make_addend(struct cdb_make *c,unsigned int keylen,unsigned int datalen,uint32 h)
31 {
32  struct cdb_hplist *head;
33 
34  head = c->head;
35  if (!head || (head->num >= CDB_HPLIST)) {
36  head = (struct cdb_hplist *) alloc(sizeof(struct cdb_hplist));
37  if (!head) return -1;
38  head->num = 0;
39  head->next = c->head;
40  c->head = head;
41  }
42  head->hp[head->num].h = h;
43  head->hp[head->num].p = c->pos;
44  ++head->num;
45  ++c->numentries;
46  if (posplus(c,8) == -1) return -1;
47  if (posplus(c,keylen) == -1) return -1;
48  if (posplus(c,datalen) == -1) return -1;
49  return 0;
50 }
51 
52 int cdb_make_addbegin(struct cdb_make *c,unsigned int keylen,unsigned int datalen)
53 {
54  char buf[8];
55 
56  if (keylen > 0xffffffff) { errno = error_nomem; return -1; }
57  if (datalen > 0xffffffff) { errno = error_nomem; return -1; }
58 
59  uint32_pack(buf,keylen);
60  uint32_pack(buf + 4,datalen);
61  if (buffer_putalign(&c->b,buf,8) == -1) return -1;
62  return 0;
63 }
64 
65 int cdb_make_add(struct cdb_make *c,char *key,unsigned int keylen,char *data,unsigned int datalen)
66 {
67  if (cdb_make_addbegin(c,keylen,datalen) == -1) return -1;
68  if (buffer_putalign(&c->b,key,keylen) == -1) return -1;
69  if (buffer_putalign(&c->b,data,datalen) == -1) return -1;
70  return cdb_make_addend(c,keylen,datalen,cdb_hash(key,keylen));
71 }
72 
73 int cdb_make_finish(struct cdb_make *c)
74 {
75  char buf[8];
76  int i;
77  uint32 len;
78  uint32 u;
79  uint32 memsize;
80  uint32 count;
81  uint32 where;
82  struct cdb_hplist *x;
83  struct cdb_hp *hp;
84 
85  for (i = 0; i < 256; ++i)
86  c->count[i] = 0;
87 
88  for (x = c->head; x; x = x->next) {
89  i = x->num;
90  while (i--)
91  ++c->count[255 & x->hp[i].h];
92  }
93 
94  memsize = 1;
95 
96  for (i = 0; i < 256; ++i) {
97  u = c->count[i] * 2;
98  if (u > memsize)
99  memsize = u;
100  }
101 
102  memsize += c->numentries; /* no overflow possible up to now */
103  u = (uint32) 0 - (uint32) 1;
104  u /= sizeof(struct cdb_hp);
105  if (memsize > u) { errno = error_nomem; return -1; }
106 
107  c->split = (struct cdb_hp *) alloc(memsize * sizeof(struct cdb_hp));
108  if (!c->split) return -1;
109 
110  c->hash = c->split + c->numentries;
111 
112  u = 0;
113 
114  for (i = 0; i < 256; ++i) {
115  u += c->count[i]; /* bounded by numentries, so no overflow */
116  c->start[i] = u;
117  }
118 
119  for (x = c->head; x; x = x->next) {
120  i = x->num;
121  while (i--)
122  c->split[--c->start[255 & x->hp[i].h]] = x->hp[i];
123  }
124 
125  for (i = 0; i < 256; ++i) {
126  count = c->count[i];
127 
128  len = count + count; /* no overflow possible */
129  uint32_pack(c->final + 8 * i,c->pos);
130  uint32_pack(c->final + 8 * i + 4,len);
131 
132  for (u = 0; u < len; ++u)
133  c->hash[u].h = c->hash[u].p = 0;
134 
135  hp = c->split + c->start[i];
136 
137  for (u = 0; u < count; ++u) {
138  where = (hp->h >> 8) % len;
139  while (c->hash[where].p)
140  if (++where == len)
141  where = 0;
142  c->hash[where] = *hp++;
143  }
144 
145  for (u = 0; u < len; ++u) {
146  uint32_pack(buf,c->hash[u].h);
147  uint32_pack(buf + 4,c->hash[u].p);
148  if (buffer_putalign(&c->b,buf,8) == -1) return -1;
149  if (posplus(c,8) == -1) return -1;
150  }
151  }
152 
153  if (buffer_flush(&c->b) == -1) return -1;
154  if (seek_begin(c->fd) == -1) return -1;
155  return buffer_putflush(&c->b,c->final,sizeof(c->final));
156 }
uint32 count[256]
Definition: cdb_make.h:22
struct cdb_hp * split
Definition: cdb_make.h:25
struct cdb_hplist * next
Definition: cdb_make.h:15
char * alloc(unsigned int n)
Definition: alloc.c:16
struct cdb_hp hp[CDB_HPLIST]
Definition: cdb_make.h:14
uint32 start[256]
Definition: cdb_make.h:23
int fd
Definition: idedit.c:16
int cdb_make_start(struct cdb_make *c, int fd)
Definition: cdb_make.c:10
int seek_set()
void c(char *home, char *subdir, char *file, int uid, int gid, int mode)
Definition: install.c:57
int cdb_make_add(struct cdb_make *c, char *key, unsigned int keylen, char *data, unsigned int datalen)
Definition: cdb_make.c:65
struct cdb_hplist * head
Definition: cdb_make.h:24
int fd
Definition: cdb_make.h:30
int cdb_make_addbegin(struct cdb_make *c, unsigned int keylen, unsigned int datalen)
Definition: cdb_make.c:52
int error_nomem
Definition: error.c:13
stralloc key
Definition: fastforward.c:119
struct cdb_hp * hash
Definition: cdb_make.h:26
char final[2048]
Definition: cdb_make.h:21
unsigned len
Definition: matchup.c:36
unsigned i
Definition: matchup.c:36
buffer b
Definition: cdb_make.h:28
#define CDB_HPLIST
Definition: cdb_make.h:9
uint32 numentries
Definition: cdb_make.h:27
int errno
#define seek_begin(fd)
Definition: seek.h:13
unsigned x
Definition: matchup.c:36
uint32 p
Definition: cdb_make.h:11
int num
Definition: cdb_make.h:16
int cdb_make_finish(struct cdb_make *c)
Definition: cdb_make.c:73
int buffer_putflush(buffer *, char *, unsigned int)
stralloc data
Definition: fastforward.c:121
int cdb_make_addend(struct cdb_make *c, unsigned int keylen, unsigned int datalen, uint32 h)
Definition: cdb_make.c:30
void h(char *home, int uid, int gid, int mode)
Definition: install.c:15
uint32 h
Definition: cdb_make.h:11
char bspace[8192]
Definition: cdb_make.h:20
unsigned char * buf
Definition: dns.c:41
void buffer_init(buffer *, int(*)(), int, char *, unsigned int)
uint32 cdb_hash(char *, unsigned int)
Definition: cdb_hash.c:11
uint32 pos
Definition: cdb_make.h:29
unsigned u
Definition: matchup.c:36
int buffer_flush(buffer *)