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 
cdb_bread(fd,buf,len)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 
match(fd,key,len)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 
cdb_seek(fd,key,len,dlen)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 }
96