cdb_seek.c
changeset 0 068428edee47
equal deleted inserted replaced
-1:000000000000 0:068428edee47
       
     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 }