debian/rules: Use `git' potty wrapper.
[qmail] / cdb_seek.c
1 #include <sys/types.h>
2 #include <errno.h>
3 extern int errno;
4 #include "cdb.h"
5
6 #ifndef SEEK_SET
7 #define SEEK_SET 0
8 #endif
9
10 int cdb_bread(fd,buf,len)
11 int fd;
12 char *buf;
13 int len;
14 {
15 int r;
16 while (len > 0) {
17 do
18 r = read(fd,buf,len);
19 while ((r == -1) && (errno == EINTR));
20 if (r == -1) return -1;
21 if (r == 0) { errno = EIO; return -1; }
22 buf += r;
23 len -= r;
24 }
25 return 0;
26 }
27
28 static int match(fd,key,len)
29 int fd;
30 char *key;
31 unsigned int len;
32 {
33 char buf[32];
34 int n;
35 int i;
36
37 while (len > 0) {
38 n = sizeof(buf);
39 if (n > len) n = len;
40 if (cdb_bread(fd,buf,n) == -1) return -1;
41 for (i = 0;i < n;++i) if (buf[i] != key[i]) return 0;
42 key += n;
43 len -= n;
44 }
45 return 1;
46 }
47
48 int cdb_seek(fd,key,len,dlen)
49 int fd;
50 char *key;
51 unsigned int len;
52 uint32 *dlen;
53 {
54 char packbuf[8];
55 uint32 pos;
56 uint32 h;
57 uint32 lenhash;
58 uint32 h2;
59 uint32 loop;
60 uint32 poskd;
61
62 h = cdb_hash(key,len);
63
64 pos = 8 * (h & 255);
65 if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1;
66
67 if (cdb_bread(fd,packbuf,8) == -1) return -1;
68
69 pos = cdb_unpack(packbuf);
70 lenhash = cdb_unpack(packbuf + 4);
71
72 if (!lenhash) return 0;
73 h2 = (h >> 8) % lenhash;
74
75 for (loop = 0;loop < lenhash;++loop) {
76 if (lseek(fd,(off_t) (pos + 8 * h2),SEEK_SET) == -1) return -1;
77 if (cdb_bread(fd,packbuf,8) == -1) return -1;
78 poskd = cdb_unpack(packbuf + 4);
79 if (!poskd) return 0;
80 if (cdb_unpack(packbuf) == h) {
81 if (lseek(fd,(off_t) poskd,SEEK_SET) == -1) return -1;
82 if (cdb_bread(fd,packbuf,8) == -1) return -1;
83 if (cdb_unpack(packbuf) == len)
84 switch(match(fd,key,len)) {
85 case -1:
86 return -1;
87 case 1:
88 *dlen = cdb_unpack(packbuf + 4);
89 return 1;
90 }
91 }
92 if (++h2 == lenhash) h2 = 0;
93 }
94 return 0;
95 }