9 int cdb_make_start(struct cdb_make
*c
,int fd
)
16 c
->pos
= sizeof c
->final
;
17 buffer_init(&c
->b
,buffer_unixwrite
,fd
,c
->bspace
,sizeof c
->bspace
);
18 return seek_set(fd
,c
->pos
);
21 static int posplus(struct cdb_make
*c
,uint32 len
)
23 uint32 newpos
= c
->pos
+ len
;
24 if (newpos
< len
) { errno
= error_nomem
; return -1; }
29 int cdb_make_addend(struct cdb_make
*c
,unsigned int keylen
,unsigned int datalen
,uint32 h
)
31 struct cdb_hplist
*head
;
34 if (!head
|| (head
->num
>= CDB_HPLIST
)) {
35 head
= (struct cdb_hplist
*) alloc(sizeof(struct cdb_hplist
));
41 head
->hp
[head
->num
].h
= h
;
42 head
->hp
[head
->num
].p
= c
->pos
;
45 if (posplus(c
,8) == -1) return -1;
46 if (posplus(c
,keylen
) == -1) return -1;
47 if (posplus(c
,datalen
) == -1) return -1;
51 int cdb_make_addbegin(struct cdb_make
*c
,unsigned int keylen
,unsigned int datalen
)
55 if (keylen
> 0xffffffff) { errno
= error_nomem
; return -1; }
56 if (datalen
> 0xffffffff) { errno
= error_nomem
; return -1; }
58 uint32_pack(buf
,keylen
);
59 uint32_pack(buf
+ 4,datalen
);
60 if (buffer_putalign(&c
->b
,buf
,8) == -1) return -1;
64 int cdb_make_add(struct cdb_make
*c
,const char *key
,unsigned int keylen
,const char *data
,unsigned int datalen
)
66 if (cdb_make_addbegin(c
,keylen
,datalen
) == -1) return -1;
67 if (buffer_putalign(&c
->b
,key
,keylen
) == -1) return -1;
68 if (buffer_putalign(&c
->b
,data
,datalen
) == -1) return -1;
69 return cdb_make_addend(c
,keylen
,datalen
,cdb_hash(key
,keylen
));
72 int cdb_make_finish(struct cdb_make
*c
)
84 for (i
= 0;i
< 256;++i
)
87 for (x
= c
->head
;x
;x
= x
->next
) {
90 ++c
->count
[255 & x
->hp
[i
].h
];
94 for (i
= 0;i
< 256;++i
) {
100 memsize
+= c
->numentries
; /* no overflow possible up to now */
101 u
= (uint32
) 0 - (uint32
) 1;
102 u
/= sizeof(struct cdb_hp
);
103 if (memsize
> u
) { errno
= error_nomem
; return -1; }
105 c
->split
= (struct cdb_hp
*) alloc(memsize
* sizeof(struct cdb_hp
));
106 if (!c
->split
) return -1;
108 c
->hash
= c
->split
+ c
->numentries
;
111 for (i
= 0;i
< 256;++i
) {
112 u
+= c
->count
[i
]; /* bounded by numentries, so no overflow */
116 for (x
= c
->head
;x
;x
= x
->next
) {
119 c
->split
[--c
->start
[255 & x
->hp
[i
].h
]] = x
->hp
[i
];
122 for (i
= 0;i
< 256;++i
) {
125 len
= count
+ count
; /* no overflow possible */
126 uint32_pack(c
->final
+ 8 * i
,c
->pos
);
127 uint32_pack(c
->final
+ 8 * i
+ 4,len
);
129 for (u
= 0;u
< len
;++u
)
130 c
->hash
[u
].h
= c
->hash
[u
].p
= 0;
132 hp
= c
->split
+ c
->start
[i
];
133 for (u
= 0;u
< count
;++u
) {
134 where
= (hp
->h
>> 8) % len
;
135 while (c
->hash
[where
].p
)
138 c
->hash
[where
] = *hp
++;
141 for (u
= 0;u
< len
;++u
) {
142 uint32_pack(buf
,c
->hash
[u
].h
);
143 uint32_pack(buf
+ 4,c
->hash
[u
].p
);
144 if (buffer_putalign(&c
->b
,buf
,8) == -1) return -1;
145 if (posplus(c
,8) == -1) return -1;
149 if (buffer_flush(&c
->b
) == -1) return -1;
150 if (seek_begin(c
->fd
) == -1) return -1;
151 return buffer_putflush(&c
->b
,c
->final
,sizeof c
->final
);