tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Switch device database to cdb(5)



Hi all,
the attached patch removes another db(3) user from libc. The database
creation is much faster, the overall impact of creating both database
should be neglectable. As usual, the cdb version is ~1/4 of the size of
the db(3). I've dropped the complication of the caching code in
ttyname(3). Not having access to the database is the exception case and
I expect /dev to cached, if necessary, making it still fast enough.
There is one visible functional change. devname(3) will return pts/
entries for devices not open. I'm not sure if we have to / want to stat
in that case to verify the existance. Not doing it has the advantage of
working e.g. for ps(1).

Joerg
Index: bin/ps/ps.1
===================================================================
RCS file: /btrfs/repo/netbsd/src/bin/ps/ps.1,v
retrieving revision 1.100
diff -u -p -r1.100 ps.1
--- bin/ps/ps.1 15 Apr 2012 21:20:16 -0000      1.100
+++ bin/ps/ps.1 1 Jun 2012 04:50:17 -0000
@@ -682,7 +682,7 @@ exit or stop status (valid only for stop
 special files and device names
 .It Pa /dev/drum
 default swap device
-.It Pa /var/run/dev.db
+.It Pa /var/run/dev.cdb
 /dev name database
 .It Pa /var/db/kvm.db
 system name list database
Index: distrib/amd64/cdroms/install.sh
===================================================================
RCS file: /btrfs/repo/netbsd/src/distrib/amd64/cdroms/install.sh,v
retrieving revision 1.2
diff -u -p -r1.2 install.sh
--- distrib/amd64/cdroms/install.sh     17 Apr 2011 12:18:20 -0000      1.2
+++ distrib/amd64/cdroms/install.sh     1 Jun 2012 05:00:26 -0000
@@ -38,7 +38,7 @@ termfile=/tmp/sysinst.term
 
 # Check if we are on a framebuffer or on serial console and default
 # the terminal type accordingly.
-# There is no /var/db/dev.db, so sysctl might not map the devicename properly;
+# There is no /var/db/dev.cdb, so sysctl might not map the devicename properly;
 # ttyE0 is 90,0 -> 0x5a00
 case $(sysctl -nx kern.consdev) in
  002f000000000000)
Index: distrib/amd64/installimage/install.sh
===================================================================
RCS file: /btrfs/repo/netbsd/src/distrib/amd64/installimage/install.sh,v
retrieving revision 1.1
diff -u -p -r1.1 install.sh
--- distrib/amd64/installimage/install.sh       22 Jan 2012 03:53:29 -0000      
1.1
+++ distrib/amd64/installimage/install.sh       1 Jun 2012 05:00:34 -0000
@@ -38,7 +38,7 @@ termfile=/tmp/sysinst.term
 
 # Check if we are on a framebuffer or on serial console and default
 # the terminal type accordingly.
-# There is no /var/db/dev.db, so sysctl might not map the devicename properly;
+# There is no /var/db/dev.cdb, so sysctl might not map the devicename properly;
 # ttyE0 is 90,0 -> 0x5a00
 case $(sysctl -nx kern.consdev) in
  002f000000000000)
Index: distrib/i386/cdroms/install.sh
===================================================================
RCS file: /btrfs/repo/netbsd/src/distrib/i386/cdroms/install.sh,v
retrieving revision 1.2
diff -u -p -r1.2 install.sh
--- distrib/i386/cdroms/install.sh      17 Apr 2011 12:18:20 -0000      1.2
+++ distrib/i386/cdroms/install.sh      1 Jun 2012 05:00:42 -0000
@@ -38,7 +38,7 @@ termfile=/tmp/sysinst.term
 
 # Check if we are on a framebuffer or on serial console and default
 # the terminal type accordingly.
-# There is no /var/db/dev.db, so sysctl might not map the devicename properly;
+# There is no /var/db/dev.cdb, so sysctl might not map the devicename properly;
 # ttyE0 is 90,0 -> 0x5a00
 case $(sysctl -nx kern.consdev) in
  002f000000000000)
Index: distrib/i386/installimage/install.sh
===================================================================
RCS file: /btrfs/repo/netbsd/src/distrib/i386/installimage/install.sh,v
retrieving revision 1.1
diff -u -p -r1.1 install.sh
--- distrib/i386/installimage/install.sh        22 Jan 2012 03:53:30 -0000      
1.1
+++ distrib/i386/installimage/install.sh        1 Jun 2012 05:00:46 -0000
@@ -38,7 +38,7 @@ termfile=/tmp/sysinst.term
 
 # Check if we are on a framebuffer or on serial console and default
 # the terminal type accordingly.
-# There is no /var/db/dev.db, so sysctl might not map the devicename properly;
+# There is no /var/db/dev.cdb, so sysctl might not map the devicename properly;
 # ttyE0 is 90,0 -> 0x5a00
 case $(sysctl -nx kern.consdev) in
  002f000000000000)
Index: distrib/sparc64/cdroms/installcd/install.sh
===================================================================
RCS file: /btrfs/repo/netbsd/src/distrib/sparc64/cdroms/installcd/install.sh,v
retrieving revision 1.2
diff -u -p -r1.2 install.sh
--- distrib/sparc64/cdroms/installcd/install.sh 17 Apr 2011 12:18:20 -0000      
1.2
+++ distrib/sparc64/cdroms/installcd/install.sh 1 Jun 2012 05:01:03 -0000
@@ -38,7 +38,7 @@ termfile=/tmp/sysinst.term
 
 # Check if we are on a framebuffer or on serial console and default
 # the terminal type accordingly.
-# There is no /var/db/dev.db, so sysctl might not map the devicename properly;
+# There is no /var/db/dev.cdb, so sysctl might not map the devicename properly;
 # ttyE0 is 90,0 -> 0x5a00
 case $(sysctl -nx kern.consdev) in
  0000000000005a0*)
Index: distrib/sparc64/instfs/dot.profile
===================================================================
RCS file: /btrfs/repo/netbsd/src/distrib/sparc64/instfs/dot.profile,v
retrieving revision 1.6
diff -u -p -r1.6 dot.profile
--- distrib/sparc64/instfs/dot.profile  17 Apr 2011 12:18:20 -0000      1.6
+++ distrib/sparc64/instfs/dot.profile  1 Jun 2012 05:00:53 -0000
@@ -38,7 +38,7 @@ export PATH
 
 # Check if we are on a framebuffer or on serial console and default
 # the terminal type accordingly.
-# There is no /var/db/dev.db, so sysctl might not map the devicename properly;
+# There is no /var/db/dev.cdb, so sysctl might not map the devicename properly;
 # ttyE0 is 90,0 -> 0x5a00
 case $(sysctl -nx kern.consdev) in
  0000000000005a0*)
Index: etc/rc.d/sysdb
===================================================================
RCS file: /btrfs/repo/netbsd/src/etc/rc.d/sysdb,v
retrieving revision 1.23
diff -u -p -r1.23 sysdb
--- etc/rc.d/sysdb      21 Feb 2012 12:30:32 -0000      1.23
+++ etc/rc.d/sysdb      1 Jun 2012 15:05:15 -0000
@@ -63,6 +63,7 @@ build_netgroup()
 build_devdb()
 {
        check_file /dev /var/run/dev.db dev_mkdb
+       check_file /dev /var/run/dev.cdb dev_mkdb
 }
 
 build_password()
