Imported cdb-0.75-traversal patch default tip
author"Tomas Zeman <tomas.zeman@sun.com>"
Fri, 19 Oct 2007 11:09:15 +0200
changeset 0 6ba86bca35c0
Imported cdb-0.75-traversal patch
.hgignore
pristine/cdb-0.75-traversal.README
pristine/cdb-0.75-traversal.diff2
series
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Fri Oct 19 11:09:15 2007 +0200
@@ -0,0 +1,3 @@
+syntax: glob
+status
+guards
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pristine/cdb-0.75-traversal.README	Fri Oct 19 11:09:15 2007 +0200
@@ -0,0 +1,26 @@
+http://www.fefe.de/cdb/
+
+What is cdb and why does it need your patches?
+
+cdb is DJ Bernstein's great constant database library. It allows the fast
+creation and access to read-only databases. The creation is fast enough to
+create those databases often and the access is very fast and uses only very
+little code. Also, there are no corruption or locking issues at all.
+
+Unfortunately, the cdb API has no way to dump all records in a cdb. I need this
+functionality for another project called rdbm that I will release soon,
+hopefully. rdbm will add write access to cdb using a journal and it will handle
+concurrent accesses by offering a TCP server.
+
+What does your diff do?
+
+My diff adds simple support for traversing a cdb, i.e. listing all keys in a
+cdb. It also adds a new target called "traverse" that is an example program
+that will dump the cdb you name on the command line and a target called
+"cdbnext" that can list the key following the key given on the command line.
+
+Where can I get the patch?
+
+Simply download cdb-0.75-traversal.diff2.bz2 (uncompressed). Beware: unified
+diff format (you probably need GNU patch to apply it).
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pristine/cdb-0.75-traversal.diff2	Fri Oct 19 11:09:15 2007 +0200
@@ -0,0 +1,809 @@
+diff -uNr cdb-0.75/FILES cdb-0.75-fefe/FILES
+--- cdb-0.75/FILES	Sat Feb 19 21:42:05 2000
++++ cdb-0.75-fefe/FILES	Wed Sep 27 21:54:44 2000
+@@ -76,3 +76,21 @@
+ uint32.h2
+ uint32_pack.c
+ uint32_unpack.c
++traverse.c
++cdbdump.1
++cdbget.1
++cdbmake.1
++cdbstats.1
++cdbtest.1
++cdbnext.c
++cdb_datalen.3
++cdb_datapos.3
++cdb_find.3
++cdb_firstkey.3
++cdb_free.3
++cdb_init.3
++cdb_keylen.3
++cdb_keypos.3
++cdb_nextkey.3
++cdb_read.3
++cdb_successor.3
+diff -uNr cdb-0.75/Makefile cdb-0.75-fefe/Makefile
+--- cdb-0.75/Makefile	Sat Feb 19 21:42:05 2000
++++ cdb-0.75-fefe/Makefile	Wed Sep 27 21:46:39 2000
+@@ -87,13 +87,17 @@
+ 	./compile byte_diff.c
+ 
+ cdb.a: \
+-makelib cdb.o cdb_hash.o cdb_make.o
+-	./makelib cdb.a cdb.o cdb_hash.o cdb_make.o
++makelib cdb.o cdb_hash.o cdb_make.o cdb_traverse.o
++	./makelib cdb.a cdb.o cdb_hash.o cdb_make.o cdb_traverse.o
+ 
+ cdb.o: \
+ compile cdb.c readwrite.h error.h seek.h byte.h cdb.h uint32.h
+ 	./compile cdb.c
+ 
++cdb_traverse.o: \
++compile cdb_traverse.c cdb.h uint32.h seek.h
++	./compile cdb_traverse.c
++
+ cdb_hash.o: \
+ compile cdb_hash.c cdb.h uint32.h
+ 	./compile cdb_hash.c
+@@ -244,7 +248,7 @@
+ 
+ prog: \
+ cdbget cdbmake cdbdump cdbstats cdbtest cdbmake-12 cdbmake-sv rts \
+-testzero
++testzero traverse cdbnext
+ 
+ rts: \
+ warn-auto.sh rts.sh conf-home
+@@ -318,3 +322,26 @@
+ seek_cur.o
+ 	./makelib unix.a error.o open_read.o open_trunc.o \
+ 	error_str.o seek_set.o seek_cur.o
++
++traverse: \
++load traverse.o cdb.a uint32_unpack.o byte_copy.o seek_set.o \
++error.o byte_diff.o fmt_ulong.o
++	./load traverse cdb.a uint32_unpack.o byte_copy.o seek_set.o \
++	error.o byte_diff.o fmt_ulong.o
++
++traverse.o: \
++compile traverse.c cdb.h uint32.h fmt.h
++	./compile traverse.c
++
++cdbnext: \
++load cdbnext.o cdb.a buffer.a byte.a error.o error_str.o seek_set.o
++	./load cdbnext cdb.a buffer.a byte.a error.o error_str.o \
++	seek_set.o
++
++cdbnext.o: \
++compile cdbnext.c exit.h scan.h str.h buffer.h strerr.h cdb.h \
++uint32.h
++	./compile cdbnext.c
++
++clean:
++	rm -f `cat TARGETS`
+diff -uNr cdb-0.75/TARGETS cdb-0.75-fefe/TARGETS
+--- cdb-0.75/TARGETS	Sat Feb 19 21:42:05 2000
++++ cdb-0.75-fefe/TARGETS	Wed Sep 27 21:35:15 2000
+@@ -64,3 +64,8 @@
+ it
+ setup
+ check
++traverse
++traverse.o
++cdb_traverse.o
++cdbnext
++cdbnext.o
+diff -uNr cdb-0.75/cdb.h cdb-0.75-fefe/cdb.h
+--- cdb-0.75/cdb.h	Sat Feb 19 21:42:05 2000
++++ cdb-0.75-fefe/cdb.h	Wed Sep 27 21:02:59 2000
+@@ -31,7 +31,14 @@
+ extern int cdb_findnext(struct cdb *,char *,unsigned int);
+ extern int cdb_find(struct cdb *,char *,unsigned int);
+ 
++extern int cdb_firstkey(struct cdb *c,uint32 *kpos);
++extern int cdb_nextkey(struct cdb *c,uint32 *kpos);
++
++extern int cdb_successor(struct cdb *c,char *,unsigned int);
++
+ #define cdb_datapos(c) ((c)->dpos)
+ #define cdb_datalen(c) ((c)->dlen)
++#define cdb_keypos(c) ((c)->kpos)
++#define cdb_keylen(c) ((c)->dpos-(c)->kpos)
+ 
+ #endif
+diff -uNr cdb-0.75/cdb_datalen.3 cdb-0.75-fefe/cdb_datalen.3
+--- cdb-0.75/cdb_datalen.3	Thu Jan  1 01:00:00 1970
++++ cdb-0.75-fefe/cdb_datalen.3	Wed Sep 27 21:52:34 2000
+@@ -0,0 +1,17 @@
++.TH cdb_datalen 3
++.SH NAME
++cdb_datalen \- get length of data
++.SH SYNTAX
++.B #include <cdb.h>
++
++unsigned int cdb_datalen(struct cdb *\fIc\fR);
++
++.SH DESCRIPTION
++.B cdb_datalen
++returns the length of the data associated with the last key you looked
++up with cdb_find or cdb_findnext.
++
++Use cdb_datapos to get the position of the data.
++
++.SH "SEE ALSO"
++cdb_datapos(3), cdb_keylen(3), cdb_keypos(3)
+diff -uNr cdb-0.75/cdb_datapos.3 cdb-0.75-fefe/cdb_datapos.3
+--- cdb-0.75/cdb_datapos.3	Thu Jan  1 01:00:00 1970
++++ cdb-0.75-fefe/cdb_datapos.3	Wed Sep 27 21:52:37 2000
+@@ -0,0 +1,17 @@
++.TH cdb_datapos 3
++.SH NAME
++cdb_datapos \- get position of data
++.SH SYNTAX
++.B #include <cdb.h>
++
++uint32 cdb_datapos(struct cdb *\fIc\fR);
++
++.SH DESCRIPTION
++.B cdb_datapos
++returns the position of the data associated with the last key you looked
++up using cdb_find or cdb_findnext.
++
++Use cdb_datalen to get the length of the data.
++
++.SH "SEE ALSO"
++cdb_datalen(3), cdb_keypos(3), cdb_keylen(3)
+diff -uNr cdb-0.75/cdb_find.3 cdb-0.75-fefe/cdb_find.3
+--- cdb-0.75/cdb_find.3	Thu Jan  1 01:00:00 1970
++++ cdb-0.75-fefe/cdb_find.3	Wed Sep 27 21:53:03 2000
+@@ -0,0 +1,42 @@
++.TH cdb_find 3
++.SH NAME
++cdb_find \- look up a key in a constant database
++.SH SYNTAX
++.B #include <cdb.h>
++.br
++.B #include <uint32.h>
++
++int cdb_find(struct cdb *\fIc\fR,char *\fIkey\fR,unsigned int \fIkeylen\fR);
++.br
++int cdb_datalen(struct cdb *\fIc\fR);
++.br
++int cdb_datapos(struct cdb *\fIc\fR);
++.br
++int cdb_findnext(struct cdb *\fIc\fR,char *\fIkey\fR,unsigned int \fIkeylen\fR);
++
++.SH DESCRIPTION
++\fBcdb_find\fR looks for \fIkey\fR. If cdb_find returns 0, the database
++does not contain that key; stop. If cdb_find returns -1, there was a
++read error; abort.
++
++\fBcdb_datalen\fR returns the length of the data associated with the
++\fIkey\fR.  Use it to allocate a pointer \fIp\fR with enough space to
++hold the data.
++
++\fBcdb_datapos\fR returns the position of the data inside the file.  Use
++it as argument to cdb_read to retrieve the data.
++
++There may be several records under a single key. You can use
++\fBcdb_findnext\fR to find the next record under this key.
++
++.SH EXAMPLE
++static struct cdb;
++
++if (cdb_find(&c,key,strlen(key)>0) {
++  char *buf=alloca(cdb_datalen(&c));
++  cdb_read(&c,buf,cdb_datalen(&c),cdb_datapos(&c));
++  write(1,buf,cdb_datalen(&c));
++.br
++}
++.SH "SEE ALSO"
++cdb_read(3), cdb_init(3), cdb_free(3), cdbmake(1)
+diff -uNr cdb-0.75/cdb_firstkey.3 cdb-0.75-fefe/cdb_firstkey.3
+--- cdb-0.75/cdb_firstkey.3	Thu Jan  1 01:00:00 1970
++++ cdb-0.75-fefe/cdb_firstkey.3	Wed Sep 27 21:53:07 2000
+@@ -0,0 +1,19 @@
++.TH cdb_firstkey 3
++.SH NAME
++cdb_firstkey \- find first physical record in constant database
++.SH SYNTAX
++.B #include <cdb.h>
++.br
++.B #include <uint32.h>
++
++int cdb_firstkey(struct cdb *\fIc\fR,uint32 *\fIkpos\fR);
++
++.SH DESCRIPTION
++\fBcdb_firstkey\fR finds the physically first record in the constant
++database.
++
++You can use cdb_datapos or cdb_keypos to get \fIposition\fR and
++cdb_datalen and cdb_keylen to get \fIlen\fR.
++
++.SH "SEE ALSO"
++cdb_nextkey(3), cdb_successor(3)
+diff -uNr cdb-0.75/cdb_free.3 cdb-0.75-fefe/cdb_free.3
+--- cdb-0.75/cdb_free.3	Thu Jan  1 01:00:00 1970
++++ cdb-0.75-fefe/cdb_free.3	Wed Sep 27 21:53:10 2000
+@@ -0,0 +1,17 @@
++.TH cdb_free 3
++.SH NAME
++cdb_free \- close a constant databased
++.SH SYNTAX
++.B #include <cdb.h>
++
++int cdb_free(struct cdb *\fIc\fR);
++
++.SH DESCRIPTION
++.B cdb_free
++removes any memory mapping that cdb_init might have established.
++
++It will not close the file descriptor that you passed to cdb_init or
++attempt to call free() on the struct cdb pointer.
++
++.SH "SEE ALSO"
++cdb_free(3), cdb_read(3), cdb_find(3), cdbmake(1)
+diff -uNr cdb-0.75/cdb_init.3 cdb-0.75-fefe/cdb_init.3
+--- cdb-0.75/cdb_init.3	Thu Jan  1 01:00:00 1970
++++ cdb-0.75-fefe/cdb_init.3	Wed Sep 27 21:53:12 2000
+@@ -0,0 +1,20 @@
++.TH cdb_init 3
++.SH NAME
++cdb_init \- open a constant database
++.SH SYNTAX
++.B #include <cdb.h>
++
++int cdb_init(struct cdb *\fIc\fR,int \fIfd\fR);
++
++.SH DESCRIPTION
++.B cdb_init
++places information about \fIfd\fR into a struct cdb variable \fIc\fR.
++\fIfd\fR has to be a seekable file previously opened for reading.
++
++On systems that support mmap, cdb_init will try to map the whole
++constant database into memory.
++
++The inverse operation to cdb_init is cdb_free.
++
++.SH "SEE ALSO"
++cdb_free(3), cdb_read(3), cdb_find(3), cdbmake(1)
+diff -uNr cdb-0.75/cdb_keylen.3 cdb-0.75-fefe/cdb_keylen.3
+--- cdb-0.75/cdb_keylen.3	Thu Jan  1 01:00:00 1970
++++ cdb-0.75-fefe/cdb_keylen.3	Wed Sep 27 21:53:14 2000
+@@ -0,0 +1,16 @@
++.TH cdb_keylen 3
++.SH NAME
++cdb_keylen \- get length of key
++.SH SYNTAX
++.B #include <cdb.h>
++
++unsigned int cdb_keylen(struct cdb *\fIc\fR);
++
++.SH DESCRIPTION
++.B cdb_keylen
++returns the length of the key cdb_firstkey or cdb_nextkey found.
++
++Use cdb_keypos to get the position of the key.
++
++.SH "SEE ALSO"
++cdb_keypos(3), cdb_datalen(3), cdb_datapos(3)
+diff -uNr cdb-0.75/cdb_keypos.3 cdb-0.75-fefe/cdb_keypos.3
+--- cdb-0.75/cdb_keypos.3	Thu Jan  1 01:00:00 1970
++++ cdb-0.75-fefe/cdb_keypos.3	Wed Sep 27 21:53:16 2000
+@@ -0,0 +1,16 @@
++.TH cdb_keypos 3
++.SH NAME
++cdb_keypos \- get position of key
++.SH SYNTAX
++.B #include <cdb.h>
++
++uint32 cdb_keypos(struct cdb *\fIc\fR);
++
++.SH DESCRIPTION
++.B cdb_keypos
++returns the position of the key cdb_firstkey or cdb_nextkey found.
++
++Use cdb_keylen to get the length of the key.
++
++.SH "SEE ALSO"
++cdb_keylen(3), cdb_datapos(3), cdb_datalen(3)
+diff -uNr cdb-0.75/cdb_nextkey.3 cdb-0.75-fefe/cdb_nextkey.3
+--- cdb-0.75/cdb_nextkey.3	Thu Jan  1 01:00:00 1970
++++ cdb-0.75-fefe/cdb_nextkey.3	Wed Sep 27 21:52:17 2000
+@@ -0,0 +1,19 @@
++.TH cdb_nextkey 3
++.SH NAME
++cdb_nextkey \- find next physical record in constant database
++.SH SYNTAX
++.B #include <cdb.h>
++.br
++.B #include <uint32.h>
++
++int cdb_nextkey(struct cdb *\fIc\fR,uint32 *\fIkpos\fR);
++
++.SH DESCRIPTION
++\fBcdb_nextkey\fR finds the next physical record in the constant
++database.
++
++You can use cdb_datapos or cdb_keypos to get \fIposition\fR and
++cdb_datalen and cdb_keylen to get \fIlen\fR.
++
++.SH "SEE ALSO"
++cdb_firstkey(3), cdb_successor(3)
+diff -uNr cdb-0.75/cdb_read.3 cdb-0.75-fefe/cdb_read.3
+--- cdb-0.75/cdb_read.3	Thu Jan  1 01:00:00 1970
++++ cdb-0.75-fefe/cdb_read.3	Wed Sep 27 21:53:22 2000
+@@ -0,0 +1,20 @@
++.TH cdb_read 3
++.SH NAME
++cdb_read \- read bytes from a constant database
++.SH SYNTAX
++.B #include <cdb.h>
++.br
++.B #include <uint32.h>
++
++int cdb_read(struct cdb *\fIc\fR,char *\fIbuf\fR,unsigned int \fIlen\fR,uint32 \fIposition\fR);
++
++.SH DESCRIPTION
++\fBcdb_read\fR reads \fIlen\fR bytes starting at \fIposition\fR from
++\fIc\fR to buf.  You can use cdb_datapos or cdb_keypos to get
++\fIposition\fR and cdb_datalen and cdb_keylen to get \fIlen\fR.
++
++\fIbuf\fR needs to point to a memory region large enough to hold
++\fIlen\fR bytes.
++
++.SH "SEE ALSO"
++cdb_find(3), cdb_init(3), cdb_free(3), cdbmake(1)
+diff -uNr cdb-0.75/cdb_successor.3 cdb-0.75-fefe/cdb_successor.3
+--- cdb-0.75/cdb_successor.3	Thu Jan  1 01:00:00 1970
++++ cdb-0.75-fefe/cdb_successor.3	Wed Sep 27 21:53:23 2000
+@@ -0,0 +1,21 @@
++.TH cdb_successor 3
++.SH NAME
++cdb_successor \- find next record
++.SH SYNTAX
++.B #include <cdb.h>
++
++int cdb_successor(struct cdb *\fIc\fR,char *\fIkey\fR,unsigned int \fIklen\fR);
++
++.SH DESCRIPTION
++\fBcdb_successor\fR finds the record that follows \fIkey\fR.  If
++\fIkey\fR is NULL, cdb_successor finds the first record.
++
++\fBNOTE!\fR  The database must not contain keys with more than one
++associated record or this API will lead to infinite loops!  Use
++cdb_firstkey and cdb_nextkey instead.
++
++You can use cdb_datapos or cdb_keypos to get \fIposition\fR and
++cdb_datalen and cdb_keylen to get \fIlen\fR.
++
++.SH "SEE ALSO"
++cdb_firstkey(3), cdb_nextkey(3)
+diff -uNr cdb-0.75/cdb_traverse.c cdb-0.75-fefe/cdb_traverse.c
+--- cdb-0.75/cdb_traverse.c	Thu Jan  1 01:00:00 1970
++++ cdb-0.75-fefe/cdb_traverse.c	Wed Sep 27 21:39:18 2000
+@@ -0,0 +1,41 @@
++#include "cdb.h"
++#include "seek.h"
++
++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;
++}
++
++int cdb_firstkey(struct cdb *c,uint32 *kpos) {
++  *kpos=2048;
++  return doit(c,kpos);
++}
++
++int cdb_nextkey(struct cdb *c,uint32 *kpos) {
++  return doit(c,kpos);
++}
++
++int cdb_successor(struct cdb *c,char *key,unsigned int klen) {
++  int r;
++  uint32 kpos;
++  if (key) {
++    r=cdb_find(c,key,klen);
++    if (r<1) return r;
++    kpos=c->dpos+c->dlen;
++  } else
++    kpos=2048;
++  return doit(c,&kpos);
++}
+diff -uNr cdb-0.75/cdbdump.1 cdb-0.75-fefe/cdbdump.1
+--- cdb-0.75/cdbdump.1	Thu Jan  1 01:00:00 1970
++++ cdb-0.75-fefe/cdbdump.1	Wed Sep 27 20:27:54 2000
+@@ -0,0 +1,17 @@
++.TH cdbdump 1
++.SH NAME
++cdbdump \- print the contents of a constant database
++.SH SYNOPSIS
++.B cdbdump
++.SH DESCRIPTION
++.B cbddump
++reads a constant database from its standard input
++and prints its contents, in
++.B cbdmake
++format,
++on standard output.
++.SH "SEE ALSO"
++cdbget(1),
++cdbmake(1),
++cdb_firstkey(3),
++cdb_nextkey(3)
+diff -uNr cdb-0.75/cdbget.1 cdb-0.75-fefe/cdbget.1
+--- cdb-0.75/cdbget.1	Thu Jan  1 01:00:00 1970
++++ cdb-0.75-fefe/cdbget.1	Sun Apr 30 14:31:33 2000
+@@ -0,0 +1,38 @@
++.TH cdbget 1
++.SH NAME
++cdbget \- look up one key in a constant database
++.SH SYNOPSIS
++.B cdbget
++.I key
++.SH DESCRIPTION
++.B cdbget
++searches for a record indexed by
++.I key
++in a constant database.
++The constant database must be readable (and seekable)
++on
++.BR cdbget 's
++standard input.
++
++.B cdbget
++normally (1) prints the data in the first matching record
++and (2) exits 0.
++Note that
++.B cdbget
++does not check for write errors,
++so it should be used only inside a pipe.
++
++If
++.I key
++is not in the database,
++.B cdbget
++exits 1 without printing anything.
++
++If
++.B cdbget
++encounters a read error,
++it complains and exits 111.
++.SH "SEE ALSO"
++cdbdump(1),
++cdbmake(1),
++cdb(3)
+diff -uNr cdb-0.75/cdbmake.1 cdb-0.75-fefe/cdbmake.1
+--- cdb-0.75/cdbmake.1	Thu Jan  1 01:00:00 1970
++++ cdb-0.75-fefe/cdbmake.1	Sun Apr 30 14:31:33 2000
+@@ -0,0 +1,113 @@
++.TH cdbmake 1
++.SH NAME
++cdbmake \- create a constant database
++.SH SYNOPSIS
++.B cdbmake
++.I file
++.I temp
++.SH DESCRIPTION
++.B cdbmake
++reads a series of encoded records from its standard input
++and writes a constant database to
++.IR file .
++
++Records are indexed by
++.BR keys .
++A key is a string.
++.I file
++is structured so that another program, starting from a key,
++can quickly find the relevant record.
++.B cdbmake
++allows several records with the same key,
++although (1) most readers only take the first record
++and (2)
++.B cdbmake
++slows down somewhat if there are many records with the same key.
++Note that
++.B cdbmake
++preserves the order of records in
++.IR file .
++
++A record is encoded for
++.B cdbmake
++as
++.B +\fIklen\fB,\fIdlen\fB:\fIkey\fB->\fIdata
++followed by a newline.
++Here
++.I klen
++is the number of bytes in
++.IR key
++and
++.I dlen
++is the number of bytes in
++.IR data .
++The end of data is indicated by an extra newline.
++For example:
++
++.EX
++   +3,5:one->Hello
++.br
++   +3,7:two->Goodbye
++.br
++   
++.EE
++
++.I key
++and
++.I data
++may contain any characters, including colons, dashes, newlines, and nulls.
++
++.B cdbmake
++ensures that
++.I file
++is updated atomically,
++so programs reading
++.I file
++never have to wait for
++.B cdbmake
++to finish.
++It does this by first writing the database to
++.I temp
++and then moving
++.I temp
++on top of
++.IR file .
++If
++.I temp
++already exists,
++it is destroyed.
++The directories containing
++.I temp
++and
++.I file
++must be writable to
++.BR cdbmake ;
++they must also be on the same filesystem.
++
++.B cdbmake
++always makes sure that
++.I temp
++is safely written to disk before it replaces
++.IR file .
++If the input is in a bad format or if
++.B cdbmake
++has any trouble writing
++.I temp
++to disk,
++.B cdbmake
++complains and leaves
++.I file
++alone.
++
++Keys and data do not have to fit into memory,
++but
++.B cdbmake
++needs roughly 16 bytes of memory per record.
++A database cannot exceed 4 gigabytes.
++
++.I file
++is portable across machines.
++.SH "SEE ALSO"
++cdbdump(1),
++cdbget(1),
++cdbstats(1)
+diff -uNr cdb-0.75/cdbnext.c cdb-0.75-fefe/cdbnext.c
+--- cdb-0.75/cdbnext.c	Thu Jan  1 01:00:00 1970
++++ cdb-0.75-fefe/cdbnext.c	Wed Sep 27 21:43:32 2000
+@@ -0,0 +1,51 @@
++#include "exit.h"
++#include "scan.h"
++#include "str.h"
++#include "buffer.h"
++#include "strerr.h"
++#include "cdb.h"
++
++#define FATAL "cdbnext: fatal: "
++
++void die_read(void)
++{
++  strerr_die2sys(111,FATAL,"unable to read input: ");
++}
++void die_write(void)
++{
++  strerr_die2sys(111,FATAL,"unable to write output: ");
++}
++
++static struct cdb c;
++char buf[1024];
++
++main(int argc,char **argv)
++{
++  char *key;
++  int r;
++  uint32 pos;
++  uint32 len;
++  unsigned long u = 0;
++
++  key = argv[1];
++
++  cdb_init(&c,0);
++
++  r=cdb_successor(&c,key,key?str_len(key):0);
++  if (r == -1) die_read();
++  if (!r) _exit(100);
++
++  pos = cdb_keypos(&c);
++  len = cdb_keylen(&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);
++}
+diff -uNr cdb-0.75/cdbstats.1 cdb-0.75-fefe/cdbstats.1
+--- cdb-0.75/cdbstats.1	Thu Jan  1 01:00:00 1970
++++ cdb-0.75-fefe/cdbstats.1	Sun Apr 30 14:31:33 2000
+@@ -0,0 +1,18 @@
++.TH cdbstats 1
++.SH NAME
++cdbstats \- summarize the contents of a constant database
++.SH SYNOPSIS
++.B cdbstats
++.SH DESCRIPTION
++.B cdbstats
++reads a (seekable) constant database from its standard input
++and prints a few statistics:
++.B slots
++is the number of hash positions;
++.B records
++is the number of records in the database;
++.B d0
++is the number of records at distance 0 from their hash.
++.SH "SEE ALSO"
++cdbdump(1),
++cdbmake(1)
+diff -uNr cdb-0.75/cdbtest.1 cdb-0.75-fefe/cdbtest.1
+--- cdb-0.75/cdbtest.1	Thu Jan  1 01:00:00 1970
++++ cdb-0.75-fefe/cdbtest.1	Sun Apr 30 14:31:33 2000
+@@ -0,0 +1,36 @@
++.TH cdbtest 1
++.SH NAME
++cdbtest \- check retrieval from a constant database
++.SH SYNOPSIS
++.B cdbtest
++.SH DESCRIPTION
++.B cdbtest
++reads a (seekable) constant database from its standard input.
++For each record in the database, it feeds the record's key to
++.B cdb_seek()
++and checks the result.
++It prints tallies in several categories:
++.TP 5
++.B found
++is the number of records found correctly by their keys.
++.TP
++.B different record
++is the number of records where a different record was found
++with the same key. This should not happen unless the database
++has multiple records with the same key.
++.TP
++.B bad length
++is the number of records found but with the wrong data length.
++This should never happen.
++.TP
++.B not found
++is the number of records not found.
++This should never happen.
++.TP
++.B too long to test
++is the number of records with keys longer than 1024 bytes.
++.B cdbtest
++doesn't bother testing these records.
++.SH "SEE ALSO"
++cdbget(1),
++cdb(3)
+Binary files cdb-0.75/foo.cdb and cdb-0.75-fefe/foo.cdb differ
+diff -uNr cdb-0.75/hier.c cdb-0.75-fefe/hier.c
+--- cdb-0.75/hier.c	Sat Feb 19 21:42:05 2000
++++ cdb-0.75-fefe/hier.c	Wed Sep 27 22:05:11 2000
+@@ -4,6 +4,10 @@
+ {
+   h(auto_home,-1,-1,02755);
+   d(auto_home,"bin",-1,-1,02755);
++  d(auto_home,"man",-1,-1,0755);
++  d(auto_home,"man/man1",-1,-1,0755);
++  d(auto_home,"man/man3",-1,-1,0755);
++
+ 
+   c(auto_home,"bin","cdbget",-1,-1,0755);
+   c(auto_home,"bin","cdbmake",-1,-1,0755);
+@@ -12,4 +16,22 @@
+   c(auto_home,"bin","cdbtest",-1,-1,0755);
+   c(auto_home,"bin","cdbmake-12",-1,-1,0755);
+   c(auto_home,"bin","cdbmake-sv",-1,-1,0755);
++
++  c(auto_home,"man/man1","cdbdump.1",-1,-1,0755);
++  c(auto_home,"man/man1","cdbget.1",-1,-1,0755);
++  c(auto_home,"man/man1","cdbmake.1",-1,-1,0755);
++  c(auto_home,"man/man1","cdbstats.1",-1,-1,0755);
++  c(auto_home,"man/man1","cdbtest.1",-1,-1,0755);
++
++  c(auto_home,"man/man3","cdb_datalen.3",-1,-1,0644);
++  c(auto_home,"man/man3","cdb_datapos.3",-1,-1,0644);
++  c(auto_home,"man/man3","cdb_find.3",-1,-1,0644);
++  c(auto_home,"man/man3","cdb_firstkey.3",-1,-1,0644);
++  c(auto_home,"man/man3","cdb_free.3",-1,-1,0644);
++  c(auto_home,"man/man3","cdb_init.3",-1,-1,0644);
++  c(auto_home,"man/man3","cdb_keylen.3",-1,-1,0644);
++  c(auto_home,"man/man3","cdb_keypos.3",-1,-1,0644);
++  c(auto_home,"man/man3","cdb_nextkey.3",-1,-1,0644);
++  c(auto_home,"man/man3","cdb_read.3",-1,-1,0644);
++  c(auto_home,"man/man3","cdb_successor.3",-1,-1,0644);
+ }
+diff -uNr cdb-0.75/traverse.c cdb-0.75-fefe/traverse.c
+--- cdb-0.75/traverse.c	Thu Jan  1 01:00:00 1970
++++ cdb-0.75-fefe/traverse.c	Wed Sep 27 18:41:38 2000
+@@ -0,0 +1,43 @@
++#include <unistd.h>
++#include <sys/fcntl.h>
++#include <stdlib.h>
++#include <assert.h>
++#include "cdb.h"
++#include "fmt.h"
++
++main(int argc,char *argv[]) {
++  int fd;
++  struct cdb c;
++  char strnum[FMT_ULONG];
++  uint32 kpos;
++  fd=open(argc>1?argv[1]:"foo.cdb",O_RDONLY);
++  assert(fd>=0);
++  cdb_init(&c,fd);
++  if (cdb_firstkey(&c,&kpos)==1) {
++    do {
++      uint32 kp,klen,dp,dlen;
++      char *key,*data;
++      kp=cdb_keypos(&c);
++      klen=cdb_keylen(&c);
++      dp=cdb_datapos(&c);
++      dlen=cdb_datalen(&c);
++      {
++	key=alloca(klen);
++	data=alloca(dlen);
++/*	printf("%lu %lu; %lu %lu\n",kp,klen,dp,dlen); */
++	assert(cdb_read(&c,key,klen,kp)==0);
++	assert(cdb_read(&c,data,dlen,dp)==0);
++	write(1,"+",1);
++	write(1,strnum,fmt_ulong(strnum,klen));
++	write(1,",",1);
++	write(1,strnum,fmt_ulong(strnum,dlen));
++	write(1,":",1);
++	write(1,key,klen);
++	write(1,"->",2);
++	write(1,data,dlen);
++	write(1,"\n",1);
++      }
++    } while (cdb_nextkey(&c,&kpos)==1);
++    write(1,"\n",1);
++  }
++}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/series	Fri Oct 19 11:09:15 2007 +0200
@@ -0,0 +1,1 @@
+pristine/cdb-0.75-traversal.diff2