Commit | Line | Data |
---|---|---|
2117e02e MW |
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 | } |