Index: include/paths.h
===================================================================
RCS file: /btrfs/repo/netbsd/src/include/paths.h,v
retrieving revision 1.40
diff -u -p -r1.40 paths.h
--- include/paths.h     27 Sep 2011 11:24:20 -0000      1.40
+++ include/paths.h     1 Jun 2012 01:29:44 -0000
@@ -64,6 +64,7 @@
 #define _PATH_CPUCTL   "/dev/cpuctl"
 #define        _PATH_CSMAPPER  "/usr/share/i18n/csmapper"
 #define        _PATH_DEFTAPE   "/dev/nrst0"
+#define        _PATH_DEVCDB    "/var/run/dev.cdb"
 #define        _PATH_DEVDB     "/var/run/dev.db"
 #define        _PATH_DEVNULL   "/dev/null"
 #define        _PATH_DRUM      "/dev/drum"
Index: include/stdlib.h
===================================================================
RCS file: /btrfs/repo/netbsd/src/include/stdlib.h,v
retrieving revision 1.98
diff -u -p -r1.98 stdlib.h
--- include/stdlib.h    20 Apr 2012 17:31:29 -0000      1.98
+++ include/stdlib.h    1 Jun 2012 02:24:18 -0000
@@ -269,6 +269,7 @@ int  cgetustr(char *, const char *, char
 void    csetexpandtc(int);
 
 int     daemon(int, int);
+int     devname_r(dev_t, mode_t, char *, size_t);
 #ifndef __LIBC12_SOURCE__
 __aconst char *devname(dev_t, mode_t) __RENAME(__devname50);
 #endif
Index: lib/libc/gen/devname.3
===================================================================
RCS file: /btrfs/repo/netbsd/src/lib/libc/gen/devname.3,v
retrieving revision 1.11
diff -u -p -r1.11 devname.3
--- lib/libc/gen/devname.3      7 Aug 2003 16:42:46 -0000       1.11
+++ lib/libc/gen/devname.3      1 Jun 2012 04:51:57 -0000
@@ -67,8 +67,8 @@ The traditional display for applications
 found is the string
 .Dq ?? .
 .Sh FILES
-.Bl -tag -width /var/run/dev.db -compact
-.It Pa /var/run/dev.db
+.Bl -tag -width /var/run/dev.cdb -compact
+.It Pa /var/run/dev.cdb
 Device database file.
 .El
 .Sh SEE ALSO
Index: lib/libc/gen/devname.c
===================================================================
RCS file: /btrfs/repo/netbsd/src/lib/libc/gen/devname.c,v
retrieving revision 1.21
diff -u -p -r1.21 devname.c
--- lib/libc/gen/devname.c      23 Mar 2010 20:28:59 -0000      1.21
+++ lib/libc/gen/devname.c      1 Jun 2012 14:44:57 -0000
@@ -1,7 +1,7 @@
 /*     $NetBSD: devname.c,v 1.21 2010/03/23 20:28:59 drochner Exp $    */
 
 /*-
- * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -29,170 +29,139 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-/*-
- * Copyright (c) 1992 Keith Muller.
- * Copyright (c) 1989, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Keith Muller of the University of California, San Diego.
- *
- * 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.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)devname.c  8.2 (Berkeley) 4/29/95";
-#else
 __RCSID("$NetBSD: devname.c,v 1.21 2010/03/23 20:28:59 drochner Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
 
 #include "namespace.h"
-#include <sys/types.h>
+#include "reentrant.h"
 #include <sys/stat.h>
-#include <sys/param.h>
 
-#include <db.h>
-#include <fcntl.h>
+#include <cdbr.h>
+#include <errno.h>
+#include <fts.h>
+#include <limits.h>
 #include <paths.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
-#include <err.h>
 
-#define        DEV_SZ          317     /* show be prime for best results */
-#define        VALID           1       /* entry and devname are valid */
-#define        INVALID         2       /* entry valid, devname NOT valid */
-
-typedef struct devc {
-       int valid;              /* entry valid? */
-       dev_t dev;              /* cached device */
-       mode_t type;            /* cached file type */
-       char name[NAME_MAX];    /* device name */
-} DEVC;
+#ifdef __weak_alias
+__weak_alias(devname_r,_devname_r)
+#endif
 
-char *
-devname(dev, type)
-       dev_t dev;
-       mode_t type;
-{
-       struct {
-               mode_t type;
-               dev_t dev;
-       } bkey;
-       struct {
-               mode_t type;
-               int32_t dev;
-       } obkey;
-       static DB *db;
-       static int failure;
-       DBT data, key;
-       DEVC *ptr, **pptr;
-       static DEVC **devtb = NULL;
-       static devmajor_t pts;
-       static int pts_valid = 0;
-
-       if (!db && !failure &&
-           !(db = dbopen(_PATH_DEVDB, O_RDONLY, 0, DB_HASH, NULL))) {
-               warn("warning: %s", _PATH_DEVDB);
-               failure = 1;
-       }
-       /* initialise dev cache */
-       if (!failure && devtb == NULL) {
-               devtb = calloc(DEV_SZ, sizeof(DEVC *));
-               if (devtb == NULL)
-                       failure= 1;
-       }
-       if (failure)
-               return (NULL);
+static once_t db_opened = ONCE_INITIALIZER;
+static struct cdbr *db;
+static devmajor_t pts;
 
-       /* see if we have this dev/type cached */
-       pptr = devtb + (size_t)((dev + type) % DEV_SZ);
-       ptr = *pptr;
-
-       if (ptr && ptr->valid > 0 && ptr->dev == dev && ptr->type == type) {
-               if (ptr->valid == VALID)
-                       return (ptr->name);
-               return (NULL);
-       }
+static void
+devname_dbopen(void)
+{
+       db = cdbr_open(_PATH_DEVCDB, CDBR_DEFAULT);
+       pts = getdevmajor("pts", S_IFCHR);
+}
 
-       if (ptr == NULL)
-               *pptr = ptr = malloc(sizeof(DEVC));
+__CTASSERT(sizeof(dev_t) == 8);
 
-       /*
-        * Keys are a mode_t followed by a dev_t.  The former is the type of
-        * the file (mode & S_IFMT), the latter is the st_rdev field.  Be
-        * sure to clear any padding that may be found in bkey.
-        */
-       (void)memset(&bkey, 0, sizeof(bkey));
-       bkey.dev = dev;
-       bkey.type = type;
-       key.data = &bkey;
-       key.size = sizeof(bkey);
-       if ((db->get)(db, &key, &data, 0) == 0) {
-found_it:
-               if (ptr == NULL)
-                       return (char *)data.data;
-               ptr->dev = dev;
-               ptr->type = type;
-               strncpy(ptr->name, (char *)data.data, NAME_MAX);
-               ptr->name[NAME_MAX - 1] = '\0';
-               ptr->valid = VALID;
-       } else {
-               /* Look for a 32 bit dev_t. */
-               (void)memset(&obkey, 0, sizeof(obkey));
-               obkey.dev = (int32_t)(uint32_t)dev;
-               obkey.type = type;
-               key.data = &obkey;
-               key.size = sizeof(obkey);
-               if ((db->get)(db, &key, &data, 0) == 0)
-                       goto found_it;
-
-               if (ptr == NULL)
-                       return (NULL);
-               ptr->valid = INVALID;
-               if (type == S_IFCHR) {
-                       if (!pts_valid) {
-                               pts = getdevmajor("pts", S_IFCHR);
-                               pts_valid = 1;
-                       }
-                       if (pts != NODEVMAJOR && major(dev) == pts) {
-                               (void)snprintf(ptr->name, sizeof(ptr->name),
-                                   "%s%d", _PATH_DEV_PTS +
-                                   sizeof(_PATH_DEV) - 1,
-                                   minor(dev));
-                               ptr->valid = VALID;
-                       }
+static int
+devname_dblookup(dev_t dev, mode_t type, char *path, size_t len)
+{
+       const void *data;
+       size_t datalen;
+       uint8_t key[10];
+
+       le64enc(key, dev);
+       le16enc(key + 8, type);
+       if (cdbr_find(db, key, sizeof(key), &data, &datalen) != 0)
+               return ENOENT;
+       if (datalen <= sizeof(key))
+               return ENOENT;
+       if (memcmp(key, data, sizeof(key)) != 0)
+               return ENOENT;
+       data = (const char *)data + sizeof(key);
+       datalen -= sizeof(key);
+       if (memchr(data, '\0', datalen) != (const char *)data + datalen - 1)
+               return ENOENT;
+       if (datalen > len)
+               return ERANGE;
+       memcpy(path, data, datalen);
+       return 0;
+}
+
+static int
+devname_ptslookup(dev_t dev, mode_t type, char *path, size_t len)
+{
+       int rv;
+
+       if (type != S_IFCHR || pts == NODEVMAJOR || major(dev) != pts)
+               return ENOENT;
+
+       rv = snprintf(path, len, "%s%d", _PATH_DEV_PTS + sizeof(_PATH_DEV) - 1,
+           minor(dev));
+       if (rv < 0 || (size_t)rv >= len)
+               return ERANGE;
+       return 0;
+}
+
+static int
+devname_fts(dev_t dev, mode_t type, char *path, size_t len)
+{
+       FTS *ftsp;
+       FTSENT *fe;
+       static const char path_dev[] = _PATH_DEV;
+       static char * const dirs[2] = { __UNCONST(path_dev), NULL };
+       const size_t len_dev = strlen(path_dev);
+       int rv;
+
+       if ((ftsp = fts_open(dirs, FTS_NOCHDIR | FTS_PHYSICAL, NULL)) == NULL)
+               return ENOENT;
+
+       rv = ENOENT;
+       while ((fe = fts_read(ftsp)) != NULL) {
+               if (fe->fts_info != FTS_DEFAULT)
+                       continue;
+               if (fe->fts_statp->st_rdev != dev)
+                       continue;
+               if ((type & S_IFMT) != (fe->fts_statp->st_mode & S_IFMT))
+                       continue;
+               if (strncmp(fe->fts_path, path_dev, len_dev))
+                       continue;
+               if (strlcpy(path, fe->fts_path + len_dev, len) < len) {
+                       rv = 0;
+                       break;
                }
-               ptr->dev = dev;
-               ptr->type = type;
        }
-       if (ptr->valid == VALID)
-               return (ptr->name);
-       else
-               return (NULL);
+
+       fts_close(ftsp);
+       return rv;
+}
+
+int
+devname_r(dev_t dev, mode_t type, char *path, size_t len)
+{
+       int rv;
+
+       thr_once(&db_opened, devname_dbopen);
+
+       if (db != NULL) {
+               rv = devname_dblookup(dev, type, path, len);
+               if (rv == 0 || rv == ERANGE)
+                       return rv;
+       }
+
+       rv = devname_ptslookup(dev, type, path, len);
+       if (rv == 0 || rv == ERANGE)
+               return rv;
+
+       if (db != NULL)
+               return ENOENT;
+       rv = devname_fts(dev, type, path, len);
+       return rv;
+}
+
+char *
+devname(dev_t dev, mode_t type)
+{
+       static char path[PATH_MAX];
+
+       return devname_r(dev, type, path, sizeof(path)) == 0 ? path : NULL;
 }
Index: lib/libc/gen/ttyname.3
===================================================================
RCS file: /btrfs/repo/netbsd/src/lib/libc/gen/ttyname.3,v
retrieving revision 1.23
diff -u -p -r1.23 ttyname.3
--- lib/libc/gen/ttyname.3      31 May 2012 23:11:35 -0000      1.23
+++ lib/libc/gen/ttyname.3      1 Jun 2012 04:52:17 -0000
@@ -106,7 +106,7 @@ device without requiring one to enumerat
 .Sh IMPLEMENTATION NOTES
 As an optimisation, these functions attempt to obtain information about
 all devices from the
-.Pa /var/run/dev.db
+.Pa /var/run/dev.cdb
 database, if it exists.
 If the database exists but is out of date, then these functions
 may produce incorrect results.
@@ -193,7 +193,7 @@ and
 .Fn ttyslot
 functions appeared in
 .At v7 .
-.\" Use of the .Pa /var/run/dev.db file was added in ???.
+.\" Use of the .Pa /var/run/dev.cdb file was added in netBSD 6.0.
 .Sh BUGS
 The
 .Fn ttyname
Index: lib/libc/gen/ttyname.c
===================================================================
RCS file: /btrfs/repo/netbsd/src/lib/libc/gen/ttyname.c,v
retrieving revision 1.24
diff -u -p -r1.24 ttyname.c
--- lib/libc/gen/ttyname.c      25 Jun 2008 11:47:29 -0000      1.24
+++ lib/libc/gen/ttyname.c      1 Jun 2012 02:24:48 -0000
@@ -39,48 +39,31 @@ __RCSID("$NetBSD: ttyname.c,v 1.24 2008/
 #endif /* LIBC_SCCS and not lint */
 
 #include "namespace.h"
-#include <sys/types.h>
-#include <sys/param.h>
+#include <sys/ioctl.h>
 #include <sys/stat.h>
 
 #include <assert.h>
-#include <db.h>
-#include <dirent.h>
 #include <errno.h>
-#include <fcntl.h>
-#include <paths.h>
+#include <limits.h>
 #include <string.h>
+#include <stdlib.h>
 #include <termios.h>
 #include <unistd.h>
-#include <sys/ioctl.h>
 
 #ifdef __weak_alias
 __weak_alias(ttyname,_ttyname)
 __weak_alias(ttyname_r,_ttyname_r)
 #endif
 
-static int oldttyname(const struct stat *, char *, size_t);
-
 int
 ttyname_r(int fd, char *buf, size_t len)
 {
        struct stat sb;
        struct termios ttyb;
-       DB *db;
-       DBT data, key;
-       struct {
-               mode_t type;
-               dev_t dev;
-       } bkey;
        struct ptmget ptm;
-#define DEVSZ (sizeof(_PATH_DEV) - 1)
 
        _DIAGASSERT(fd != -1);
 
-       if (len <= DEVSZ) {
-               return ERANGE;
-       }
-
        /* If it is a pty, deal with it quickly */
        if (ioctl(fd, TIOCPTSNAME, &ptm) != -1) {
                if (strlcpy(buf, ptm.sn, len) >= len) {
@@ -88,84 +71,21 @@ ttyname_r(int fd, char *buf, size_t len)
                }
                return 0;
        }
+
        /* Must be a terminal. */
        if (tcgetattr(fd, &ttyb) == -1)
                return errno;
 
-       /* Must be a character device. */
        if (fstat(fd, &sb))
                return errno;
-       if (!S_ISCHR(sb.st_mode))
-               return ENOTTY;
 
-       (void)memcpy(buf, _PATH_DEV, DEVSZ);
-       if ((db = dbopen(_PATH_DEVDB, O_RDONLY, 0, DB_HASH, NULL)) != NULL) {
-               (void)memset(&bkey, 0, sizeof(bkey));
-               bkey.type = S_IFCHR;
-               bkey.dev = sb.st_rdev;
-               key.data = &bkey;
-               key.size = sizeof(bkey);
-               if (!(db->get)(db, &key, &data, 0)) {
-                       if (len - DEVSZ <= data.size) {
-                               return ERANGE;
-                       }
-                       (void)memcpy(buf + DEVSZ, data.data, data.size);
-                       (void)(db->close)(db);
-                       return 0;
-               }
-               (void)(db->close)(db);
-       }
-       if (oldttyname(&sb, buf, len) == -1)
-               return errno;
-       return 0;
-}
-
-static int
-oldttyname(const struct stat *sb, char *buf, size_t len)
-{
-       struct dirent *dirp;
-       DIR *dp;
-       struct stat dsb;
-       size_t dlen;
-
-       _DIAGASSERT(sb != NULL);
-
-       if ((dp = opendir(_PATH_DEV)) == NULL)
-               return -1;
-
-       while ((dirp = readdir(dp)) != NULL) {
-               if (dirp->d_fileno != sb->st_ino)
-                       continue;
-               dlen = dirp->d_namlen + 1;
-               if (len - DEVSZ <= dlen) {
-                       /*
-                        * XXX: we return an error if *any* entry does not
-                        * fit
-                        */
-                       errno = ERANGE;
-                       (void)closedir(dp);
-                       return -1;
-               }
-               (void)memcpy(buf + DEVSZ, dirp->d_name, dlen);
-               if (stat(buf, &dsb) || sb->st_dev != dsb.st_dev ||
-                   sb->st_ino != dsb.st_ino)
-                       continue;
-               (void)closedir(dp);
-               return 0;
-       }
-       (void)closedir(dp);
-       /*
-        * XXX: Documented by TOG to return EBADF or ENOTTY only; neither are
-        * applicable here.
-        */
-       errno = ENOENT;
-       return -1;
+       return devname_r(sb.st_rdev, sb.st_mode & S_IFMT, buf, len);
 }
 
 char *
 ttyname(int fd)
 {
-       static char buf[MAXPATHLEN];
+       static char buf[PATH_MAX];
        int rv;
        
        rv = ttyname_r(fd, buf, sizeof(buf));
Index: lib/libc/include/namespace.h
===================================================================
RCS file: /btrfs/repo/netbsd/src/lib/libc/include/namespace.h,v
retrieving revision 1.153
diff -u -p -r1.153 namespace.h
--- lib/libc/include/namespace.h        12 Apr 2012 22:08:46 -0000      1.153
+++ lib/libc/include/namespace.h        1 Jun 2012 00:30:49 -0000
@@ -39,6 +39,7 @@
 #define catopen                _catopen
 #define daylight       _daylight
 #define difftime       _difftime
+#define devname_r      _devname_r
 #define err            _err
 #define errx           _errx
 #ifdef _REENTRANT
Index: share/man/man5/rc.conf.5
===================================================================
RCS file: /btrfs/repo/netbsd/src/share/man/man5/rc.conf.5,v
retrieving revision 1.151
diff -u -p -r1.151 rc.conf.5
--- share/man/man5/rc.conf.5    8 Jan 2012 04:01:12 -0000       1.151
+++ share/man/man5/rc.conf.5    1 Jun 2012 04:52:33 -0000
@@ -55,7 +55,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd June 1, 2011
+.Dd June 1, 2012
 .Dt RC.CONF 5
 .Os
 .Sh NAME
@@ -493,10 +493,10 @@ The default setting is
 .It Sy sysdb
 Boolean value.
 Builds various system databases, including
-.Pa /var/run/dev.db ,
+.Pa /var/run/dev.cdb ,
 .Pa /etc/spwd.db ,
 .Pa /var/db/netgroup.db ,
-.Pa /var/db/services.db ,
+.Pa /var/db/services.cdb ,
 and entries for
 .Xr utmp 5 .
 .It Sy tpctl
Index: tests/include/t_paths.c
===================================================================
RCS file: /btrfs/repo/netbsd/src/tests/include/t_paths.c,v
retrieving revision 1.11
diff -u -p -r1.11 t_paths.c
--- tests/include/t_paths.c     6 Nov 2011 16:18:27 -0000       1.11
+++ tests/include/t_paths.c     1 Jun 2012 01:29:53 -0000
@@ -64,6 +64,7 @@ static const struct {
        { _PATH_CPUCTL,         PATH_DEV                },
        { _PATH_CSMAPPER,       PATH_DIR                },
        { _PATH_DEFTAPE,        PATH_DEV | PATH_ROOT    },
+       { _PATH_DEVCDB,         PATH_FILE               },
        { _PATH_DEVDB,          PATH_FILE               },
        { _PATH_DEVNULL,        PATH_DEV                },
        { _PATH_DRUM,           PATH_DEV | PATH_ROOT    },
Index: tests/usr.bin/sdiff/d_flags_l.out
===================================================================
RCS file: /btrfs/repo/netbsd/src/tests/usr.bin/sdiff/d_flags_l.out,v
retrieving revision 1.1
diff -u -p -r1.1 d_flags_l.out
--- tests/usr.bin/sdiff/d_flags_l.out   17 Mar 2012 16:33:15 -0000      1.1
+++ tests/usr.bin/sdiff/d_flags_l.out   1 Jun 2012 04:53:17 -0000
@@ -67,7 +67,7 @@ Policy: /usr/bin/lynx, Emulation: native
                                                                 >     
native-pread: permit
                                                                 >     
native-write: permit
                                                                 >     
native-fsread: filename eq "$HOME/.lynx-keymaps" then permi
-    native-fsread: filename eq "/var/run/dev.db" then permit
+    native-fsread: filename eq "/var/run/dev.cdb" then permit
     native-fsread: filename eq "/var/run/ld.so.hints" then perm |     
native-fsread: filename eq "/etc/utmp" then permit
     native-fstat: permit                                        <
     native-fswrite: filename match "/tmp/lynx-*" then permit    <
Index: tests/usr.bin/sdiff/d_flags_w.out
===================================================================
RCS file: /btrfs/repo/netbsd/src/tests/usr.bin/sdiff/d_flags_w.out,v
retrieving revision 1.1
diff -u -p -r1.1 d_flags_w.out
--- tests/usr.bin/sdiff/d_flags_w.out   17 Mar 2012 16:33:15 -0000      1.1
+++ tests/usr.bin/sdiff/d_flags_w.out   1 Jun 2012 04:53:26 -0000
@@ -67,7 +67,7 @@ Policy: /usr/bin/lynx, Emulation: native
                                                               >     
native-pread: permit
                                                               >     
native-write: permit
                                                               >     
native-fsread: filename eq "$HOME/.lynx-keymaps" then per
-    native-fsread: filename eq "/var/run/dev.db" then permit        
native-fsread: filename eq "/var/run/dev.db" then permit
+    native-fsread: filename eq "/var/run/dev.cdb" then permit       
native-fsread: filename eq "/var/run/dev.cdb" then permit
     native-fsread: filename eq "/var/run/ld.so.hints" then pe |     
native-fsread: filename eq "/etc/utmp" then permit
     native-fstat: permit                                      <
     native-fswrite: filename match "/tmp/lynx-*" then permit  <
Index: tests/usr.bin/sdiff/d_iflags_a1.out
===================================================================
RCS file: /btrfs/repo/netbsd/src/tests/usr.bin/sdiff/d_iflags_a1.out,v
retrieving revision 1.1
diff -u -p -r1.1 d_iflags_a1.out
--- tests/usr.bin/sdiff/d_iflags_a1.out 17 Mar 2012 16:33:15 -0000      1.1
+++ tests/usr.bin/sdiff/d_iflags_a1.out 1 Jun 2012 04:53:41 -0000
@@ -65,7 +65,7 @@ Policy: /usr/bin/lynx, Emulation: native
                                                               >     
native-pread: permit
                                                               >     
native-write: permit
                                                               >     
native-fsread: filename eq "$HOME/.lynx-keymaps" then per
-    native-fsread: filename eq "/var/run/dev.db" then permit        
native-fsread: filename eq "/var/run/dev.db" then permit
+    native-fsread: filename eq "/var/run/dev.cdb" then permit       
native-fsread: filename eq "/var/run/dev.cdb" then permit
     native-fsread: filename eq "/var/run/ld.so.hints" then pe |     
native-fsread: filename eq "/etc/utmp" then permit
     native-fstat: permit                                      <
     native-fswrite: filename match "/tmp/lynx-*" then permit  <
Index: tests/usr.bin/sdiff/d_iflags_a2.out
===================================================================
RCS file: /btrfs/repo/netbsd/src/tests/usr.bin/sdiff/d_iflags_a2.out,v
retrieving revision 1.1
diff -u -p -r1.1 d_iflags_a2.out
--- tests/usr.bin/sdiff/d_iflags_a2.out 17 Mar 2012 16:33:15 -0000      1.1
+++ tests/usr.bin/sdiff/d_iflags_a2.out 1 Jun 2012 05:01:00 -0000
@@ -65,7 +65,7 @@ Policy: /usr/bin/lynx, Emulation: native
     native-pread: permit                                      <
     native-write: permit                                      <
     native-fsread: filename eq "$HOME/.lynx-keymaps" then per <
-    native-fsread: filename eq "/var/run/dev.db" then permit        
native-fsread: filename eq "/var/run/dev.db" then permit
+    native-fsread: filename eq "/var/run/dev.cdb" then permit       
native-fsread: filename eq "/var/run/dev.cdb" then permit
     native-fsread: filename eq "/etc/utmp" then permit        |     
native-fsread: filename eq "/var/run/ld.so.hints" then pe
     native-poll: permit                                       |     
native-fstat: permit
     native-nanosleep: permit                                  |     
native-fswrite: filename match "/tmp/lynx-*" then permit
Index: tests/usr.bin/sdiff/d_iflags_c1.out
===================================================================
RCS file: /btrfs/repo/netbsd/src/tests/usr.bin/sdiff/d_iflags_c1.out,v
retrieving revision 1.1
diff -u -p -r1.1 d_iflags_c1.out
--- tests/usr.bin/sdiff/d_iflags_c1.out 17 Mar 2012 16:33:15 -0000      1.1
+++ tests/usr.bin/sdiff/d_iflags_c1.out 1 Jun 2012 04:53:48 -0000
@@ -64,7 +64,7 @@ Policy: /usr/bin/lynx, Emulation: native
                                                               >     
native-pread: permit
                                                               >     
native-write: permit
                                                               >     
native-fsread: filename eq "$HOME/.lynx-keymaps" then per
-    native-fsread: filename eq "/var/run/dev.db" then permit  (
+    native-fsread: filename eq "/var/run/dev.cdb" then permit (
     native-fsread: filename eq "/var/run/ld.so.hints" then pe |     
native-fsread: filename eq "/etc/utmp" then permit
     native-fstat: permit                                      <
     native-fswrite: filename match "/tmp/lynx-*" then permit  <
Index: tests/usr.bin/sdiff/d_iflags_c2.out
===================================================================
RCS file: /btrfs/repo/netbsd/src/tests/usr.bin/sdiff/d_iflags_c2.out,v
retrieving revision 1.1
diff -u -p -r1.1 d_iflags_c2.out
--- tests/usr.bin/sdiff/d_iflags_c2.out 17 Mar 2012 16:33:15 -0000      1.1
+++ tests/usr.bin/sdiff/d_iflags_c2.out 1 Jun 2012 04:53:54 -0000
@@ -63,7 +63,7 @@ Policy: /usr/bin/lynx, Emulation: native
     native-pread: permit                                      <
     native-write: permit                                      <
     native-fsread: filename eq "$HOME/.lynx-keymaps" then per <
-    native-fsread: filename eq "/var/run/dev.db" then permit  (
+    native-fsread: filename eq "/var/run/dev.cdb" then permit (
     native-fsread: filename eq "/etc/utmp" then permit        |     
native-fsread: filename eq "/var/run/ld.so.hints" then pe
     native-poll: permit                                       |     
native-fstat: permit
     native-nanosleep: permit                                  |     
native-fswrite: filename match "/tmp/lynx-*" then permit
Index: tests/usr.bin/sdiff/d_input1
===================================================================
RCS file: /btrfs/repo/netbsd/src/tests/usr.bin/sdiff/d_input1,v
retrieving revision 1.1
diff -u -p -r1.1 d_input1
--- tests/usr.bin/sdiff/d_input1        17 Mar 2012 16:33:15 -0000      1.1
+++ tests/usr.bin/sdiff/d_input1        1 Jun 2012 04:53:58 -0000
@@ -42,7 +42,7 @@ Policy: /usr/bin/lynx, Emulation: native
     native-fsread: filename eq "/usr/obj/bin/systrace/.mailcap" then permit
     native-fsread: filename eq "/usr/obj/bin/systrace/.mime.types" then permit
     native-fsread: filename eq "/usr/share/misc/terminfo.db" then permit
-    native-fsread: filename eq "/var/run/dev.db" then permit
+    native-fsread: filename eq "/var/run/dev.cdb" then permit
     native-fsread: filename eq "/var/run/ld.so.hints" then permit
     native-fstat: permit
     native-fswrite: filename match "/tmp/lynx-*" then permit
Index: tests/usr.bin/sdiff/d_input2
===================================================================
RCS file: /btrfs/repo/netbsd/src/tests/usr.bin/sdiff/d_input2,v
retrieving revision 1.1
diff -u -p -r1.1 d_input2
--- tests/usr.bin/sdiff/d_input2        17 Mar 2012 16:33:15 -0000      1.1
+++ tests/usr.bin/sdiff/d_input2        1 Jun 2012 04:54:03 -0000
@@ -53,7 +53,7 @@ Policy: /usr/bin/lynx, Emulation: native
     native-pread: permit
     native-write: permit
     native-fsread: filename eq "$HOME/.lynx-keymaps" then permit
-    native-fsread: filename eq "/var/run/dev.db" then permit
+    native-fsread: filename eq "/var/run/dev.cdb" then permit
     native-fsread: filename eq "/etc/utmp" then permit
     native-poll: permit
     native-nanosleep: permit
Index: tests/usr.bin/sdiff/d_same.out
===================================================================
RCS file: /btrfs/repo/netbsd/src/tests/usr.bin/sdiff/d_same.out,v
retrieving revision 1.1
diff -u -p -r1.1 d_same.out
--- tests/usr.bin/sdiff/d_same.out      17 Mar 2012 16:33:15 -0000      1.1
+++ tests/usr.bin/sdiff/d_same.out      1 Jun 2012 04:54:08 -0000
@@ -42,7 +42,7 @@ Policy: /usr/bin/lynx, Emulation: native
     native-fsread: filename eq "/usr/obj/bin/systrace/.mailcap"       
native-fsread: filename eq "/usr/obj/bin/systrace/.mailcap"
     native-fsread: filename eq "/usr/obj/bin/systrace/.mime.typ       
native-fsread: filename eq "/usr/obj/bin/systrace/.mime.typ
     native-fsread: filename eq "/usr/share/misc/terminfo.db" th       
native-fsread: filename eq "/usr/share/misc/terminfo.db" th
-    native-fsread: filename eq "/var/run/dev.db" then permit          
native-fsread: filename eq "/var/run/dev.db" then permit
+    native-fsread: filename eq "/var/run/dev.cdb" then permit         
native-fsread: filename eq "/var/run/dev.cdb" then permit
     native-fsread: filename eq "/var/run/ld.so.hints" then perm       
native-fsread: filename eq "/var/run/ld.so.hints" then perm
     native-fstat: permit                                              
native-fstat: permit
     native-fswrite: filename match "/tmp/lynx-*" then permit          
native-fswrite: filename match "/tmp/lynx-*" then permit
Index: tests/usr.bin/sdiff/d_tabs.out
===================================================================
RCS file: /btrfs/repo/netbsd/src/tests/usr.bin/sdiff/d_tabs.out,v
retrieving revision 1.1
diff -u -p -r1.1 d_tabs.out
--- tests/usr.bin/sdiff/d_tabs.out      17 Mar 2012 16:33:15 -0000      1.1
+++ tests/usr.bin/sdiff/d_tabs.out      1 Jun 2012 04:54:13 -0000
@@ -67,7 +67,7 @@ Policy: /usr/bin/lynx, Emulation: native
                                                                 >      
native-pread: permit
                                                                 >      
native-write: permit
                                                                 >      
native-fsread: filename eq "$HOME/.lynx-keymaps" then per
-       native-fsread: filename eq "/var/run/dev.db" then permi         
native-fsread: filename eq "/var/run/dev.db" then permit
+       native-fsread: filename eq "/var/run/dev.cdb" then permi        
native-fsread: filename eq "/var/run/dev.cdb" then permit
        native-fsread: filename eq "/var/run/ld.so.hints" then  |       
native-fsread: filename eq "/etc/utmp" then permit
        native-fstat: permit                                    <
        native-fswrite: filename match "/tmp/lynx-*" then permi <
Index: tests/usr.bin/sdiff/d_tabs1.in
===================================================================
RCS file: /btrfs/repo/netbsd/src/tests/usr.bin/sdiff/d_tabs1.in,v
retrieving revision 1.1
diff -u -p -r1.1 d_tabs1.in
--- tests/usr.bin/sdiff/d_tabs1.in      17 Mar 2012 16:33:15 -0000      1.1
+++ tests/usr.bin/sdiff/d_tabs1.in      1 Jun 2012 04:54:16 -0000
@@ -42,7 +42,7 @@ Policy: /usr/bin/lynx, Emulation: native
        native-fsread: filename eq "/usr/obj/bin/systrace/.mailcap" then permit
        native-fsread: filename eq "/usr/obj/bin/systrace/.mime.types" then 
permit
        native-fsread: filename eq "/usr/share/misc/terminfo.db" then permit
-       native-fsread: filename eq "/var/run/dev.db" then permit
+       native-fsread: filename eq "/var/run/dev.cdb" then permit
        native-fsread: filename eq "/var/run/ld.so.hints" then permit
        native-fstat: permit
        native-fswrite: filename match "/tmp/lynx-*" then permit
Index: tests/usr.bin/sdiff/d_tabs2.in
===================================================================
RCS file: /btrfs/repo/netbsd/src/tests/usr.bin/sdiff/d_tabs2.in,v
retrieving revision 1.1
diff -u -p -r1.1 d_tabs2.in
--- tests/usr.bin/sdiff/d_tabs2.in      17 Mar 2012 16:33:15 -0000      1.1
+++ tests/usr.bin/sdiff/d_tabs2.in      1 Jun 2012 04:54:21 -0000
@@ -53,7 +53,7 @@ Policy: /usr/bin/lynx, Emulation: native
        native-pread: permit
        native-write: permit
        native-fsread: filename eq "$HOME/.lynx-keymaps" then permit
-       native-fsread: filename eq "/var/run/dev.db" then permit
+       native-fsread: filename eq "/var/run/dev.cdb" then permit
        native-fsread: filename eq "/etc/utmp" then permit
        native-poll: permit
        native-nanosleep: permit
Index: usr.sbin/dev_mkdb/Makefile
===================================================================
RCS file: /btrfs/repo/netbsd/src/usr.sbin/dev_mkdb/Makefile,v
retrieving revision 1.7
diff -u -p -r1.7 Makefile
--- usr.sbin/dev_mkdb/Makefile  15 Apr 2009 01:01:06 -0000      1.7
+++ usr.sbin/dev_mkdb/Makefile  1 Jun 2012 14:28:27 -0000
@@ -4,4 +4,7 @@
 PROG=  dev_mkdb
 MAN=   dev_mkdb.8
 
+LDADD+=        -lutil
+DPADD+=        ${LIBUTIL}
+
 .include <bsd.prog.mk>
Index: usr.sbin/dev_mkdb/dev_mkdb.8
===================================================================
RCS file: /btrfs/repo/netbsd/src/usr.sbin/dev_mkdb/dev_mkdb.8,v
retrieving revision 1.12
diff -u -p -r1.12 dev_mkdb.8
--- usr.sbin/dev_mkdb/dev_mkdb.8        5 Mar 2012 10:57:19 -0000       1.12
+++ usr.sbin/dev_mkdb/dev_mkdb.8        1 Jun 2012 05:04:07 -0000
@@ -28,7 +28,7 @@
 .\"    from: @(#)dev_mkdb.8    8.1 (Berkeley) 6/6/93
 .\"    $NetBSD: dev_mkdb.8,v 1.12 2012/03/05 10:57:19 njoly Exp $
 .\"
-.Dd June 6, 1993
+.Dd June 1, 2012
 .Dt DEV_MKDB 8
 .Os
 .Sh NAME
@@ -38,15 +38,16 @@
 database
 .Sh SYNOPSIS
 .Nm
+.Op Fl c
 .Op Fl o Ar database
 .Op directory
 .Sh DESCRIPTION
 The
 .Nm
 command creates a
-.Xr db 3
-hash access method database in
-.Dq Pa /var/run/dev.db
+.Xr cdbr 3
+database in
+.Dq Pa /var/run/dev.cdb 
 which contains the names of all of the character and block special
 files in the specified directory, using the file type and the
 .Fa st_rdev
@@ -62,6 +63,14 @@ the latter is the st_rdev field.
 .Pp
 The options are as follows:
 .Bl -tag -width indent
+.It Fl c
+Create a
+.Xr db 3
+database for compatibility with libc versions and statically linked programs
+from before
+.Nx 6.0 .
+The default name is
+.Dq Pa /var/run/dev.db .
 .It Fl o Ar database
 Put the output databases in the named file.
 .El
Index: usr.sbin/dev_mkdb/dev_mkdb.c
===================================================================
RCS file: /btrfs/repo/netbsd/src/usr.sbin/dev_mkdb/dev_mkdb.c,v
retrieving revision 1.28
diff -u -p -r1.28 dev_mkdb.c
--- usr.sbin/dev_mkdb/dev_mkdb.c        30 Aug 2011 10:04:50 -0000      1.28
+++ usr.sbin/dev_mkdb/dev_mkdb.c        1 Jun 2012 15:07:48 -0000
@@ -30,186 +30,231 @@
  */
 
 #include <sys/cdefs.h>
-#ifndef lint
-__COPYRIGHT("@(#) Copyright (c) 1990, 1993\
- The Regents of the University of California.  All rights reserved.");
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "from: @(#)dev_mkdb.c   8.1 (Berkeley) 6/6/93";
-#else
 __RCSID("$NetBSD: dev_mkdb.c,v 1.28 2011/08/30 10:04:50 joerg Exp $");
-#endif
-#endif /* not lint */
 
-#include <sys/param.h>
+#include <sys/queue.h>
 #include <sys/stat.h>
 
+#include <cdbw.h>
 #include <db.h>
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <fts.h>
-#include <kvm.h>
-#include <nlist.h>
 #include <paths.h>
+#include <search.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <util.h>
+
+#define        HASH_SIZE       65536
+#define        FILE_PERMISSION S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH
+
+static struct cdbw *db;
+static DB *db_compat;
+static const char *db_name;
+static char *db_name_tmp;
 
 static void    usage(void) __dead;
 
-static HASHINFO openinfo = {
-       4096,           /* bsize */
-       128,            /* ffactor */
-       1024,           /* nelem */
-       2048 * 1024,    /* cachesize */
-       NULL,           /* hash() */
-       0               /* lorder */
-};
+static void
+cdb_open(void)
+{
+       db = cdbw_open();
+       if (db == NULL)
+               err(1, "opening cdb writer failed");
+}
 
-int
-main(int argc, char **argv)
+static void
+cdb_close(void)
 {
-       struct stat *st;
+       int fd;
+
+       fd = open(db_name_tmp, O_CREAT|O_EXCL|O_WRONLY, FILE_PERMISSION);
+       if (fd == -1)
+               err(1, "opening %s failed", db_name_tmp);
+       if (cdbw_output(db, fd, "NetBSD6 devdb", NULL))
+               err(1, "failed to write temporary database %s", db_name_tmp);
+       cdbw_close(db);
+       db = NULL;
+       if (close(fd))
+               err(1, "failed to write temporary database %s", db_name_tmp);
+}
+
+static void
+cdb_add_entry(dev_t dev, mode_t type, const char *relpath)
+{
+       uint8_t *buf;
+       size_t len;
+
+       len = strlen(relpath) + 1;
+       buf = malloc(len + 10);
+       le64enc(buf, dev);
+       le16enc(buf + 8, type);
+       memcpy(buf + 10, relpath, len);
+       cdbw_put(db, buf, 10, buf, len + 10);
+       free(buf);
+}
+
+static void
+compat_open(void)
+{
+       static HASHINFO openinfo = {
+               4096,           /* bsize */
+               128,            /* ffactor */
+               1024,           /* nelem */
+               2048 * 1024,    /* cachesize */
+               NULL,           /* hash() */
+               0               /* lorder */
+       };
+
+       db_compat = dbopen(db_name_tmp, O_CREAT|O_EXCL|O_EXLOCK|O_RDWR|O_TRUNC,
+           FILE_PERMISSION, DB_HASH, &openinfo);
+
+       if (db_compat == NULL)
+               err(1, "failed to create temporary database %s",
+                   db_name_tmp);
+}
+
+static void
+compat_close(void)
+{
+       if ((*db_compat->close)(db_compat))
+               err(1, "failed to write temporary database %s", db_name_tmp);
+}
+
+static void
+compat_add_entry(dev_t dev, mode_t type, const char *relpath)
+{
+       /*
+        * Keys are a mode_t followed by a dev_t.  The former is the type of
+        * the file (mode & S_IFMT), the latter is the st_rdev field.  Note
+        * that the structure may contain padding, so we have to clear it
+        * out here.
+        */
        struct {
                mode_t type;
                dev_t dev;
        } bkey;
-       DB *db;
+       struct {
+               mode_t type;
+               int32_t dev;
+       } obkey;
        DBT data, key;
+
+       (void)memset(&bkey, 0, sizeof(bkey));
+       key.data = &bkey;
+       key.size = sizeof(bkey);
+       data.data = __UNCONST(relpath);
+       data.size = strlen(relpath) + 1;
+       bkey.type = type;
+       bkey.dev = dev;
+       if ((*db_compat->put)(db_compat, &key, &data, 0))
+               err(1, "failed to write temporary database %s", db_name_tmp);
+
+       /*
+        * If the device fits into the old 32bit format, add compat entry
+        * for pre-NetBSD6 libc.
+        */
+
+       if ((dev_t)(int32_t)dev != dev)
+               return;
+
+       (void)memset(&obkey, 0, sizeof(obkey));
+       key.data = &obkey;
+       key.size = sizeof(obkey);
+       data.data = __UNCONST(relpath);
+       data.size = strlen(relpath) + 1;
+       obkey.type = type;
+       obkey.dev = (int32_t)dev;
+       if ((*db_compat->put)(db_compat, &key, &data, 0))
+               err(1, "failed to write temporary database %s", db_name_tmp);
+}
+
+int
+main(int argc, char **argv)
+{
+       struct stat *st;
        FTS *ftsp;
        FTSENT *p;
        int ch;
-       char buf[MAXPATHLEN + 1];
-       char dbtmp[MAXPATHLEN + 1];
-       char dbname[MAXPATHLEN + 1];
-       char *dbname_arg = NULL;
        char *pathv[2];
-       char path_dev[MAXPATHLEN + 1] = _PATH_DEV;
-       char cur_dir[MAXPATHLEN + 1];
-       struct timeval tv;
-       char *q;
        size_t dlen;
+       int compat_mode;
 
        setprogname(argv[0]);
+       compat_mode = 0;
 
-       while ((ch = getopt(argc, argv, "o:")) != -1)
+       while ((ch = getopt(argc, argv, "co:")) != -1)
                switch (ch) {
+               case 'c':
+                       compat_mode = 1;
+                       break;
                case 'o':
-                       dbname_arg = optarg;
+                       db_name = optarg;
                        break;
-               case '?':
                default:
                        usage();
                }
        argc -= optind;
        argv += optind;
 
-       if (argc == 1)
-               if (strlcpy(path_dev, argv[0], sizeof(path_dev)) >=
-                   sizeof(path_dev))
-                       errx(1, "device path too long");
-
        if (argc > 1)
                usage();
 
-       if (getcwd(cur_dir, sizeof(cur_dir)) == NULL)
-               err(1, "%s", cur_dir);
-
-       if (chdir(path_dev) == -1)
-               err(1, "%s", path_dev);
-
-       pathv[0] = path_dev;
        pathv[1] = NULL;
-       dlen = strlen(path_dev) - 1;
-       ftsp = fts_open(pathv, FTS_PHYSICAL, NULL);
+       if (argc == 1)
+               pathv[0] = argv[0];
+       else
+               pathv[0] = __UNCONST(_PATH_DEV);
+       
+       ftsp = fts_open(pathv, FTS_NOCHDIR | FTS_PHYSICAL, NULL);
        if (ftsp == NULL)
-               err(1, "fts_open: %s", path_dev);
+               err(1, "fts_open: %s", pathv[0]);
 
-       if (chdir(cur_dir) == -1)
-               err(1, "%s", cur_dir);
-
-       if (dbname_arg) {
-               if (strlcpy(dbname, dbname_arg, sizeof(dbname)) >=
-                   sizeof(dbname))
-                       errx(1, "dbname too long");
-       } else {
-               if (snprintf(dbname, sizeof(dbname), "%sdev.db",
-                   _PATH_VARRUN) >= (int)sizeof(dbname))
-                       errx(1, "dbname too long");
+       if (db_name == NULL) {
+               if (compat_mode)
+                       db_name = _PATH_DEVDB;
+               else
+                       db_name = _PATH_DEVCDB;
        }
-       /* 
-        * We use rename() to produce the dev.db file from a temporary file,
-        * and rename() is not able to move files across filesystems. Hence we 
-        * need the temporary file to be in the same directory as dev.db.
-        *
-        * Additionally, we might be working in a world writable directory, 
-        * we must ensure that we are not opening an existing file, therefore
-        * the loop on dbopen. 
-        */
-       (void)strlcpy(dbtmp, dbname, sizeof(dbtmp));
-       q = dbtmp + strlen(dbtmp);
-       do {
-               (void)gettimeofday(&tv, NULL);
-               (void)snprintf(q, sizeof(dbtmp) - (q - dbtmp), 
-                   "%ld.tmp", (long)tv.tv_usec);
-               db = dbopen(dbtmp, O_CREAT|O_EXCL|O_EXLOCK|O_RDWR|O_TRUNC,
-                   S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, DB_HASH, &openinfo);
-       } while (!db && (errno == EEXIST));
-       if (db == NULL)
-               err(1, "%s", dbtmp);
+       easprintf(&db_name_tmp, "%s.XXXXXXX", db_name);
+       mktemp(db_name_tmp);
+
+       if (compat_mode)
+               compat_open();
+       else
+               cdb_open();
 
-       /*
-        * Keys are a mode_t followed by a dev_t.  The former is the type of
-        * the file (mode & S_IFMT), the latter is the st_rdev field.  Note
-        * that the structure may contain padding, so we have to clear it
-        * out here.
-        */
-       (void)memset(&bkey, 0, sizeof(bkey));
-       key.data = &bkey;
-       key.size = sizeof(bkey);
-       data.data = (u_char *)(void *)buf;
        while ((p = fts_read(ftsp)) != NULL) {
-               switch (p->fts_info) {
-               case FTS_DEFAULT:
-                       st = p->fts_statp;
-                       break;
-               default:
+               if (p->fts_info != FTS_DEFAULT)
                        continue;
-               }
 
-               /* Create the key. */
-               if (S_ISCHR(st->st_mode))
-                       bkey.type = S_IFCHR;
-               else if (S_ISBLK(st->st_mode))
-                       bkey.type = S_IFBLK;
-               else
+               st = p->fts_statp;
+               if (!S_ISCHR(st->st_mode) && !S_ISBLK(st->st_mode))
                        continue;
-               bkey.dev = st->st_rdev;
-
-               /*
-                * Create the data; nul terminate the name so caller doesn't
-                * have to.  Skip path_dev and slash. Handle old versions
-                * of fts(3), that added multiple slashes, if the pathname
-                * ended with a slash.
-                */
-               while (p->fts_path[dlen] == '/')
-                       dlen++;
-               (void)strlcpy(buf, p->fts_path + dlen, sizeof(buf));
-               data.size = p->fts_pathlen - dlen + 1;
-               if ((*db->put)(db, &key, &data, 0))
-                       err(1, "dbput %s", dbtmp);
+               dlen = strlen(pathv[0]);
+               while (pathv[0][dlen] == '/')
+                       ++dlen;
+               if (compat_mode)
+                       compat_add_entry(st->st_rdev, st->st_mode & S_IFMT,
+                           p->fts_path + dlen);
+               else
+                       cdb_add_entry(st->st_rdev, st->st_mode & S_IFMT,
+                           p->fts_path + dlen);
        }
-       (void)(*db->close)(db);
        (void)fts_close(ftsp);
 
-       if (chdir(cur_dir) == -1)
-               err(1, "%s", cur_dir);
-       if (rename(dbtmp, dbname) == -1)
-               err(1, "rename %s to %s", dbtmp, dbname);
+       if (compat_mode)
+               compat_close();
+       else
+               cdb_close();
+
+       if (rename(db_name_tmp, db_name) == -1)
+               err(1, "rename %s to %s", db_name_tmp, db_name);
        return 0;
 }
 
@@ -217,7 +262,7 @@ static void
 usage(void)
 {
 
-       (void)fprintf(stderr, "Usage: %s [-o database] [directory]\n",
+       (void)fprintf(stderr, "Usage: %s [-c] [-o database] [directory]\n",
            getprogname());
        exit(1);
 }


Home | Main Index | Thread Index | Old Index