// TODO: use mmap instead of read.. much faster! SDB_VISIBLE Sdb* sdb_new (const char *dir, int lock) { Sdb* s; if (lock && !sdb_lock (sdb_lockfile (dir))) return NULL; s = malloc (sizeof (Sdb)); if (dir && *dir) { s->dir = strdup (dir); s->fd = open (dir, O_RDONLY|O_BINARY); // if (s->fd == -1) // must fail if we cant open for write in sync } else { s->dir = NULL; s->fd = -1; } s->fdump = -1; s->ndump = NULL; s->ns = ls_new (); s->ht = ht_new (); s->lock = lock; s->expire = 0LL; //s->ht->list->free = (SdbListFree)sdb_kv_free; // if open fails ignore cdb_init (&s->db, s->fd); cdb_findstart (&s->db); return s; }
static void __cdb_findstart(Dictionary *dic) { #if defined(USE_TINYCDB) dic->first = 1; #else cdb_findstart(&dic->cdb); #endif }
static int doit(struct cdb *c,uint32 *kpos) { char buf[8]; uint32 eod,klen; if (cdb_read(c,buf,4,0)) return -1; uint32_unpack(buf,&eod); if (eod<8 || eod-8<*kpos) return 0; c->kpos=*kpos+8; if (c->kpos<*kpos) return -1; /* wraparound */ cdb_findstart(c); c->hslots=1; if (cdb_read(c,buf,8,*kpos) == -1) return -1; uint32_unpack(buf,&klen); uint32_unpack(buf+4,&c->dlen); c->dpos=c->kpos+klen; *kpos+=8+klen+c->dlen; return 1; }
SDB_VISIBLE int sdb_exists (Sdb* s, const char *key) { char ch; SdbKv *kv; int klen = strlen (key); ut32 pos, hash = sdb_hash (key, klen); kv = (SdbKv*)ht_lookup (s->ht, hash); if (kv) return (*kv->value)? 1: 0; if (s->fd == -1) return 0; cdb_findstart (&s->db); if (cdb_findnext (&s->db, hash, key, klen)) { pos = cdb_datapos (&s->db); cdb_read (&s->db, &ch, 1, pos); return ch != 0; } return 0; }
void cdb_init(struct cdb *c,int fd) { struct stat st; char *x; cdb_free(c); cdb_findstart(c); c->fd = fd; if (fstat(fd,&st) == 0) { x = mmap(0,st.st_size,PROT_READ,MAP_SHARED,fd,0); if (x + 1) { c->size = st.st_size; c->map = x; } } }
SDB_VISIBLE char *sdb_get (Sdb* s, const char *key, ut32 *cas) { char *buf; ut32 hash, pos, len, keylen; SdbKv *kv; ut64 now = 0LL; if (cas) *cas = 0; if (!s || !key) return NULL; keylen = strlen (key)+1; hash = sdb_hash (key, keylen); /* search in memory */ kv = (SdbKv*)ht_lookup (s->ht, hash); if (kv) { if (*kv->value) { if (kv->expire) { if (!now) now = sdb_now (); if (now > kv->expire) { sdb_remove (s, key, 0); return NULL; } } if (cas) *cas = kv->cas; return strdup (kv->value); // XXX too many mallocs } return NULL; } /* search in disk */ if (s->fd == -1) return NULL; cdb_findstart (&s->db); if (!cdb_findnext (&s->db, hash, key, keylen)) return NULL; len = cdb_datalen (&s->db); if (len == 0) return NULL; pos = cdb_datapos (&s->db); if (!(buf = malloc (len+1))) // XXX too many mallocs return NULL; cdb_read (&s->db, buf, len, pos); buf[len] = 0; return buf; }
void cdb_init(struct cdb *c, int fd) { struct stat st; c->map = NULL; cdb_findstart (c); c->fd = fd; if (!fstat (fd, &st) && st.st_size != UT32_MAX) { #if USE_MMAN char *x = mmap (0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); #else char *x = malloc (st.st_size); read (fd, x, st.st_size); // TODO: handle return value #endif if (x + 1) { c->size = st.st_size; c->map = x; } } }
main(int argc,char **argv) { char *key; int r; uint32 pos; uint32 len; unsigned long u = 0; if (!*argv) die_usage(); if (!*++argv) die_usage(); key = *argv; if (*++argv) { scan_ulong(*argv,&u); } cdb_init(&c,0); cdb_findstart(&c); for (;;) { r = cdb_findnext(&c,key,str_len(key)); if (r == -1) die_read(); if (!r) _exit(100); if (!u) break; --u; } pos = cdb_datapos(&c); len = cdb_datalen(&c); while (len > 0) { r = sizeof buf; if (r > len) r = len; if (cdb_read(&c,buf,r,pos) == -1) die_read(); if (buffer_put(buffer_1small,buf,r) == -1) die_write(); pos += r; len -= r; } if (buffer_flush(buffer_1small) == -1) die_write(); _exit(0); }
SDB_VISIBLE const char *sdb_getc (Sdb* s, const char *key, ut32 *cas) { ut32 hash, pos, len, keylen; SdbKv *kv; ut64 now = 0LL; if (cas) *cas = 0; if (!s||!key) return NULL; keylen = strlen (key)+1; hash = sdb_hash (key, keylen); /* search in memory */ kv = (SdbKv*)ht_lookup (s->ht, hash); if (kv) { if (*kv->value) { if (kv->expire) { if (!now) now = sdb_now (); if (now > kv->expire) { sdb_remove (s, key, 0); return NULL; } } if (cas) *cas = kv->cas; return kv->value; } return NULL; } /* search in disk */ if (s->fd == -1) return NULL; cdb_findstart (&s->db); if (!cdb_findnext (&s->db, hash, key, keylen)) return NULL; len = cdb_datalen (&s->db); if (len == 0) return NULL; pos = cdb_datapos (&s->db); return s->db.map+pos; }
static PyObject * cdbo_getall(CdbObject *self, PyObject *args) { PyObject * list, * data; char * key; unsigned int klen; int r, err; if (!PyArg_ParseTuple(args, "s#:getall", &key, &klen)) return NULL; list = PyList_New(0); if (list == NULL) return NULL; cdb_findstart(&self->c); while ((r = cdb_findnext(&self->c, key, klen))) { if (r == -1) { Py_DECREF(list); return CDBerr; } data = CDBO_CURDATA(self); if (data == NULL) { Py_DECREF(list); return NULL; } err = PyList_Append(list, data); Py_DECREF(data); if (err != 0) { Py_DECREF(list); return NULL; } } return list; }
static int doit(char *q,char qtype[2]) { unsigned int bpos; unsigned int anpos; unsigned int aupos; unsigned int arpos; char *control; char *wild; int flaggavesoa; int flagfound; int r; int flagns; int flagauthoritative; char x[20]; uint16 u16; char addr[8][4]; int addrnum; uint32 addrttl; int i; anpos = response_len; control = q; for (;;) { flagns = 0; flagauthoritative = 0; cdb_findstart(&c); while (r = find(control,0)) { if (r == -1) return 0; if (byte_equal(type,2,DNS_T_SOA)) flagauthoritative = 1; if (byte_equal(type,2,DNS_T_NS)) flagns = 1; } if (flagns) break; if (!*control) return 0; /* q is not within our bailiwick */ control += *control; control += 1; } if (!flagauthoritative) { response[2] &= ~4; goto AUTHORITY; /* q is in a child zone */ } flaggavesoa = 0; flagfound = 0; wild = q; for (;;) { addrnum = 0; addrttl = 0; cdb_findstart(&c); while (r = find(wild,wild != q)) { if (r == -1) return 0; flagfound = 1; if (flaggavesoa && byte_equal(type,2,DNS_T_SOA)) continue; if (byte_diff(type,2,qtype) && byte_diff(qtype,2,DNS_T_ANY) && byte_diff(type,2,DNS_T_CNAME)) continue; if (byte_equal(type,2,DNS_T_A) && (dlen - dpos == 4)) { addrttl = ttl; i = dns_random(addrnum + 1); if (i < 8) { if ((i < addrnum) && (addrnum < 8)) byte_copy(addr[addrnum],4,addr[i]); byte_copy(addr[i],4,data + dpos); } if (addrnum < 1000000) ++addrnum; continue; } if (!response_rstart(q,type,ttl)) return 0; if (byte_equal(type,2,DNS_T_NS) || byte_equal(type,2,DNS_T_CNAME) || byte_equal(type,2,DNS_T_PTR)) { if (!doname()) return 0; } else if (byte_equal(type,2,DNS_T_MX)) { if (!dobytes(2)) return 0; if (!doname()) return 0; } else if (byte_equal(type,2,DNS_T_SOA)) { if (!doname()) return 0; if (!doname()) return 0; if (!dobytes(20)) return 0; flaggavesoa = 1; } else if (!response_addbytes(data + dpos,dlen - dpos)) return 0; response_rfinish(RESPONSE_ANSWER); } for (i = 0;i < addrnum;++i) if (i < 8) { if (!response_rstart(q,DNS_T_A,addrttl)) return 0; if (!response_addbytes(addr[i],4)) return 0; response_rfinish(RESPONSE_ANSWER); } if (flagfound) break; if (wild == control) break; if (!*wild) break; /* impossible */ wild += *wild; wild += 1; } if (!flagfound) response_nxdomain(); AUTHORITY: aupos = response_len; if (flagauthoritative && (aupos == anpos)) { cdb_findstart(&c); while (r = find(control,0)) { if (r == -1) return 0; if (byte_equal(type,2,DNS_T_SOA)) { if (!response_rstart(control,DNS_T_SOA,ttl)) return 0; if (!doname()) return 0; if (!doname()) return 0; if (!dobytes(20)) return 0; response_rfinish(RESPONSE_AUTHORITY); break; } } } else if (want(control,DNS_T_NS)) { cdb_findstart(&c); while (r = find(control,0)) { if (r == -1) return 0; if (byte_equal(type,2,DNS_T_NS)) { if (!response_rstart(control,DNS_T_NS,ttl)) return 0; if (!doname()) return 0; response_rfinish(RESPONSE_AUTHORITY); } } } arpos = response_len; bpos = anpos; while (bpos < arpos) { bpos = dns_packet_skipname(response,arpos,bpos); if (!bpos) return 0; bpos = dns_packet_copy(response,arpos,bpos,x,10); if (!bpos) return 0; if (byte_equal(x,2,DNS_T_NS) || byte_equal(x,2,DNS_T_MX)) { if (byte_equal(x,2,DNS_T_NS)) { if (!dns_packet_getname(response,arpos,bpos,&d1)) return 0; } else if (!dns_packet_getname(response,arpos,bpos + 2,&d1)) return 0; case_lowerb(d1,dns_domain_length(d1)); if (want(d1,DNS_T_A)) { cdb_findstart(&c); while (r = find(d1,0)) { if (r == -1) return 0; if (byte_equal(type,2,DNS_T_A)) { if (!response_rstart(d1,DNS_T_A,ttl)) return 0; if (!dobytes(4)) return 0; response_rfinish(RESPONSE_ADDITIONAL); } } } } uint16_unpack_big(x + 8,&u16); bpos += u16; } if (flagauthoritative && (response_len > 512)) { byte_zero(response + RESPONSE_ADDITIONAL,2); response_len = arpos; if (response_len > 512) { byte_zero(response + RESPONSE_AUTHORITY,2); response_len = aupos; } } return 1; }
/* {{{ cdb_init */ void cdb_init(struct cdb *c, php_stream *fp) { cdb_free(c); cdb_findstart(c); c->fp = fp; }
void doaxfr (char id[2]) { int r = 0; char num[4]; char key[512]; uint32 klen = 0; uint32 eod = 0, pos = 0; axfrcheck (zone); tai_now (&now); cdb_init (&c, fdcdb); byte_zero (clientloc, 2); key[0] = 0; key[1] = '%'; byte_copy (key + 2, 4, ip); r = cdb_find (&c, key, 6); if (!r) r = cdb_find (&c, key, 5); if (!r) r = cdb_find (&c, key, 4); if (!r) r = cdb_find (&c, key, 3); if (!r) r = cdb_find (&c, key, 2); if (r == -1) errx (-1, "could not read from file `data.cdb'"); if (r && (cdb_datalen (&c) == 2)) if (cdb_read (&c, clientloc, 2, cdb_datapos (&c)) == -1) err (-1, "could not read from file `data.cdb'"); cdb_findstart (&c); for (;;) { r = cdb_findnext (&c, zone, zonelen); if (r == -1) errx (-1, "could not read from file `data.cdb'"); if (!r) errx (-1, "could not find information in `data.cdb'"); dlen = cdb_datalen (&c); if (dlen > sizeof data) errx (-1, "could not read from file `data.cdb': format error"); if (cdb_read (&c, data, dlen, cdb_datapos (&c)) == -1) errx (-1, "could not read from file `data.cdb': format error"); if (build (&soa, zone, 1, id)) break; } cdb_free (&c); print (soa.s, soa.len); seek_begin (fdcdb); buffer_init (&bcdb, buffer_unixread, fdcdb, bcdbspace, sizeof (bcdbspace)); pos = 0; get (num, 4); pos += 4; uint32_unpack (num, &eod); while (pos < 2048) { get (num, 4); pos += 4; } while (pos < eod) { if (eod - pos < 8) errx (-1, "could not read from file `data.cdb': format error"); get (num, 4); pos += 4; uint32_unpack (num, &klen); get (num,4); pos += 4; uint32_unpack (num, &dlen); if (eod - pos < klen) errx (-1, "could not read from file `data.cdb': format error"); pos += klen; if (eod - pos < dlen) errx (-1, "could not read from file `data.cdb': format error"); pos += dlen; if (klen > sizeof key) errx (-1, "could not read from file `data.cdb': format error"); get (key, klen); if (dlen > sizeof data) errx (-1, "could not read from file `data.cdb': format error"); get (data, dlen); if ((klen > 1) && (key[0] == 0)) continue; /* location */ if (klen < 1) errx (-1, "could not read from file `data.cdb': format error"); if (dns_packet_getname (key, klen, 0, &q) != klen) errx (-1, "could not read from file `data.cdb': format error"); if (!dns_domain_suffix (q, zone)) continue; if (!build (&message, q, 0, id)) continue; print (message.s, message.len); } print (soa.s, soa.len); }
void doaxfr(char id[2]) { char key[512]; uint32 klen; char num[4]; uint32 eod; uint32 pos; int r; axfrcheck(zone); find_client_loc(clientloc, ip); tai_now(&now); cdb_init(&c,fdcdb); cdb_findstart(&c); for (;;) { r = cdb_findnext(&c,zone,zonelen); if (r == -1) die_cdbread(); if (!r) die_outside(); dlen = cdb_datalen(&c); if (dlen > sizeof data) die_cdbformat(); if (cdb_read(&c,data,dlen,cdb_datapos(&c)) == -1) die_cdbformat(); if (build(&soa,zone,1,id)) break; } cdb_free(&c); print(soa.s,soa.len); seek_begin(fdcdb); buffer_init(&bcdb,buffer_unixread,fdcdb,bcdbspace,sizeof bcdbspace); pos = 0; get(num,4); pos += 4; uint32_unpack(num,&eod); while (pos < 2048) { get(num,4); pos += 4; } while (pos < eod) { if (eod - pos < 8) die_cdbformat(); get(num,4); pos += 4; uint32_unpack(num,&klen); get(num,4); pos += 4; uint32_unpack(num,&dlen); if (eod - pos < klen) die_cdbformat(); pos += klen; if (eod - pos < dlen) die_cdbformat(); pos += dlen; if (klen > sizeof key) die_cdbformat(); get(key,klen); if (dlen > sizeof data) die_cdbformat(); get(data,dlen); if ((klen > 1) && (key[0] == 0)) continue; /* location */ if (klen < 1) die_cdbformat(); if (dns_packet_getname(key,klen,0,&q) != klen) die_cdbformat(); if (!dns_domain_suffix(q,zone)) continue; if (!build(&message,q,0,id)) continue; print(message.s,message.len); } print(soa.s,soa.len); }
int cdb_find(struct cdb *c,char *key,unsigned int len) { cdb_findstart(c); return cdb_findnext(c,key,len); }
int cdb_find(struct cdb *c,char *key,off_t len) { cdb_findstart(c); return cdb_findnext(c,key,len); }