Index: distrib/sets/lists/base/ad.mips64eb =================================================================== RCS file: /home/joerg/repo/netbsd/src/distrib/sets/lists/base/ad.mips64eb,v retrieving revision 1.12 diff -u -p -r1.12 ad.mips64eb --- distrib/sets/lists/base/ad.mips64eb 13 Mar 2010 23:33:52 -0000 1.12 +++ distrib/sets/lists/base/ad.mips64eb 17 Mar 2010 20:53:00 -0000 @@ -62,7 +62,7 @@ ./usr/lib/64/libbz2.so.1 base-compat-shlib compat,pic ./usr/lib/64/libbz2.so.1.1 base-compat-shlib compat,pic ./usr/lib/64/libc.so.12 base-compat-shlib compat,pic -./usr/lib/64/libc.so.12.171 base-compat-shlib compat,pic +./usr/lib/64/libc.so.12.172 base-compat-shlib compat,pic ./usr/lib/64/libcom_err.so.6 base-compat-shlib compat,pic ./usr/lib/64/libcom_err.so.6.0 base-compat-shlib compat,pic ./usr/lib/64/libcrypt.so.1 base-compat-shlib compat,pic @@ -294,7 +294,7 @@ ./usr/lib/o32/libbz2.so.1 base-compat-shlib compat,pic ./usr/lib/o32/libbz2.so.1.1 base-compat-shlib compat,pic ./usr/lib/o32/libc.so.12 base-compat-shlib compat,pic -./usr/lib/o32/libc.so.12.171 base-compat-shlib compat,pic +./usr/lib/o32/libc.so.12.172 base-compat-shlib compat,pic ./usr/lib/o32/libcom_err.so.6 base-compat-shlib compat,pic ./usr/lib/o32/libcom_err.so.6.0 base-compat-shlib compat,pic ./usr/lib/o32/libcrypt.so.1 base-compat-shlib compat,pic Index: distrib/sets/lists/base/ad.mips64el =================================================================== RCS file: /home/joerg/repo/netbsd/src/distrib/sets/lists/base/ad.mips64el,v retrieving revision 1.12 diff -u -p -r1.12 ad.mips64el --- distrib/sets/lists/base/ad.mips64el 13 Mar 2010 23:33:52 -0000 1.12 +++ distrib/sets/lists/base/ad.mips64el 17 Mar 2010 20:53:00 -0000 @@ -62,7 +62,7 @@ ./usr/lib/64/libbz2.so.1 base-compat-shlib compat,pic ./usr/lib/64/libbz2.so.1.1 base-compat-shlib compat,pic ./usr/lib/64/libc.so.12 base-compat-shlib compat,pic -./usr/lib/64/libc.so.12.171 base-compat-shlib compat,pic +./usr/lib/64/libc.so.12.172 base-compat-shlib compat,pic ./usr/lib/64/libcom_err.so.6 base-compat-shlib compat,pic ./usr/lib/64/libcom_err.so.6.0 base-compat-shlib compat,pic ./usr/lib/64/libcrypt.so.1 base-compat-shlib compat,pic @@ -294,7 +294,7 @@ ./usr/lib/o32/libbz2.so.1 base-compat-shlib compat,pic ./usr/lib/o32/libbz2.so.1.1 base-compat-shlib compat,pic ./usr/lib/o32/libc.so.12 base-compat-shlib compat,pic -./usr/lib/o32/libc.so.12.171 base-compat-shlib compat,pic +./usr/lib/o32/libc.so.12.172 base-compat-shlib compat,pic ./usr/lib/o32/libcom_err.so.6 base-compat-shlib compat,pic ./usr/lib/o32/libcom_err.so.6.0 base-compat-shlib compat,pic ./usr/lib/o32/libcrypt.so.1 base-compat-shlib compat,pic Index: distrib/sets/lists/base/md.amd64 =================================================================== RCS file: /home/joerg/repo/netbsd/src/distrib/sets/lists/base/md.amd64,v retrieving revision 1.86 diff -u -p -r1.86 md.amd64 --- distrib/sets/lists/base/md.amd64 13 Mar 2010 23:33:52 -0000 1.86 +++ distrib/sets/lists/base/md.amd64 17 Mar 2010 20:53:00 -0000 @@ -65,7 +65,7 @@ ./usr/lib/i386/libbz2.so.1 base-compat-shlib compat,pic ./usr/lib/i386/libbz2.so.1.1 base-compat-shlib compat,pic ./usr/lib/i386/libc.so.12 base-compat-shlib compat,pic -./usr/lib/i386/libc.so.12.171 base-compat-shlib compat,pic +./usr/lib/i386/libc.so.12.172 base-compat-shlib compat,pic ./usr/lib/i386/libcom_err.so.6 base-compat-shlib compat,pic,kerberos ./usr/lib/i386/libcom_err.so.6.0 base-compat-shlib compat,pic,kerberos ./usr/lib/i386/libcrypt.so.1 base-compat-shlib compat,pic Index: distrib/sets/lists/base/md.sparc64 =================================================================== RCS file: /home/joerg/repo/netbsd/src/distrib/sets/lists/base/md.sparc64,v retrieving revision 1.80 diff -u -p -r1.80 md.sparc64 --- distrib/sets/lists/base/md.sparc64 13 Mar 2010 23:33:52 -0000 1.80 +++ distrib/sets/lists/base/md.sparc64 17 Mar 2010 20:53:00 -0000 @@ -63,7 +63,7 @@ ./usr/lib/sparc/libbz2.so.1 base-compat-shlib compat,pic ./usr/lib/sparc/libbz2.so.1.1 base-compat-shlib compat,pic ./usr/lib/sparc/libc.so.12 base-compat-shlib compat,pic -./usr/lib/sparc/libc.so.12.171 base-compat-shlib compat,pic +./usr/lib/sparc/libc.so.12.172 base-compat-shlib compat,pic ./usr/lib/sparc/libcom_err.so.6 base-compat-shlib compat,pic ./usr/lib/sparc/libcom_err.so.6.0 base-compat-shlib compat,pic ./usr/lib/sparc/libcrypt.so.1 base-compat-shlib compat,pic Index: distrib/sets/lists/base/shl.mi =================================================================== RCS file: /home/joerg/repo/netbsd/src/distrib/sets/lists/base/shl.mi,v retrieving revision 1.526 diff -u -p -r1.526 shl.mi --- distrib/sets/lists/base/shl.mi 13 Mar 2010 23:33:52 -0000 1.526 +++ distrib/sets/lists/base/shl.mi 17 Mar 2010 20:53:00 -0000 @@ -13,7 +13,7 @@ # # Note: libtermcap and libtermlib are hardlinked and share the same version. # -./lib/libc.so.12.171 base-sys-shlib dynamicroot +./lib/libc.so.12.172 base-sys-shlib dynamicroot ./lib/libcrypt.so.1.0 base-sys-shlib dynamicroot ./lib/libcrypto.so.6.1 base-crypto-shlib crypto,dynamicroot ./lib/libdevmapper.so.1.0 base-lvm-shlib lvm,dynamicroot @@ -63,7 +63,7 @@ ./usr/lib/libbluetooth.so.4.2 base-sys-shlib ./usr/lib/libbsdmalloc.so.0.0 base-sys-shlib ./usr/lib/libbz2.so.1.1 base-sys-shlib -./usr/lib/libc.so.12.171 base-sys-shlib +./usr/lib/libc.so.12.172 base-sys-shlib ./usr/lib/libcom_err.so.6.0 base-krb5-shlib kerberos ./usr/lib/libcrypt.so.1.0 base-sys-shlib ./usr/lib/libcrypto.so.6.1 base-crypto-shlib crypto Index: distrib/sets/lists/comp/mi =================================================================== RCS file: /home/joerg/repo/netbsd/src/distrib/sets/lists/comp/mi,v retrieving revision 1.1408 diff -u -p -r1.1408 mi --- distrib/sets/lists/comp/mi 19 Mar 2010 20:31:50 -0000 1.1408 +++ distrib/sets/lists/comp/mi 19 Mar 2010 20:33:40 -0000 @@ -191,6 +191,8 @@ ./usr/include/bluetooth.h comp-c-include ./usr/include/bm.h comp-c-include ./usr/include/bzlib.h comp-c-include +./usr/include/cdbr.h comp-c-include +./usr/include/cdbw.h comp-c-include ./usr/include/cdk/alphalist.h comp-obsolete obsolete ./usr/include/cdk/binding.h comp-obsolete obsolete ./usr/include/cdk/buttonbox.h comp-obsolete obsolete @@ -5208,6 +5210,18 @@ ./usr/share/man/cat3/ccosf.0 comp-c-catman .cat ./usr/share/man/cat3/ccosh.0 comp-c-catman .cat ./usr/share/man/cat3/ccoshf.0 comp-c-catman .cat +./usr/share/man/cat3/cdbr.0 comp-c-catman .cat +./usr/share/man/cat3/cdbr_close.0 comp-c-catman .cat +./usr/share/man/cat3/cdbr_find.0 comp-c-catman .cat +./usr/share/man/cat3/cdbr_get.0 comp-c-catman .cat +./usr/share/man/cat3/cdbr_open.0 comp-c-catman .cat +./usr/share/man/cat3/cdbw.0 comp-c-catman .cat +./usr/share/man/cat3/cdbw_close.0 comp-c-catman .cat +./usr/share/man/cat3/cdbw_output.0 comp-c-catman .cat +./usr/share/man/cat3/cdbw_put.0 comp-c-catman .cat +./usr/share/man/cat3/cdbw_put_data.0 comp-c-catman .cat +./usr/share/man/cat3/cdbw_put_key.0 comp-c-catman .cat +./usr/share/man/cat3/cdbw_open.0 comp-c-catman .cat ./usr/share/man/cat3/cdk.0 comp-obsolete obsolete ./usr/share/man/cat3/cdk_alphalist.0 comp-obsolete obsolete ./usr/share/man/cat3/cdk_binding.0 comp-obsolete obsolete @@ -11026,6 +11040,18 @@ ./usr/share/man/html3/ccosf.html comp-c-htmlman html ./usr/share/man/html3/ccosh.html comp-c-htmlman html ./usr/share/man/html3/ccoshf.html comp-c-htmlman html +./usr/share/man/html3/cdbr.html comp-c-htmlman html +./usr/share/man/html3/cdbr_close.html comp-c-htmlman html +./usr/share/man/html3/cdbr_find.html comp-c-htmlman html +./usr/share/man/html3/cdbr_get.html comp-c-htmlman html +./usr/share/man/html3/cdbr_open.html comp-c-htmlman html +./usr/share/man/html3/cdbw.html comp-c-htmlman html +./usr/share/man/html3/cdbw_close.html comp-c-htmlman html +./usr/share/man/html3/cdbw_output.html comp-c-htmlman html +./usr/share/man/html3/cdbw_put.html comp-c-htmlman html +./usr/share/man/html3/cdbw_put_data.html comp-c-htmlman html +./usr/share/man/html3/cdbw_put_key.html comp-c-htmlman html +./usr/share/man/html3/cdbw_open.html comp-c-htmlman html ./usr/share/man/html3/ceil.html comp-c-htmlman html ./usr/share/man/html3/ceilf.html comp-c-htmlman html ./usr/share/man/html3/cexp.html comp-c-htmlman html @@ -16666,6 +16692,18 @@ ./usr/share/man/man3/ccosf.3 comp-c-man .man ./usr/share/man/man3/ccosh.3 comp-c-man .man ./usr/share/man/man3/ccoshf.3 comp-c-man .man +./usr/share/man/man3/cdbr.3 comp-c-man .man +./usr/share/man/man3/cdbr_close.3 comp-c-man .man +./usr/share/man/man3/cdbr_find.3 comp-c-man .man +./usr/share/man/man3/cdbr_get.3 comp-c-man .man +./usr/share/man/man3/cdbr_open.3 comp-c-man .man +./usr/share/man/man3/cdbw.3 comp-c-man .man +./usr/share/man/man3/cdbw_close.3 comp-c-man .man +./usr/share/man/man3/cdbw_output.3 comp-c-man .man +./usr/share/man/man3/cdbw_put.3 comp-c-man .man +./usr/share/man/man3/cdbw_put_data.3 comp-c-man .man +./usr/share/man/man3/cdbw_put_key.3 comp-c-man .man +./usr/share/man/man3/cdbw_open.3 comp-c-man .man ./usr/share/man/man3/cdk.3 comp-obsolete obsolete ./usr/share/man/man3/cdk_alphalist.3 comp-obsolete obsolete ./usr/share/man/man3/cdk_binding.3 comp-obsolete obsolete Index: distrib/sets/lists/man/mi =================================================================== RCS file: /home/joerg/repo/netbsd/src/distrib/sets/lists/man/mi,v retrieving revision 1.1198 diff -u -p -r1.1198 mi --- distrib/sets/lists/man/mi 11 Mar 2010 10:38:36 -0000 1.1198 +++ distrib/sets/lists/man/mi 17 Mar 2010 20:53:02 -0000 @@ -1742,6 +1742,7 @@ ./usr/share/man/cat5/bounce.0 man-postfix-catman postfix,.cat ./usr/share/man/cat5/canonical.0 man-postfix-catman postfix,.cat ./usr/share/man/cat5/ccd.conf.0 man-sysutil-catman .cat +./usr/share/man/cat5/cdb.0 man-sys-catman .cat ./usr/share/man/cat5/cidr_table.0 man-postfix-catman postfix,.cat ./usr/share/man/cat5/core.0 man-sys-catman .cat ./usr/share/man/cat5/crontab.0 man-cron-catman .cat @@ -4312,6 +4313,7 @@ ./usr/share/man/html5/bounce.html man-postfix-htmlman postfix,html ./usr/share/man/html5/canonical.html man-postfix-htmlman postfix,html ./usr/share/man/html5/ccd.conf.html man-sysutil-htmlman html +./usr/share/man/html5/cdb.html man-sys-htmlman html ./usr/share/man/html5/cidr_table.html man-postfix-htmlman postfix,html ./usr/share/man/html5/core.html man-sys-htmlman html ./usr/share/man/html5/crontab.html man-cron-htmlman html @@ -6822,6 +6824,7 @@ ./usr/share/man/man5/bounce.5 man-postfix-man postfix,.man ./usr/share/man/man5/canonical.5 man-postfix-man postfix,.man ./usr/share/man/man5/ccd.conf.5 man-sysutil-man .man +./usr/share/man/man5/cdb.5 man-sys-man .man ./usr/share/man/man5/cidr_table.5 man-postfix-man postfix,.man ./usr/share/man/man5/core.5 man-sys-man .man ./usr/share/man/man5/crontab.5 man-cron-man .man Index: include/Makefile =================================================================== RCS file: /home/joerg/repo/netbsd/src/include/Makefile,v retrieving revision 1.131 diff -u -p -r1.131 Makefile --- include/Makefile 28 May 2008 12:28:12 -0000 1.131 +++ include/Makefile 7 Mar 2010 21:23:03 -0000 @@ -8,7 +8,7 @@ NOOBJ= # defined # Missing: mp.h INCS= a.out.h aio.h ar.h assert.h atomic.h \ - bitstring.h bm.h complex.h cpio.h ctype.h \ + bitstring.h bm.h cdbr.h cdbw.h complex.h cpio.h ctype.h \ db.h dirent.h disktab.h dlfcn.h err.h errno.h fmtmsg.h fnmatch.h \ fstab.h fts.h ftw.h getopt.h glob.h grp.h ifaddrs.h iconv.h \ inttypes.h iso646.h kvm.h langinfo.h libgen.h \ Index: include/cdbr.h =================================================================== RCS file: include/cdbr.h diff -N include/cdbr.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ include/cdbr.h 20 Mar 2010 14:48:34 -0000 @@ -0,0 +1,55 @@ +/* $NetBSD$ */ +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Joerg Sonnenberger. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CDBR_H +#define _CDBR_H + +#include +#include +#include + +#define CDBR_DEFAULT 0 + +struct cdbr; + +__BEGIN_DECLS + +struct cdbr *cdbr_open(const char *, int); +int cdbr_get(struct cdbr *, uint32_t, const void **, size_t *); +int cdbr_find(struct cdbr *, const void *, size_t, + const void **, size_t *); +void cdbr_close(struct cdbr *); + +__END_DECLS + +#endif /* _CDBR_H */ Index: include/cdbw.h =================================================================== RCS file: include/cdbw.h diff -N include/cdbw.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ include/cdbw.h 7 Mar 2010 22:58:14 -0000 @@ -0,0 +1,58 @@ +/* $NetBSD$ */ +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Joerg Sonnenberger. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CDBW_H +#define _CDBW_H + +#include +#include +#include + +struct cdbw; + +__BEGIN_DECLS + +struct cdbw *cdbw_open(void); +int cdbw_put(struct cdbw *, const void *, size_t, + const void *, size_t); +int cdbw_put_data(struct cdbw *, const void *, size_t, + uint32_t *); +int cdbw_put_key(struct cdbw *, const void *, size_t, + uint32_t); +int cdbw_output(struct cdbw *, int, const char[16], + uint32_t (*)(void)); +void cdbw_close(struct cdbw *); + +__END_DECLS + +#endif /* _CDBW_H */ Index: include/netdb.h =================================================================== RCS file: /home/joerg/repo/netbsd/src/include/netdb.h,v retrieving revision 1.62 diff -u -p -r1.62 netdb.h --- include/netdb.h 2 Oct 2009 02:45:29 -0000 1.62 +++ include/netdb.h 19 Mar 2010 19:56:06 -0000 @@ -125,6 +125,9 @@ typedef _BSD_SIZE_T_ size_t; #ifndef _PATH_SERVICES #define _PATH_SERVICES "/etc/services" #endif +#ifndef _PATH_SERVICES_CDB +#define _PATH_SERVICES_CDB "/var/db/services.cdb" +#endif #ifndef _PATH_SERVICES_DB #define _PATH_SERVICES_DB "/var/db/services.db" #endif Index: lib/libc/Makefile =================================================================== RCS file: /home/joerg/repo/netbsd/src/lib/libc/Makefile,v retrieving revision 1.140 diff -u -p -r1.140 Makefile --- lib/libc/Makefile 6 Dec 2009 12:56:59 -0000 1.140 +++ lib/libc/Makefile 7 Mar 2010 21:31:52 -0000 @@ -55,6 +55,7 @@ COMPATDIR=${.CURDIR}/compat .include "${.CURDIR}/../../common/lib/libc/Makefile.inc" .include "${.CURDIR}/atomic/Makefile.inc" +.include "${.CURDIR}/cdb/Makefile.inc" .include "${.CURDIR}/db/Makefile.inc" .include "${.CURDIR}/citrus/Makefile.inc" .include "${.CURDIR}/compat-43/Makefile.inc" Index: lib/libc/shlib_version =================================================================== RCS file: /home/joerg/repo/netbsd/src/lib/libc/shlib_version,v retrieving revision 1.215 diff -u -p -r1.215 shlib_version --- lib/libc/shlib_version 2 Oct 2009 02:45:29 -0000 1.215 +++ lib/libc/shlib_version 7 Mar 2010 22:30:32 -0000 @@ -35,4 +35,4 @@ # it's insufficient bitwidth to implement all ctype class. # see isblank's comment in ctype.h. major=12 -minor=171 +minor=172 Index: lib/libc/cdb/Makefile.inc =================================================================== RCS file: lib/libc/cdb/Makefile.inc diff -N lib/libc/cdb/Makefile.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/cdb/Makefile.inc 19 Mar 2010 18:46:09 -0000 @@ -0,0 +1,20 @@ +# $NetBSD$ + +# Constant database reader/writer + +.PATH: ${.CURDIR}/cdb + +SRCS+= cdbr.c cdbw.c + +MAN+= cdbr.3 cdbw.3 cdb.5 + +MLINKS+= cdbr.3 cdbr_open.3 +MLINKS+= cdbr.3 cdbr_get.3 +MLINKS+= cdbr.3 cdbr_find.3 +MLINKS+= cdbr.3 cdbr_close.3 +MLINKS+= cdbw.3 cdbw_open.3 +MLINKS+= cdbw.3 cdbw_put.3 +MLINKS+= cdbw.3 cdbw_put_data.3 +MLINKS+= cdbw.3 cdbw_put_key.3 +MLINKS+= cdbw.3 cdbw_output.3 +MLINKS+= cdbw.3 cdbw_close.3 Index: lib/libc/cdb/cdb.5 =================================================================== RCS file: lib/libc/cdb/cdb.5 diff -N lib/libc/cdb/cdb.5 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/cdb/cdb.5 7 Mar 2010 23:03:48 -0000 @@ -0,0 +1,103 @@ +.\" $NetBSD$ +.\" +.\" Copyright (c) 2010 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Joerg Sonnenberger. +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, +.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.Dd March 3, 2010 +.Dt CDB 5 +.Os +.Sh NAME +.Nm cdb +.Nd format of the constant database +.Sh DESCRIPTION +The +.Nm +database format provides a space-efficient (key,value) database. +The format doesn't allow updates in any convient form. +The file overhead is around 5 Byte per key and 5 Byte per entry. +Keys are not stored and it is the responsibility of the using application +to validate matches. +The index structure is based on a minimal perfect hash table, so exactly +one entry has to be checked for match. +.Ss General Format +The header record of a +.Nm +database consists of the following: +.Bd -literal -offset indent +struct header_cdb { + uint8_t magic[7]; + uint8_t version; + uint8_t description[16]; + uint32_t data_size; + uint32_t entries; + uint32_t entries_index; + uint32_t seed; +}; +.Ed +All fields are in Little Endian byte order. +.Pp +This is followed by a description of the hash function of +.Va entries_index +records. +The size of each index entry is the logarithm of +.Va entries +to base 256, rounded up. +.Pp +The index records are followed by the the start offsets of the entries, +followed by +.Va data_size . +The offsets are relative to the end of the offset record table and are +monotically increasing. +The size of each offset record is the logarithm of +.Va data_size +to base 256, rounded up. +.Pp +The offset table is followed by the entries in order. +No separation or padding is added. +.Ss Limitations +The +.Nm +file format is by design intended for a databases that can be +mapped into memory. +The hard limit for the number of entries and keys 3435973836. +The total size of all values must be smaller than 4GiB. +.Sh SEE ALSO +.Xr cdbr 3 , +.Xr cdbw 3 +.Sh HISTORY +Support for the +.Nm cdb +format first appeared in +.Nx 6.0 . +.Sh AUTHORS +The +.Nm cdbr +and +.Nm cdbw +functions have been written by +.An Joerg Sonnenberger Aq joerg@NetBSD.org . Index: lib/libc/cdb/cdbr.3 =================================================================== RCS file: lib/libc/cdb/cdbr.3 diff -N lib/libc/cdb/cdbr.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/cdb/cdbr.3 7 Mar 2010 21:28:01 -0000 @@ -0,0 +1,114 @@ +.\" $NetBSD$ +.\" +.\" Copyright (c) 2010 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Joerg Sonnenberger. +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, +.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.Dd March 3, 2010 +.Dt CDBR 3 +.Os +.Sh NAME +.Nm cdbr +.Nm cdbr_open , +.Nm cdbr_get , +.Nm cdbr_find , +.Nm cdbr_close , +.Nm cdbr_write +.Nd constant database access methods +.Sh SYNOPSIS +.Ft "struct cdbr *" +.Fn cdbr_open "const char *path" "int flags" +.Ft int +.Fn cdbr_get "struct cdbr *cdbr" "uint32_t index" "const void **data" "size_t *datalen" +.Ft int +.Fo cdbr_find +.Fa "struct cdbr *cdbr" +.Fa "const void *key" +.Fa "size_t keylen" +.Fa "const void **data" +.Fa "size_t *datalen" +.Fc +.Ft void +.Fn cdbr_close "struct cdbr *cdbr" +.Sh DESCRIPTION +The +.Nm +library provides a space efficient key,value database based +on perfect hashing. +.Pp +A cdb database is opened for reading by calling +.Fn cdbr_open . +The only supported value for +.Va flags +is +.Dv CDBR_DEFAULT . +The function returns a handle to pass to the other functions. +The database is closed by invoking +.Fn cdbr_close . +All resources associated with the handle are freed and the memory +returned by +.Fn cdbr_get +and +.Fn cdbr_find +is invalidated. +.Pp +Records can be obtained by record number by using +.Fn cdbr_get +or by key using +.Fn cdbr_find . +Both functions return 0 on success and update +.Va data +and +.Va datalen +accordingly. +The location +.Va *data +remains valid until +.Fn cdbr_close +is called. +It is the responsibility of the caller of +.Fn cdbr_find +to ensure, that the key matches the returned data. +The function returns the only possible match, but the database doesn't store +the keys to minimize overhead. +.Sh SEE ALSO +.Xr nbperf 1 , +.Xr db 3 , +.Xr cdbw 3 , +.Xr cdb 5 +.Sh HISTORY +Support for the +.Nm cdb +format first appeared in +.Nx 6.0 . +.Sh AUTHORS +The +.Nm cdbr +and +.Nm cdbw +functions have been written by +.An Joerg Sonnenberger Aq joerg@NetBSD.org . Index: lib/libc/cdb/cdbr.c =================================================================== RCS file: lib/libc/cdb/cdbr.c diff -N lib/libc/cdb/cdbr.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/cdb/cdbr.c 20 Mar 2010 15:04:13 -0000 @@ -0,0 +1,250 @@ +/* $NetBSD$ */ +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Joerg Sonnenberger. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include +__RCSID("$NetBSD$"); + +#include "namespace.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __weak_alias +__weak_alias(cdbr_close,_cdbr_close) +__weak_alias(cdbr_find,_cdbr_find) +__weak_alias(cdbr_get,_cdbr_get) +__weak_alias(cdbr_open,_cdbr_open) +#endif + +struct cdbr { + uint8_t *mmap_base; + size_t mmap_size; + + uint8_t *hash_base; + uint8_t *offset_base; + uint8_t *data_base; + + uint32_t data_size; + uint32_t entries; + uint32_t entries_index; + uint32_t seed; + + uint8_t offset_size; + uint8_t index_size; + + uint32_t entries_m; + uint32_t entries_index_m; + uint8_t entries_s1, entries_s2; + uint8_t entries_index_s1, entries_index_s2; +}; + +struct cdbr * +cdbr_open(const char *path, int flags) +{ + uint8_t buf[40]; + int fd; + struct cdbr *cdbr; + struct stat sb; + + if ((fd = open(path, O_RDONLY)) == -1) + return NULL; + + errno = EINVAL; + if (fstat(fd, &sb) == -1 || + read(fd, buf, sizeof(buf)) != sizeof(buf) || + memcmp(buf, "NBCDB\n\0\001", 8) || + (cdbr = malloc(sizeof(*cdbr))) == NULL) { + close(fd); + return NULL; + } + + cdbr->data_size = le32dec(buf + 24); + cdbr->entries = le32dec(buf + 28); + cdbr->entries_index = le32dec(buf + 32); + cdbr->seed = le32dec(buf + 36); + + if (cdbr->data_size < 0x100) + cdbr->offset_size = 1; + else if (cdbr->data_size < 0x10000) + cdbr->offset_size = 2; + else if (cdbr->data_size < 0x1000000) + cdbr->offset_size = 3; + else + cdbr->offset_size = 4; + + if (cdbr->entries_index < 0x100) + cdbr->index_size = 1; + else if (cdbr->entries_index < 0x10000) + cdbr->index_size = 2; + else if (cdbr->entries_index < 0x1000000) + cdbr->index_size = 3; + else + cdbr->index_size = 4; + + cdbr->mmap_size = sb.st_size; + cdbr->mmap_base = mmap(NULL, cdbr->mmap_size, PROT_READ, MAP_FILE, fd, 0); + close(fd); + + if (cdbr->mmap_base == MAP_FAILED) { + free(cdbr); + return NULL; + } + + cdbr->hash_base = cdbr->mmap_base + 40; + cdbr->offset_base = cdbr->hash_base + cdbr->entries_index * cdbr->index_size; + cdbr->data_base = cdbr->offset_base + (cdbr->entries + 1) * cdbr->offset_size; + + if (cdbr->hash_base < cdbr->mmap_base || + cdbr->offset_base < cdbr->mmap_base || + cdbr->data_base < cdbr->mmap_base || + cdbr->data_base + cdbr->data_size < cdbr->mmap_base || + cdbr->data_base + cdbr->data_size > + cdbr->mmap_base + cdbr->mmap_size || + cdbr->entries == 0 || cdbr->entries_index == 0) { + errno = EINVAL; + cdbr_close(cdbr); + return NULL; + } + + fast_divide32_prepare(cdbr->entries, &cdbr->entries_m, + &cdbr->entries_s1, &cdbr->entries_s2); + fast_divide32_prepare(cdbr->entries_index, &cdbr->entries_index_m, + &cdbr->entries_index_s1, &cdbr->entries_index_s2); + + return cdbr; +} + +static uint32_t +get_uintX(const uint8_t *addr, uint32_t idx, int size) +{ + uint32_t val; + + addr += idx * size; + + val = 0; + switch (size) { + case 4: + val |= addr[3] << 24; + /* FALLTHROUGH */ + case 3: + val |= addr[2] << 16; + /* FALLTHROUGH */ + case 2: + val |= addr[1] << 8; + /* FALLTHROUGH */ + case 1: + val |= addr[0]; + } + return val; +} + +int +cdbr_get(struct cdbr *cdbr, uint32_t idx, const void **data, size_t *data_len) +{ + uint32_t start, end; + + if (idx >= cdbr->entries) { + errno = EINVAL; + return -1; + } + + start = get_uintX(cdbr->offset_base, idx, cdbr->offset_size); + end = get_uintX(cdbr->offset_base, idx + 1, cdbr->offset_size); + + if (start > end) { + errno = EIO; + return -1; + } + + if (end > cdbr->data_size) { + errno = EIO; + return -1; + } + + *data = cdbr->data_base + start; + *data_len = end - start; + + return 0; +} + +int +cdbr_find(struct cdbr *cdbr, const void *key, size_t key_len, + const void **data, size_t *data_len) +{ + uint32_t hashes[3], idx; + + if (cdbr->entries_index == 0) { + errno = EINVAL; + return -1; + } + + mi_vector_hash(key, key_len, cdbr->seed, hashes); + + hashes[0] = fast_remainder32(hashes[0], cdbr->entries_index, + cdbr->entries_index_m, cdbr->entries_index_s1, + cdbr->entries_index_s2); + hashes[1] = fast_remainder32(hashes[1], cdbr->entries_index, + cdbr->entries_index_m, cdbr->entries_index_s1, + cdbr->entries_index_s2); + hashes[2] = fast_remainder32(hashes[2], cdbr->entries_index, + cdbr->entries_index_m, cdbr->entries_index_s1, + cdbr->entries_index_s2); + + idx = get_uintX(cdbr->hash_base, hashes[0], cdbr->index_size); + idx += get_uintX(cdbr->hash_base, hashes[1], cdbr->index_size); + idx += get_uintX(cdbr->hash_base, hashes[2], cdbr->index_size); + + return cdbr_get(cdbr, fast_remainder32(idx, cdbr->entries, + cdbr->entries_m, cdbr->entries_s1, cdbr->entries_s2), data, + data_len); +} + +void +cdbr_close(struct cdbr *cdbr) +{ + munmap(cdbr->mmap_base, cdbr->mmap_size); + free(cdbr); +} Index: lib/libc/cdb/cdbw.3 =================================================================== RCS file: lib/libc/cdb/cdbw.3 diff -N lib/libc/cdb/cdbw.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/cdb/cdbw.3 7 Mar 2010 23:10:54 -0000 @@ -0,0 +1,130 @@ +.\" $NetBSD$ +.\" +.\" Copyright (c) 2010 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Joerg Sonnenberger. +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, +.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.Dd March 3, 2010 +.Dt CDB 3 +.Os +.Sh NAME +.Nm cdbw_open , +.Nm cdbw_put , +.Nm cdbw_put_data , +.Nm cdbw_put_key , +.Nm cdbw_close +.Nd create constant databases +.Sh SYNOPSIS +.In archive_entry.h +.Ft "struct cdbw *" +.Fn cdbw_open "void" +.Ft int +.Fo cdbw_put +.Fa "struct cdbw *cdbw" +.Fa "const void *key" +.Fa "size_t keylen" +.Fa "const void *data" +.Fa "size_t datalen" +.Fc +.Ft int +.Fo cdbw_put_data +.Fa "struct cdbw *cdbw" +.Fa "const void *data" +.Fa "size_t datalen" +.Fa "uint32_t *index" +.Fc +.Ft int +.Fo cdbw_put_key +.Fa "struct cdbw *cdbw" +.Fa "const void *key" +.Fa "size_t keylen" +.Fa "uint32_t index" +.Fc +.Ft int +.Fo cdbw_output +.Fa "struct cdbw *cdbw" +.Fa "int output" +.Fa "const char descr[16]" +.Fa "uint32_t (*seedgen)(void)" +.Fc +.Ft void +.Fn cdbw_close "struct cdbw *cdbw" +.Sh DESCRIPTION +The +.Nm cdbw +funcations are used to create a constant databases for use with +.Xr cdbr 5 . +Details about the file format, including overhead and limitations, +can be found in +.Xr cdb 5 . +.Pp +.Fn cdbw_open +prepares a new +.Nm cdb +writer. +The function returns a handle to pass to the other functions. +.Pp +.Fn cdbw_close +frees all resources associated with the handle. +.Pp +.Fn cdbw_put +adds the given key,value pair after checking for a duplicate key. +.Fn cdbw_put_data +adds the given value to the writer without adding a key reference. +The returned index can be used in subsequent calls to +.Fn cdbw_put_key +to add one or more keys pointing to this value. +.Fn cdbw_put_key +checks for duplicate keys and valid index arguments. +On success it adds the given key. +.Pp +.Fn cdbw_output +computes the database file and writes it to the given descriptor. +The function returns an error, if the file cannot be written correctly. +The +.Fn descr +parameter provides a human readable description of the database content. +The +.Fn seedgen +parameter can be used to override the default PRNG. +The function should return a different value for each invokation. +The bitwise layout of the output depends on the choosen seed. +.Sh SEE ALSO +.Xr cdbr 3 , +.Xr cdb 5 +.Sh HISTORY +Support for the +.Nm cdb +format first appeared in +.Nx 6.0 . +.Sh AUTHORS +The +.Nm cdbr +and +.Nm cdbw +functions have been written by +.An Joerg Sonnenberger Aq joerg@NetBSD.org . Index: lib/libc/cdb/cdbw.c =================================================================== RCS file: lib/libc/cdb/cdbw.c diff -N lib/libc/cdb/cdbw.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/cdb/cdbw.c 19 Mar 2010 18:44:37 -0000 @@ -0,0 +1,593 @@ +/* $NetBSD$ */ +/*- + * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Joerg Sonnenberger. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include +__RCSID("$NetBSD$"); + +#include "namespace.h" + +#include +#include +#include +#include +#include +#include + +#ifdef __weak_alias +__weak_alias(cdbw_close,_cdbw_close) +__weak_alias(cdbw_open,_cdbw_open) +__weak_alias(cdbw_output,_cdbw_output) +__weak_alias(cdbw_put,_cdbw_put) +__weak_alias(cdbw_put_data,_cdbw_put_data) +__weak_alias(cdbw_put_key,_cdbw_put_key) +#endif + +struct key_hash { + SLIST_ENTRY(key_hash) link; + uint32_t hashes[3]; + uint32_t idx; + void *key; + size_t keylen; +}; + +SLIST_HEAD(key_hash_head, key_hash); + +struct cdbw { + size_t data_counter; + size_t data_allocated; + size_t data_size; + size_t *data_len; + void **data_ptr; + + size_t hash_size; + struct key_hash_head *hash; + size_t key_counter; +}; + + /* Max. data counter that allows the index size to be 32bit. */ +static const uint32_t max_data_counter = 0xccccccccU; + +struct cdbw * +cdbw_open(void) +{ + struct cdbw *cdbw; + size_t i; + + cdbw = calloc(sizeof(*cdbw), 1); + if (cdbw == NULL) + return NULL; + + cdbw->hash_size = 1024; + cdbw->hash = calloc(cdbw->hash_size, sizeof(*cdbw->hash)); + if (cdbw->hash == NULL) { + free(cdbw); + return NULL; + } + + for (i = 0; i < cdbw->hash_size; ++i) + SLIST_INIT(cdbw->hash + i); + + return cdbw; +} + +int +cdbw_put(struct cdbw *cdbw, const void *key, size_t keylen, + const void *data, size_t datalen) +{ + uint32_t idx; + int rv; + + rv = cdbw_put_data(cdbw, data, datalen, &idx); + if (rv) + return rv; + rv = cdbw_put_key(cdbw, key, keylen, idx); + if (rv) { + --cdbw->data_counter; + free(cdbw->data_ptr[cdbw->data_counter]); + cdbw->data_size -= datalen; + return rv; + } + return 0; +} + +int +cdbw_put_data(struct cdbw *cdbw, const void *data, size_t datalen, + uint32_t *idx) +{ + + if (cdbw->data_counter == max_data_counter) + return -1; + + if (cdbw->data_size + datalen < cdbw->data_size || + cdbw->data_size + datalen > 0xffffffffU) + return -1; /* Overflow */ + + if (cdbw->data_allocated == cdbw->data_counter) { + void **new_data_ptr; + size_t *new_data_len; + size_t new_allocated; + + if (cdbw->data_allocated == 0) + new_allocated = 256; + else + new_allocated = cdbw->data_allocated * 2; + + new_data_ptr = realloc(cdbw->data_ptr, + sizeof(*cdbw->data_ptr) * new_allocated); + if (new_data_ptr == NULL) + return -1; + cdbw->data_ptr = new_data_ptr; + + new_data_len = realloc(cdbw->data_len, + sizeof(*cdbw->data_len) * new_allocated); + if (new_data_len == NULL) + return -1; + cdbw->data_len = new_data_len; + + cdbw->data_allocated = new_allocated; + } + + cdbw->data_ptr[cdbw->data_counter] = malloc(datalen); + if (cdbw->data_ptr[cdbw->data_counter] == NULL) + return -1; + memcpy(cdbw->data_ptr[cdbw->data_counter], data, datalen); + cdbw->data_len[cdbw->data_counter] = datalen; + cdbw->data_size += datalen; + *idx = cdbw->data_counter++; + return 0; +} + +int +cdbw_put_key(struct cdbw *cdbw, const void *key, size_t keylen, uint32_t idx) +{ + uint32_t hashes[3]; + struct key_hash_head *head, *head2, *new_head; + struct key_hash *key_hash; + size_t new_hash_size, i; + + if (idx >= cdbw->data_counter || + cdbw->key_counter == max_data_counter) + return -1; + + mi_vector_hash(key, keylen, 0, hashes); + + head = cdbw->hash + (hashes[0] & (cdbw->hash_size - 1)); + SLIST_FOREACH(key_hash, head, link) { + if (key_hash->keylen != keylen) + continue; + if (key_hash->hashes[0] != hashes[0]) + continue; + if (key_hash->hashes[1] != hashes[1]) + continue; + if (key_hash->hashes[2] != hashes[2]) + continue; + if (memcmp(key, key_hash->key, keylen)) + continue; + return -1; + } + key_hash = malloc(sizeof(*key_hash)); + if (key_hash == NULL) + return -1; + key_hash->key = malloc(keylen); + if (key_hash->key == NULL) { + free(key_hash); + return -1; + } + memcpy(key_hash->key, key, keylen); + key_hash->hashes[0] = hashes[0]; + key_hash->hashes[1] = hashes[1]; + key_hash->hashes[2] = hashes[2]; + key_hash->keylen = keylen; + key_hash->idx = idx; + SLIST_INSERT_HEAD(head, key_hash, link); + ++cdbw->key_counter; + + if (cdbw->key_counter <= cdbw->hash_size) + return 0; + + /* Try to resize the hash table, but ignore errors. */ + new_hash_size = cdbw->hash_size * 2; + new_head = calloc(sizeof(*new_head), new_hash_size); + if (new_head == NULL) + return 0; + + head = &cdbw->hash[hashes[0] & (cdbw->hash_size - 1)]; + for (i = 0; i < new_hash_size; ++i) + SLIST_INIT(new_head + i); + + for (i = 0; i < cdbw->hash_size; ++i) { + head = cdbw->hash + i; + + while ((key_hash = SLIST_FIRST(head)) != NULL) { + SLIST_REMOVE_HEAD(head, link); + head2 = new_head + + (key_hash->hashes[0] & (new_hash_size - 1)); + SLIST_INSERT_HEAD(head2, key_hash, link); + } + } + free(cdbw->hash); + cdbw->hash_size = new_hash_size; + cdbw->hash = new_head; + + return 0; +} + +void +cdbw_close(struct cdbw *cdbw) +{ + struct key_hash_head *head; + struct key_hash *key_hash; + size_t i; + + for (i = 0; i < cdbw->hash_size; ++i) { + head = cdbw->hash + i; + while ((key_hash = SLIST_FIRST(head)) != NULL) { + SLIST_REMOVE_HEAD(head, link); + free(key_hash->key); + free(key_hash); + } + } + + for (i = 0; i < cdbw->data_counter; ++i) + free(cdbw->data_ptr[i]); + free(cdbw->data_ptr); + free(cdbw->data_len); + free(cdbw->hash); + free(cdbw); +} + +#define unused 0xffffffffU + +struct vertex { + uint32_t l_edge, m_edge, r_edge; +}; + +struct edge { + uint32_t idx; + + uint32_t left, middle, right; + uint32_t l_prev, m_prev, l_next; + uint32_t r_prev, m_next, r_next; +}; + +struct state { + uint32_t data_entries; + uint32_t entries; + uint32_t keys; + uint32_t seed; + + uint32_t *g; + char *visited; + + struct vertex *verts; + struct edge *edges; + uint32_t output_index; + uint32_t *output_order; +}; + +static void +remove_vertex(struct state *state, struct vertex *v) +{ + struct edge *e; + struct vertex *vl, *vm, *vr; + + if (v->l_edge != unused && v->m_edge != unused) + return; + if (v->l_edge != unused && v->r_edge != unused) + return; + if (v->m_edge != unused && v->r_edge != unused) + return; + if (v->l_edge == unused && v->m_edge == unused && v->r_edge == unused) + return; + + if (v->l_edge != unused) { + e = &state->edges[v->l_edge]; + if (e->l_next != unused) + return; + } else if (v->m_edge != unused) { + e = &state->edges[v->m_edge]; + if (e->m_next != unused) + return; + } else { + if (v->r_edge == unused) + abort(); + e = &state->edges[v->r_edge]; + if (e->r_next != unused) + return; + } + + state->output_order[--state->output_index] = e - state->edges; + + vl = &state->verts[e->left]; + vm = &state->verts[e->middle]; + vr = &state->verts[e->right]; + + if (e->l_prev == unused) + vl->l_edge = e->l_next; + else + state->edges[e->l_prev].l_next = e->l_next; + if (e->l_next != unused) + state->edges[e->l_next].l_prev = e->l_prev; + + if (e->m_prev == unused) + vm->m_edge = e->m_next; + else + state->edges[e->m_prev].m_next = e->m_next; + if (e->m_next != unused) + state->edges[e->m_next].m_prev = e->m_prev; + + if (e->r_prev == unused) + vr->r_edge = e->r_next; + else + state->edges[e->r_prev].r_next = e->r_next; + if (e->r_next != unused) + state->edges[e->r_next].r_prev = e->r_prev; +} + +static int +build_graph(struct cdbw *cdbw, struct state *state) +{ + struct key_hash_head *head; + struct key_hash *key_hash; + struct vertex *v; + struct edge *e; + uint32_t hashes[3]; + size_t i; + + e = state->edges; + for (i = 0; i < cdbw->hash_size; ++i) { + head = &cdbw->hash[i]; + SLIST_FOREACH(key_hash, head, link) { + e->idx = key_hash->idx; + mi_vector_hash(key_hash->key, key_hash->keylen, + state->seed, hashes); + e->left = hashes[0] % state->entries; + e->middle = hashes[1] % state->entries; + e->right = hashes[2] % state->entries; + + ++e; + } + } + + for (i = 0; i < state->entries; ++i) { + v = state->verts + i; + v->l_edge = unused; + v->m_edge = unused; + v->r_edge = unused; + } + + for (i = 0; i < state->keys; ++i) { + e = state->edges + i; + v = state->verts + e->left; + if (v->l_edge != unused) + state->edges[v->l_edge].l_prev = i; + e->l_next = v->l_edge; + e->l_prev = unused; + v->l_edge = i; + + v = &state->verts[e->middle]; + if (v->m_edge != unused) + state->edges[v->m_edge].m_prev = i; + e->m_next = v->m_edge; + e->m_prev = unused; + v->m_edge = i; + + v = &state->verts[e->right]; + if (v->r_edge != unused) + state->edges[v->r_edge].r_prev = i; + e->r_next = v->r_edge; + e->r_prev = unused; + v->r_edge = i; + } + + state->output_index = state->keys; + for (i = 0; i < state->entries; ++i) + remove_vertex(state, state->verts + i); + + i = state->keys; + while (i > 0 && i > state->output_index) { + --i; + e = state->edges + state->output_order[i]; + remove_vertex(state, state->verts + e->left); + remove_vertex(state, state->verts + e->middle); + remove_vertex(state, state->verts + e->right); + } + + return state->output_index == 0 ? 0 : -1; +} + +static void +assign_nodes(struct state *state) +{ + struct edge *e; + size_t i; + + for (i = 0; i < state->keys; ++i) { + e = state->edges + state->output_order[i]; + + if (!state->visited[e->left]) { + state->g[e->left] = + (2 * state->data_entries + e->idx + - state->g[e->middle] - state->g[e->right]) + % state->data_entries; + } else if (!state->visited[e->middle]) { + state->g[e->middle] = + (2 * state->data_entries + e->idx + - state->g[e->left] - state->g[e->right]) + % state->data_entries; + } else { + state->g[e->right] = + (2 * state->data_entries + e->idx + - state->g[e->left] - state->g[e->middle]) + % state->data_entries; + } + state->visited[e->left] = 1; + state->visited[e->middle] = 1; + state->visited[e->right] = 1; + } +} + +static size_t +compute_size(uint32_t size) +{ + if (size < 0x100) + return 1; + if (size < 0x10000) + return 2; + if (size < 0x1000000) + return 3; + return 4; +} + +#define COND_FLUSH_BUFFER(n) do { \ + if (__predict_false(cur_pos + (n) >= sizeof(buf))) { \ + ret = write(fd, buf, cur_pos); \ + if (ret == -1 || (size_t)ret != cur_pos) \ + return -1; \ + cur_pos = 0; \ + } \ +} while (/* CONDCOND */ 0) + +static int +print_hash(struct cdbw *cdbw, struct state *state, int fd, const char *descr) +{ + uint32_t data_size; + uint8_t buf[90000]; + size_t i, size, cur_pos; + ssize_t ret; + + memcpy(buf, "NBCDB\n\0", 7); + buf[7] = 1; + strncpy((char *)buf + 8, descr, 16); + le32enc(buf + 24, cdbw->data_size); + le32enc(buf + 28, cdbw->data_counter); + le32enc(buf + 32, state->entries); + le32enc(buf + 36, state->seed); + cur_pos = 40; + + size = compute_size(state->entries); + for (i = 0; i < state->entries; ++i) { + COND_FLUSH_BUFFER(4); + le32enc(buf + cur_pos, state->g[i]); + cur_pos += size; + } + size = compute_size(cdbw->data_size); + for (data_size = 0, i = 0; i < cdbw->data_counter; ++i) { + COND_FLUSH_BUFFER(4); + le32enc(buf + cur_pos, data_size); + cur_pos += size; + data_size += cdbw->data_len[i]; + } + COND_FLUSH_BUFFER(4); + le32enc(buf + cur_pos, data_size); + cur_pos += size; + + for (i = 0; i < cdbw->data_counter; ++i) { + COND_FLUSH_BUFFER(cdbw->data_len[i]); + if (cdbw->data_len[i] < sizeof(buf)) { + memcpy(buf + cur_pos, cdbw->data_ptr[i], + cdbw->data_len[i]); + cur_pos += cdbw->data_len[i]; + } else { + ret = write(fd, cdbw->data_ptr[i], cdbw->data_len[i]); + if (ret == -1 || (size_t)ret != cdbw->data_len[i]) + return -1; + } + } + if (cur_pos != 0) { + ret = write(fd, buf, cur_pos); + if (ret == -1 || (size_t)ret != cur_pos) + return -1; + } + return 0; +} + +int +cdbw_output(struct cdbw *cdbw, int fd, const char descr[16], + uint32_t (*seedgen)(void)) +{ + struct state state; + int rv; + + if (cdbw->data_counter == 0 || cdbw->key_counter == 0) { + state.entries = 0; + state.seed = 0; + print_hash(cdbw, &state, fd, descr); + return 0; + } + + if (seedgen == NULL) + seedgen = arc4random; + + rv = 0; + + state.keys = cdbw->key_counter; + state.data_entries = cdbw->data_counter; + state.entries = state.keys + (state.keys + 3) / 4; + if (state.entries < 10) + state.entries = 10; + +#define NALLOC(var, n) var = calloc(sizeof(*var), n) + NALLOC(state.g, state.entries); + NALLOC(state.visited, state.entries); + NALLOC(state.verts, state.entries); + NALLOC(state.edges, state.entries); + NALLOC(state.output_order, state.keys); +#undef NALLOC + + if (state.g == NULL || state.visited == NULL || state.verts == NULL || + state.edges == NULL || state.output_order == NULL) { + rv = -1; + goto release; + } + + do { + state.seed = (*seedgen)(); + } while (build_graph(cdbw, &state)); + + assign_nodes(&state); + rv = print_hash(cdbw, &state, fd, descr); + +release: + free(state.g); + free(state.visited); + free(state.verts); + free(state.edges); + free(state.output_order); + + return rv; +} Index: lib/libc/include/namespace.h =================================================================== RCS file: /home/joerg/repo/netbsd/src/lib/libc/include/namespace.h,v retrieving revision 1.141 diff -u -p -r1.141 namespace.h --- lib/libc/include/namespace.h 19 Mar 2010 18:11:30 -0000 1.141 +++ lib/libc/include/namespace.h 19 Mar 2010 18:11:44 -0000 @@ -167,6 +167,16 @@ #define bm_exec _bm_exec #define bm_free _bm_free #define callrpc _callrpc +#define cdbr_close _cdbr_close +#define cdbr_find _cdbr_find +#define cdbr_get _cdbr_get +#define cdbr_open _cdbr_open +#define cdbw_close _cdbw_close +#define cdbw_open _cdbw_open +#define cdbw_put _cdbw_put +#define cdbw_put_data _cdbw_put_data +#define cdbw_put_key _cdbw_put_key +#define cdbw_output _cdbw_output #define cfgetispeed _cfgetispeed #define cfgetospeed _cfgetospeed #define cfmakeraw _cfmakeraw Index: lib/libc/net/getservbyname_r.c =================================================================== RCS file: /home/joerg/repo/netbsd/src/lib/libc/net/getservbyname_r.c,v retrieving revision 1.6 diff -u -p -r1.6 getservbyname_r.c --- lib/libc/net/getservbyname_r.c 21 Mar 2007 02:35:39 -0000 1.6 +++ lib/libc/net/getservbyname_r.c 9 Mar 2010 03:02:44 -0000 @@ -40,10 +40,10 @@ __RCSID("$NetBSD: getservbyname_r.c,v 1. #include "namespace.h" #include +#include #include #include #include -#include #include "servent.h" @@ -55,33 +55,62 @@ static struct servent * _servent_getbyname(struct servent_data *sd, struct servent *sp, const char *name, const char *proto) { - if (sd->db == NULL) + + if ((sd->flags & (_SV_CDB | _SV_PLAINFILE)) == 0) return NULL; - if (sd->flags & _SV_DB) { - char buf[BUFSIZ]; - DBT key, data; - DB *db = sd->db; - key.data = buf; + if (sd->flags & _SV_CDB) { + uint8_t buf[255 * 2 + 2]; + size_t namelen, protolen; + const uint8_t *data, *data_end; + const void *data_ptr; + size_t datalen; - if (proto == NULL) - key.size = snprintf(buf, sizeof(buf), "\376%s", name); - else - key.size = snprintf(buf, sizeof(buf), "\376%s/%s", - name, proto); - key.size++; - - if ((*db->get)(db, &key, &data, 0) != 0) + namelen = strlen(name); + if (namelen == 0 || namelen > 255) + return NULL; + if (proto != NULL && *proto == '\0') return NULL; + if (proto != NULL) + protolen = strlen(proto); + else + protolen = 0; + + buf[0] = namelen; + buf[1] = protolen; + memcpy(buf + 2, name, namelen); + memcpy(buf + 2 + namelen, proto, protolen); - if ((*db->get)(db, &data, &key, 0) != 0) + if (cdbr_find(sd->cdb, buf, 2 + namelen + protolen, + &data_ptr, &datalen)) return NULL; - if (sd->line) - free(sd->line); + if (datalen < namelen + protolen + 6) + return NULL; - sd->line = strdup(key.data); - return _servent_parseline(sd, sp); + data = data_ptr; + data_end = data + datalen; + if (protolen) { + if (data[2] != protolen) + return NULL; + if (memcmp(data + 3, proto, protolen + 1)) + return NULL; + } + data += 3 + data[2] + 1; + if (data > data_end) + return NULL; + while (data != data_end) { + if (*data == '\0') + return NULL; + if (data + data[0] + 2 > data_end) + return NULL; + if (data[0] == namelen && + memcmp(data + 1, name, namelen + 1) == 0) + return _servent_parsedb(sd, sp, data_ptr, + datalen); + data += data[0] + 2; + } + return NULL; } else { while (_servent_getline(sd) != -1) { char **cp; Index: lib/libc/net/getservbyport_r.c =================================================================== RCS file: /home/joerg/repo/netbsd/src/lib/libc/net/getservbyport_r.c,v retrieving revision 1.6 diff -u -p -r1.6 getservbyport_r.c --- lib/libc/net/getservbyport_r.c 21 Mar 2007 02:35:39 -0000 1.6 +++ lib/libc/net/getservbyport_r.c 9 Mar 2010 02:57:46 -0000 @@ -39,11 +39,10 @@ __RCSID("$NetBSD: getservbyport_r.c,v 1. #endif /* LIBC_SCCS and not lint */ #include "namespace.h" -#include +#include #include #include #include -#include #include "servent.h" @@ -55,34 +54,51 @@ static struct servent * _servent_getbyport(struct servent_data *sd, struct servent *sp, int port, const char *proto) { - if (sd->db == NULL) + + if ((sd->flags & (_SV_CDB | _SV_PLAINFILE)) == 0) return NULL; - if (sd->flags & _SV_DB) { - char buf[BUFSIZ]; - DBT key, data; - DB *db = sd->db; - key.data = buf; - - port = htons(port); - if (proto == NULL) - key.size = snprintf(buf, sizeof(buf), "\377%d", port); + if (sd->flags & _SV_CDB) { + uint8_t buf[255 + 4]; + size_t protolen; + const uint8_t *data, *data_end; + const void *data_ptr; + size_t datalen; + + port = be16toh(port); + + if (proto != NULL && *proto == '\0') + return NULL; + if (proto != NULL) + protolen = strlen(proto); else - key.size = snprintf(buf, sizeof(buf), "\377%d/%s", port, - proto); - key.size++; - - if ((*db->get)(db, &key, &data, 0) != 0) + protolen = 0; + if (port < 0 || port > 65536) return NULL; - if ((*db->get)(db, &data, &key, 0) != 0) + buf[0] = 0; + buf[1] = protolen; + be16enc(buf + 2, port); + memcpy(buf + 4, proto, protolen); + + if (cdbr_find(sd->cdb, buf, 4 + protolen, + &data_ptr, &datalen)) return NULL; - if (sd->line) - free(sd->line); + if (datalen < protolen + 4) + return NULL; - sd->line = strdup(key.data); - return _servent_parseline(sd, sp); + data = data_ptr; + data_end = data + datalen; + if (be16dec(data) != port) + return NULL; + if (protolen) { + if (data[2] != protolen) + return NULL; + if (memcmp(data + 3, proto, protolen + 1)) + return NULL; + } + return _servent_parsedb(sd, sp, data, datalen); } else { while (_servent_getline(sd) != -1) { if (_servent_parseline(sd, sp) == NULL) Index: lib/libc/net/getservent_r.c =================================================================== RCS file: /home/joerg/repo/netbsd/src/lib/libc/net/getservent_r.c,v retrieving revision 1.9 diff -u -p -r1.9 getservent_r.c --- lib/libc/net/getservent_r.c 6 Jan 2008 16:34:18 -0000 1.9 +++ lib/libc/net/getservent_r.c 19 Mar 2010 19:55:59 -0000 @@ -39,13 +39,13 @@ __RCSID("$NetBSD: getservent_r.c,v 1.9 2 #endif /* LIBC_SCCS and not lint */ #include "namespace.h" -#include +#include #include +#include +#include #include -#include #include -#include -#include +#include #include "servent.h" @@ -58,27 +58,48 @@ __weak_alias(setservent_r,_setservent_r) int _servent_open(struct servent_data *sd) { + if (sd->flags & (_SV_CDB | _SV_PLAINFILE)) { + sd->flags |= _SV_FIRST; + return 0; + } + + free(sd->line); + sd->line = NULL; + free(sd->cdb_buf); + sd->cdb_buf = NULL; + sd->cdb_buf_len = 0; + free(sd->aliases); + sd->aliases = NULL; + sd->maxaliases = 0; sd->flags |= _SV_FIRST; - if (sd->db == NULL) { - if ((sd->db = dbopen(_PATH_SERVICES_DB, O_RDONLY, 0, - DB_HASH, NULL)) != NULL) - sd->flags |= _SV_DB; - else - sd->db = fopen(_PATH_SERVICES, "r"); + + sd->cdb = cdbr_open(_PATH_SERVICES_CDB, CDBR_DEFAULT); + if (sd->cdb != NULL) { + sd->flags |= _SV_CDB; + return 0; + } + + sd->plainfile = fopen(_PATH_SERVICES, "r"); + if (sd->plainfile != NULL) { + sd->flags |= _SV_PLAINFILE; + return 0; } - return sd->db ? 0 : -1; + return -1; } void _servent_close(struct servent_data *sd) { - if (sd->db) { - if (sd->flags & _SV_DB) { - DB *db = sd->db; - (*db->close)(db); - } else - (void)fclose((FILE *)sd->db); - sd->db = NULL; + if (sd->flags & _SV_CDB) { + cdbr_close(sd->cdb); + sd->cdb = NULL; + sd->flags &= ~_SV_CDB; + } + + if (sd->flags & _SV_PLAINFILE) { + (void)fclose(sd->plainfile); + sd->plainfile = NULL; + sd->flags &= ~_SV_PLAINFILE; } sd->flags &= ~_SV_STAYOPEN; } @@ -87,42 +108,25 @@ _servent_close(struct servent_data *sd) int _servent_getline(struct servent_data *sd) { - if (sd->line) { - free(sd->line); - sd->line = NULL; - } - if (sd->db == NULL) + if (sd->flags & _SV_CDB) return -1; - if (sd->flags & _SV_DB) { - DB *db = sd->db; - DBT key, data; - u_int flags = (sd->flags & _SV_FIRST) ? R_FIRST : R_NEXT; - - while ((*db->seq)(db, &key, &data, flags) == 0) { - flags = R_NEXT; - switch (((u_char *)key.data)[0]) { - case (u_char)'\377': - case (u_char)'\376': - continue; - default: - break; - } - sd->line = strdup(data.data); - break; - } - } else { - if (sd->flags & _SV_FIRST) - (void)rewind((FILE *)sd->db); - sd->line = fparseln((FILE *)sd->db, NULL, NULL, NULL, - FPARSELN_UNESCALL); + if ((sd->flags & _SV_PLAINFILE) == 0) + return -1; + + free(sd->line); + sd->line = NULL; + + if (sd->flags & _SV_FIRST) { + (void)rewind((FILE *)sd->plainfile); + sd->flags &= ~_SV_FIRST; } - sd->flags &= ~_SV_FIRST; + sd->line = fparseln(sd->plainfile, NULL, NULL, NULL, + FPARSELN_UNESCALL); return sd->line == NULL ? -1 : 0; } - struct servent * _servent_parseline(struct servent_data *sd, struct servent *sp) { @@ -148,7 +152,7 @@ _servent_parseline(struct servent_data * sp->s_proto = cp; if (sd->aliases == NULL) { sd->maxaliases = 10; - sd->aliases = malloc(sd->maxaliases * sizeof(char *)); + sd->aliases = calloc(sd->maxaliases, sizeof(*sd->aliases)); if (sd->aliases == NULL) { oerrno = errno; endservent_r(sd); @@ -156,7 +160,7 @@ _servent_parseline(struct servent_data * return NULL; } } - q = sp->s_aliases = sd->aliases; + sp->s_aliases = sd->aliases; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; @@ -167,8 +171,7 @@ _servent_parseline(struct servent_data * } if (i == sd->maxaliases - 2) { sd->maxaliases *= 2; - q = realloc(q, - sd->maxaliases * sizeof(char *)); + q = realloc(sd->aliases, sd->maxaliases * sizeof(*q)); if (q == NULL) { oerrno = errno; endservent_r(sd); @@ -177,12 +180,12 @@ _servent_parseline(struct servent_data * } sp->s_aliases = sd->aliases = q; } - q[i++] = cp; + sp->s_aliases[i++] = cp; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; } - q[i] = NULL; + sp->s_aliases[i] = NULL; return sp; } @@ -197,28 +200,124 @@ void endservent_r(struct servent_data *sd) { _servent_close(sd); - if (sd->aliases) { - free(sd->aliases); - sd->aliases = NULL; - sd->maxaliases = 0; - } - if (sd->line) { - free(sd->line); - sd->line = NULL; - } + free(sd->aliases); + sd->aliases = NULL; + sd->maxaliases = 0; + free(sd->line); + sd->line = NULL; + free(sd->cdb_buf); + sd->cdb_buf = NULL; + sd->cdb_buf_len = 0; } struct servent * getservent_r(struct servent *sp, struct servent_data *sd) { - if (sd->db == NULL && _servent_open(sd) == -1) + + if ((sd->flags & (_SV_CDB | _SV_PLAINFILE)) == 0 && + _servent_open(sd) == -1) return NULL; - for (;;) { - if (_servent_getline(sd) == -1) + if (sd->flags & _SV_CDB) { + const void *data; + size_t len; + + if (sd->flags & _SV_FIRST) { + sd->cdb_index = 0; + sd->flags &= ~_SV_FIRST; + } + + if (cdbr_get(sd->cdb, sd->cdb_index, &data, &len)) return NULL; - if (_servent_parseline(sd, sp) == NULL) - continue; - return sp; + ++sd->cdb_index; + return _servent_parsedb(sd, sp, data, len); } + if (sd->flags & _SV_PLAINFILE) { + for (;;) { + if (_servent_getline(sd) == -1) + return NULL; + if (_servent_parseline(sd, sp) == NULL) + continue; + return sp; + } + } + return NULL; +} + +struct servent * +_servent_parsedb(struct servent_data *sd, struct servent *sp, + const uint8_t *data, size_t len) +{ + char **q; + size_t i; + int oerrno; + + if ((sd->flags & _SV_STAYOPEN) == 0) { + if (len > sd->cdb_buf_len) { + void *tmp = realloc(sd->cdb_buf, len); + if (tmp == NULL) + goto fail; + sd->cdb_buf = tmp; + sd->cdb_buf_len = len; + } + memcpy(sd->cdb_buf, data, len); + data = sd->cdb_buf; + } + + if (len < 2) + goto fail; + sp->s_port = data[1] * 256 + data[0]; + data += 2; + len -= 2; + + if (len == 0 || len < (size_t)data[0] + 2) + goto fail; + sp->s_proto = __UNCONST(data + 1); + + if (sp->s_proto[data[0]] != '\0') + goto fail; + + len -= 2 + data[0]; + data += 2 + data[0]; + + if (len == 0) + goto fail; + if (len < (size_t)data[0] + 2) + goto fail; + + sp->s_name = __UNCONST(data + 1); + len -= 2 + data[0]; + data += 2 + data[0]; + + if (sd->aliases == NULL) { + sd->maxaliases = 10; + sd->aliases = malloc(sd->maxaliases * sizeof(char *)); + if (sd->aliases == NULL) + goto fail; + } + sp->s_aliases = sd->aliases; + i = 0; + while (len) { + if (len < (size_t)data[0] + 2) + goto fail; + if (i == sd->maxaliases - 2) { + sd->maxaliases *= 2; + q = realloc(sd->aliases, sd->maxaliases * sizeof(*q)); + if (q == NULL) + goto fail; + sp->s_aliases = sd->aliases = q; + } + sp->s_aliases[i++] = __UNCONST(data + 1); + len -= 2 + data[0]; + data += 2 + data[0]; + } + sp->s_aliases[i] = NULL; + return sp; + +fail: + oerrno = errno; + endservent_r(sd); + errno = oerrno; + return NULL; } + Index: lib/libc/net/servent.h =================================================================== RCS file: /home/joerg/repo/netbsd/src/lib/libc/net/servent.h,v retrieving revision 1.3 diff -u -p -r1.3 servent.h --- lib/libc/net/servent.h 28 Apr 2008 20:23:00 -0000 1.3 +++ lib/libc/net/servent.h 18 Mar 2010 14:36:46 -0000 @@ -32,14 +32,19 @@ #include struct servent_data { - void *db; + FILE *plainfile; + struct cdbr *cdb; struct servent serv; char **aliases; size_t maxaliases; int flags; #define _SV_STAYOPEN 1 -#define _SV_DB 2 -#define _SV_FIRST 4 +#define _SV_CDB 2 +#define _SV_PLAINFILE 4 +#define _SV_FIRST 8 + uint32_t cdb_index; + uint8_t *cdb_buf; + size_t cdb_buf_len; char *line; void *dummy; }; @@ -56,3 +61,5 @@ int _servent_open(struct servent_data *) void _servent_close(struct servent_data *); int _servent_getline(struct servent_data *); struct servent *_servent_parseline(struct servent_data *, struct servent *); +struct servent *_servent_parsedb(struct servent_data *, struct servent *, + const uint8_t *, size_t); Index: usr.sbin/services_mkdb/Makefile =================================================================== RCS file: /home/joerg/repo/netbsd/src/usr.sbin/services_mkdb/Makefile,v retrieving revision 1.6 diff -u -p -r1.6 Makefile --- usr.sbin/services_mkdb/Makefile 22 Apr 2009 15:23:08 -0000 1.6 +++ usr.sbin/services_mkdb/Makefile 19 Mar 2010 19:20:20 -0000 @@ -2,7 +2,7 @@ PROG= services_mkdb MAN= services_mkdb.8 -SRCS= services_mkdb.c uniq.c +SRCS= services_mkdb.c output_cdb.c output_db.c uniq.c LDADD+= -lutil DPADD+= ${LIBUTIL} Index: usr.sbin/services_mkdb/extern.h =================================================================== RCS file: usr.sbin/services_mkdb/extern.h diff -N usr.sbin/services_mkdb/extern.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ usr.sbin/services_mkdb/extern.h 19 Mar 2010 19:48:50 -0000 @@ -0,0 +1,9 @@ +#include + +int cdb_open(const char *); +void cdb_add(StringList *, size_t, const char *, size_t *, int); +int cdb_close(void); +int db_open(const char *); +void db_add(StringList *, size_t, const char *, size_t *, int); +int db_close(void); +void uniq(const char *); Index: usr.sbin/services_mkdb/output_cdb.c =================================================================== RCS file: usr.sbin/services_mkdb/output_cdb.c diff -N usr.sbin/services_mkdb/output_cdb.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ usr.sbin/services_mkdb/output_cdb.c 19 Mar 2010 19:26:58 -0000 @@ -0,0 +1,163 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Joerg Sonnenberger. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "extern.h" + +static struct cdbw *cdbw; +static int cdbw_fd = -1; + +int +cdb_open(const char *tname) +{ + + if ((cdbw = cdbw_open()) == NULL) + return -1; + + if ((cdbw_fd = open(tname, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) { + cdbw_close(cdbw); + cdbw = NULL; + return -1; + } + return 0; +} + +void +cdb_add(StringList *sl, size_t port, const char *proto, size_t *cnt, + int warndup) +{ + uint8_t key[255 * 2 + 2]; + uint8_t *data, *data_iter; + size_t len, protolen, datalen, keylen; + uint32_t idx; + size_t i; + + protolen = strlen(proto); + if (protolen == 0 || protolen > 255) + errx(1, "Invalid protocol ``%s'', entry skipped", proto); + + datalen = 4 + protolen; + for (i = 0; i < sl->sl_cur; ++i) { + len = strlen(sl->sl_str[i]); + if (len == 0 || len > 255) + errx(1, "Service alias ``%s'' invalid", sl->sl_str[i]); + datalen += len + 2; + } + + data = malloc(datalen); + if (data == NULL) + err(1, "malloc failed"); + be16enc(data, port); + data[2] = protolen; + data_iter = data + 3; + memcpy(data_iter, proto, protolen + 1); + data_iter += protolen + 1; + for (i = 0; i < sl->sl_cur; ++i) { + len = strlen(sl->sl_str[i]); + *data_iter++ = len; + memcpy(data_iter, sl->sl_str[i], len + 1); + data_iter += len + 1; + } + + if (cdbw_put_data(cdbw, data, datalen, &idx)) + err(1, "cdbw_put_data failed"); + + free(data); + + key[0] = 0; + key[1] = protolen; + be16enc(key + 2, port); + memcpy(key + 4, proto, protolen); + keylen = 4 + protolen; + if (cdbw_put_key(cdbw, key, keylen, idx) && warndup) + warnx("duplicate service: `%ju/%s'", port, proto); + + key[1] = 0; + keylen = 4; + if (cdbw_put_key(cdbw, key, keylen, idx) && warndup) + warnx("duplicate service: `%ju'", port); + + /* add references for service and all aliases */ + for (i = 0; i < sl->sl_cur; i++) { + len = strlen(sl->sl_str[i]); + key[0] = len; + key[1] = protolen; + memcpy(key + 2, sl->sl_str[i], len); + memcpy(key + 2 + len, proto, protolen); + keylen = 2 + len + protolen; + if (cdbw_put_key(cdbw, key, keylen, idx) && warndup) + warnx("duplicate service: `%s/%s'", sl->sl_str[i], proto); + + key[1] = 0; + keylen = 2 + len; + if (cdbw_put_key(cdbw, key, keylen, idx) && warndup) + warnx("duplicate service: `%s'", sl->sl_str[i]); + } + + sl_free(sl, 1); +} + +int +cdb_close(void) +{ + int rv, serrno; + + rv = 0; + serrno = errno; + + if (cdbw_output(cdbw, cdbw_fd, "services(5)", NULL)) { + rv = -1; + serrno = errno; + } + + cdbw_close(cdbw); + cdbw = NULL; + + if (close(cdbw_fd)) { + if (rv == 0) + serrno = errno; + rv = -1; + } + cdbw_fd = -1; + + errno = serrno; + return rv; +} Index: usr.sbin/services_mkdb/output_db.c =================================================================== RCS file: usr.sbin/services_mkdb/output_db.c diff -N usr.sbin/services_mkdb/output_db.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ usr.sbin/services_mkdb/output_db.c 19 Mar 2010 19:40:11 -0000 @@ -0,0 +1,189 @@ +/* $NetBSD: services_mkdb.c,v 1.14 2008/04/28 20:24:17 martin Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn and Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifndef lint +__RCSID("$NetBSD: services_mkdb.c,v 1.14 2008/04/28 20:24:17 martin Exp $"); +#endif /* not lint */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "extern.h" + +static DB *db; + +static const HASHINFO hinfo = { + .bsize = 256, + .ffactor = 4, + .nelem = 32768, + .cachesize = 1024, + .hash = NULL, + .lorder = 0 +}; + +static void store(DBT *, DBT *, int); +static void killproto(DBT *); +static const char *mkaliases(StringList *, char *, size_t); + +int +db_open(const char *tname) +{ + db = dbopen(tname, O_RDWR | O_CREAT | O_EXCL, + (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), DB_HASH, &hinfo); + + return db != NULL ? 0 : -1; +} + +int +db_close(void) +{ + int rv; + + rv = (db->close)(db); + db = NULL; + + return rv; +} + +void +db_add(StringList *sl, size_t port, const char *proto, size_t *cnt, + int warndup) +{ + size_t i; + char keyb[BUFSIZ], datab[BUFSIZ], abuf[BUFSIZ]; + DBT data, key; + key.data = keyb; + data.data = datab; + + /* key `indirect key', data `full line' */ + data.size = snprintf(datab, sizeof(datab), "%zu", (*cnt)++) + 1; + key.size = snprintf(keyb, sizeof(keyb), "%s %zu/%s %s", + sl->sl_str[0], port, proto, mkaliases(sl, abuf, sizeof(abuf))) + 1; + store(&data, &key, warndup); + + /* key `\377port/proto', data = `indirect key' */ + key.size = snprintf(keyb, sizeof(keyb), "\377%zu/%s", + port, proto) + 1; + store(&key, &data, warndup); + + /* key `\377port', data = `indirect key' */ + killproto(&key); + store(&key, &data, warndup); + + /* add references for service and all aliases */ + for (i = 0; i < sl->sl_cur; i++) { + /* key `\376service/proto', data = `indirect key' */ + key.size = snprintf(keyb, sizeof(keyb), "\376%s/%s", + sl->sl_str[i], proto) + 1; + store(&key, &data, warndup); + + /* key `\376service', data = `indirect key' */ + killproto(&key); + store(&key, &data, warndup); + } + sl_free(sl, 1); +} + +static void +killproto(DBT *key) +{ + char *p, *d = key->data; + + if ((p = strchr(d, '/')) == NULL) + abort(); + *p++ = '\0'; + key->size = p - d; +} + +static void +store(DBT *key, DBT *data, int warndup) +{ +#ifdef DEBUG + int k = key->size - 1; + int d = data->size - 1; + (void)printf("store [%*.*s] [%*.*s]\n", + k, k, (char *)key->data + 1, + d, d, (char *)data->data + 1); +#endif + switch ((db->put)(db, key, data, R_NOOVERWRITE)) { + case 0: + break; + case 1: + if (warndup) + warnx("duplicate service `%s'", + &((char *)key->data)[1]); + break; + case -1: + err(1, "put"); + break; + default: + abort(); + break; + } +} + +static const char * +mkaliases(StringList *sl, char *buf, size_t len) +{ + size_t nc, i, pos; + + buf[0] = 0; + for (i = 1, pos = 0; i < sl->sl_cur; i++) { + nc = strlcpy(buf + pos, sl->sl_str[i], len); + if (nc >= len) + goto out; + pos += nc; + len -= nc; + nc = strlcpy(buf + pos, " ", len); + if (nc >= len) + goto out; + pos += nc; + len -= nc; + } + return buf; +out: + warn("aliases for `%s' truncated", sl->sl_str[0]); + return buf; +} Index: usr.sbin/services_mkdb/services_mkdb.8 =================================================================== RCS file: /home/joerg/repo/netbsd/src/usr.sbin/services_mkdb/services_mkdb.8,v retrieving revision 1.9 diff -u -p -r1.9 services_mkdb.8 --- usr.sbin/services_mkdb/services_mkdb.8 13 May 2009 22:36:39 -0000 1.9 +++ usr.sbin/services_mkdb/services_mkdb.8 19 Mar 2010 22:28:28 -0000 @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd June 23, 2007 +.Dd March 19, 2010 .Dt SERVICES_MKDB 8 .Os .Sh NAME @@ -37,10 +37,11 @@ .Nm .Op Fl q .Op Fl o Ar database -.Op file +.Op Fl V Ar style +.Op Ar file .Nm .Fl u -.Op file +.Op Ar file .Sh DESCRIPTION .Nm creates a @@ -50,7 +51,11 @@ If no file is specified, then .Pa /etc/services is used. The database is installed into -.Pa /var/db/services.db . +.Pa /var/db/services.cdb +for CDB format and into +.Pa /var/db/services.db +for DB format (see +.Fl V ) . The file must be in the correct format (see .Xr services 5 ) . .Pp @@ -62,6 +67,16 @@ Put the output databases in the named fi Don't warn about duplicate services. .It Fl u Print the services file to stdout, omitting duplicate entries and comments. +.It Fl V +Create a specific version of the database style. +.Ar style +can be +.Li cdb +to request the CDB format (default) or +.Li db +to request the DB format. +The DB format is useful for compatibility with old statically +linked binaries. .El .Pp The databases are used by the C library services routines (see Index: usr.sbin/services_mkdb/services_mkdb.c =================================================================== RCS file: /home/joerg/repo/netbsd/src/usr.sbin/services_mkdb/services_mkdb.c,v retrieving revision 1.14 diff -u -p -r1.14 services_mkdb.c --- usr.sbin/services_mkdb/services_mkdb.c 28 Apr 2008 20:24:17 -0000 1.14 +++ usr.sbin/services_mkdb/services_mkdb.c 19 Mar 2010 22:28:07 -0000 @@ -37,7 +37,6 @@ __RCSID("$NetBSD: services_mkdb.c,v 1.14 #include #include -#include #include #include #include @@ -50,51 +49,39 @@ __RCSID("$NetBSD: services_mkdb.c,v 1.14 #include #include +#include "extern.h" + static char tname[MAXPATHLEN]; #define PMASK 0xffff #define PROTOMAX 5 -extern void uniq(const char *); - -static void add(DB *, StringList *, size_t, const char *, size_t *, int); static StringList ***parseservices(const char *, StringList *); static void cleanup(void); -static void store(DB *, DBT *, DBT *, int); -static void killproto(DBT *); static char *getstring(const char *, size_t, char **, const char *); static size_t getprotoindex(StringList *, const char *); static const char *getprotostr(StringList *, size_t); -static const char *mkaliases(StringList *, char *, size_t); static void usage(void) __dead; -const HASHINFO hinfo = { - .bsize = 256, - .ffactor = 4, - .nelem = 32768, - .cachesize = 1024, - .hash = NULL, - .lorder = 0 -}; - - int main(int argc, char *argv[]) { - DB *db; int ch; const char *fname = _PATH_SERVICES; - const char *dbname = _PATH_SERVICES_DB; + const char *dbname = NULL; + int use_db = 0; int warndup = 1; int unique = 0; int otherflag = 0; size_t cnt = 0; StringList *sl, ***svc; size_t port, proto; + void (*addfn)(StringList *, size_t, const char *, size_t *, int); + int (*closefn)(void); setprogname(argv[0]); - while ((ch = getopt(argc, argv, "qo:u")) != -1) + while ((ch = getopt(argc, argv, "qo:uV:")) != -1) switch (ch) { case 'q': otherflag = 1; @@ -107,7 +94,14 @@ main(int argc, char *argv[]) case 'u': unique++; break; - case '?': + case 'V': + if (strcmp(optarg, "db") == 0) + use_db = 1; + else if (strcmp(optarg, "cdb") == 0) + use_db = 0; + else + usage(); + break; default: usage(); } @@ -123,17 +117,27 @@ main(int argc, char *argv[]) if (unique) uniq(fname); + if (dbname == NULL) + dbname = use_db ? _PATH_SERVICES_DB : _PATH_SERVICES_CDB; + svc = parseservices(fname, sl = sl_init()); if (atexit(cleanup)) err(1, "Cannot install exit handler"); (void)snprintf(tname, sizeof(tname), "%s.tmp", dbname); - db = dbopen(tname, O_RDWR | O_CREAT | O_EXCL, - (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), DB_HASH, &hinfo); - if (!db) - err(1, "Error opening temporary database `%s'", tname); + if (use_db) { + if (db_open(tname)) + err(1, "Error opening temporary database `%s'", tname); + addfn = db_add; + closefn = db_close; + } else { + if (cdb_open(tname)) + err(1, "Error opening temporary database `%s'", tname); + addfn = cdb_add; + closefn = cdb_close; + } for (port = 0; port < PMASK + 1; port++) { if (svc[port] == NULL) @@ -143,7 +147,7 @@ main(int argc, char *argv[]) StringList *s; if ((s = svc[port][proto]) == NULL) continue; - add(db, s, port, getprotostr(sl, proto), &cnt, warndup); + (addfn)(s, port, getprotostr(sl, proto), &cnt, warndup); } free(svc[port]); @@ -152,8 +156,8 @@ main(int argc, char *argv[]) free(svc); sl_free(sl, 1); - if ((db->close)(db)) - err(1, "Error closing temporary database `%s'", tname); + if ((closefn)()) + err(1, "Error writing temporary database `%s'", tname); if (rename(tname, dbname) == -1) err(1, "Cannot rename `%s' to `%s'", tname, dbname); @@ -161,52 +165,6 @@ main(int argc, char *argv[]) return 0; } -static void -add(DB *db, StringList *sl, size_t port, const char *proto, size_t *cnt, - int warndup) -{ - size_t i; - char keyb[BUFSIZ], datab[BUFSIZ], abuf[BUFSIZ]; - DBT data, key; - key.data = keyb; - data.data = datab; - -#ifdef DEBUG - (void)printf("add %s %zu %s [ ", sl->sl_str[0], port, proto); - for (i = 1; i < sl->sl_cur; i++) - (void)printf("%s ", sl->sl_str[i]); - (void)printf("]\n"); -#endif - - /* key `indirect key', data `full line' */ - data.size = snprintf(datab, sizeof(datab), "%zu", (*cnt)++) + 1; - key.size = snprintf(keyb, sizeof(keyb), "%s %zu/%s %s", - sl->sl_str[0], port, proto, mkaliases(sl, abuf, sizeof(abuf))) + 1; - store(db, &data, &key, warndup); - - /* key `\377port/proto', data = `indirect key' */ - key.size = snprintf(keyb, sizeof(keyb), "\377%zu/%s", - port, proto) + 1; - store(db, &key, &data, warndup); - - /* key `\377port', data = `indirect key' */ - killproto(&key); - store(db, &key, &data, warndup); - - /* add references for service and all aliases */ - for (i = 0; i < sl->sl_cur; i++) { - /* key `\376service/proto', data = `indirect key' */ - key.size = snprintf(keyb, sizeof(keyb), "\376%s/%s", - sl->sl_str[i], proto) + 1; - store(db, &key, &data, warndup); - - /* key `\376service', data = `indirect key' */ - killproto(&key); - store(db, &key, &data, warndup); - } - sl_free(sl, 1); -} - static StringList *** parseservices(const char *fname, StringList *sl) { @@ -276,7 +234,13 @@ parseservices(const char *fname, StringL s = svc[pnum][pindex] = sl_init(); else s = svc[pnum][pindex]; - + + if (strlen(name) > 255) { + warnx("%s, %zu: invalid name too long `%s'", fname, + line, name); + continue; + } + /* build list of aliases */ if (sl_find(s, name) == NULL) (void)sl_add(s, estrdup(name)); @@ -285,6 +249,11 @@ parseservices(const char *fname, StringL while ((alias = strsep(&aliases, " \t")) != NULL) { if (alias[0] == '\0') continue; + if (strlen(alias) > 255) { + warnx("%s, %zu: alias name too long `%s'", + fname, line, alias); + continue; + } if (sl_find(s, alias) == NULL) (void)sl_add(s, estrdup(alias)); } @@ -318,44 +287,6 @@ getstring(const char *fname, size_t line return str; } -static void -killproto(DBT *key) -{ - char *p, *d = key->data; - - if ((p = strchr(d, '/')) == NULL) - abort(); - *p++ = '\0'; - key->size = p - d; -} - -static void -store(DB *db, DBT *key, DBT *data, int warndup) -{ -#ifdef DEBUG - int k = key->size - 1; - int d = data->size - 1; - (void)printf("store [%*.*s] [%*.*s]\n", - k, k, (char *)key->data + 1, - d, d, (char *)data->data + 1); -#endif - switch ((db->put)(db, key, data, R_NOOVERWRITE)) { - case 0: - break; - case 1: - if (warndup) - warnx("duplicate service `%s'", - &((char *)key->data)[1]); - break; - case -1: - err(1, "put"); - break; - default: - abort(); - break; - } -} - static size_t getprotoindex(StringList *sl, const char *str) { @@ -379,34 +310,10 @@ getprotostr(StringList *sl, size_t i) return sl->sl_str[i]; } -static const char * -mkaliases(StringList *sl, char *buf, size_t len) -{ - size_t nc, i, pos; - - buf[0] = 0; - for (i = 1, pos = 0; i < sl->sl_cur; i++) { - nc = strlcpy(buf + pos, sl->sl_str[i], len); - if (nc >= len) - goto out; - pos += nc; - len -= nc; - nc = strlcpy(buf + pos, " ", len); - if (nc >= len) - goto out; - pos += nc; - len -= nc; - } - return buf; -out: - warn("aliases for `%s' truncated", sl->sl_str[0]); - return buf; -} - static void usage(void) { - (void)fprintf(stderr, "Usage:\t%s [-q] [-o ] []\n" + (void)fprintf(stderr, "Usage:\t%s [-q] [-o ] [-V cdb|db] []\n" "\t%s -u []\n", getprogname(), getprogname()); exit(1); } Index: usr.sbin/services_mkdb/uniq.c =================================================================== RCS file: /home/joerg/repo/netbsd/src/usr.sbin/services_mkdb/uniq.c,v retrieving revision 1.4 diff -u -p -r1.4 uniq.c --- usr.sbin/services_mkdb/uniq.c 28 Apr 2008 20:24:17 -0000 1.4 +++ usr.sbin/services_mkdb/uniq.c 19 Mar 2010 19:06:02 -0000 @@ -40,9 +40,17 @@ __RCSID("$NetBSD: uniq.c,v 1.4 2008/04/2 #include #include -extern const HASHINFO hinfo; +#include "extern.h" + +static const HASHINFO hinfo = { + .bsize = 256, + .ffactor = 4, + .nelem = 32768, + .cachesize = 1024, + .hash = NULL, + .lorder = 0 +}; -void uniq(const char *); static int comp(const char *, char **, size_t *); /*