summaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorjoerg <joerg@NetBSD.org>2012-06-03 21:42:44 +0000
committerjoerg <joerg@NetBSD.org>2012-06-03 21:42:44 +0000
commitc75c4faf072ea40511548482ef5ddf59c92afcc0 (patch)
treeb2176172ab0730406ac514ab1c56e5cbd2720253 /lib/libc
parentb77be5886d2a20db14467957a1d6086db60cec6e (diff)
Switch device database to cdb(5). Rework ttyname(3) and ttyname_r(3) to
depend on new devname_r(3) as heart. Add /dev/pts magic directly to devname(3). While it can lead to returning non-existing paths, the behavior is more consistent that way. Drop caching layer in devname(3), it doesn't buy anything for the common case of having access to the database. Teach devname(3) proper fallback behavior of scanning /dev. Create both old-style and new-style database for now in /etc/rc.d/sysdb.
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/gen/devname.313
-rw-r--r--lib/libc/gen/devname.c269
-rw-r--r--lib/libc/gen/ttyname.36
-rw-r--r--lib/libc/gen/ttyname.c96
-rw-r--r--lib/libc/include/namespace.h3
5 files changed, 136 insertions, 251 deletions
diff --git a/lib/libc/gen/devname.3 b/lib/libc/gen/devname.3
index 1c00fc5b56b..6ab0318d128 100644
--- a/lib/libc/gen/devname.3
+++ b/lib/libc/gen/devname.3
@@ -1,4 +1,4 @@
-.\" $NetBSD: devname.3,v 1.11 2003/08/07 16:42:46 agc Exp $
+.\" $NetBSD: devname.3,v 1.12 2012/06/03 21:42:46 joerg Exp $
.\"
.\" Copyright (c) 1993
.\" The Regents of the University of California. All rights reserved.
@@ -29,7 +29,7 @@
.\"
.\" @(#)devname.3 8.2 (Berkeley) 4/29/95
.\"
-.Dd April 29, 1995
+.Dd June 3, 2012
.Dt DEVNAME 3
.Os
.Sh NAME
@@ -53,11 +53,6 @@ with a device number of
and a file type matching the one encoded in
.Fa type
which must be one of S_IFBLK or S_IFCHR.
-The device name is cached so that multiple calls with the same
-.Fa dev
-and
-.Fa type
-do not require additional queries of the device database file.
If no device matches the specified values, or no information is
available,
.Dv NULL
@@ -67,8 +62,8 @@ The traditional display for applications when no device is
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
diff --git a/lib/libc/gen/devname.c b/lib/libc/gen/devname.c
index e11d11f06fa..f6719108f41 100644
--- a/lib/libc/gen/devname.c
+++ b/lib/libc/gen/devname.c
@@ -1,7 +1,7 @@
-/* $NetBSD: devname.c,v 1.21 2010/03/23 20:28:59 drochner Exp $ */
+/* $NetBSD: devname.c,v 1.22 2012/06/03 21:42:46 joerg 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 */
+__RCSID("$NetBSD: devname.c,v 1.22 2012/06/03 21:42:46 joerg Exp $");
#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 */
+#ifdef __weak_alias
+__weak_alias(devname_r,_devname_r)
+#endif
-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;
+static once_t db_opened = ONCE_INITIALIZER;
+static struct cdbr *db;
+static devmajor_t pts;
-char *
-devname(dev, type)
- dev_t dev;
- mode_t type;
+static void
+devname_dbopen(void)
{
- 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);
+ db = cdbr_open(_PATH_DEVCDB, CDBR_DEFAULT);
+ pts = getdevmajor("pts", S_IFCHR);
+}
- /* see if we have this dev/type cached */
- pptr = devtb + (size_t)((dev + type) % DEV_SZ);
- ptr = *pptr;
+__CTASSERT(sizeof(dev_t) == 8);
- if (ptr && ptr->valid > 0 && ptr->dev == dev && ptr->type == type) {
- if (ptr->valid == VALID)
- return (ptr->name);
- return (NULL);
- }
+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;
+}
- if (ptr == NULL)
- *pptr = ptr = malloc(sizeof(DEVC));
-
- /*
- * 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_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;
}
diff --git a/lib/libc/gen/ttyname.3 b/lib/libc/gen/ttyname.3
index 42645dda1bd..eddfa0175ac 100644
--- a/lib/libc/gen/ttyname.3
+++ b/lib/libc/gen/ttyname.3
@@ -1,4 +1,4 @@
-.\" $NetBSD: ttyname.3,v 1.23 2012/05/31 23:11:35 joerg Exp $
+.\" $NetBSD: ttyname.3,v 1.24 2012/06/03 21:42:46 joerg Exp $
.\"
.\" Copyright (c) 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -106,7 +106,7 @@ device without requiring one to enumerate all of them in
.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
diff --git a/lib/libc/gen/ttyname.c b/lib/libc/gen/ttyname.c
index 6002c1e2ff0..4a9d997fadc 100644
--- a/lib/libc/gen/ttyname.c
+++ b/lib/libc/gen/ttyname.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ttyname.c,v 1.24 2008/06/25 11:47:29 ad Exp $ */
+/* $NetBSD: ttyname.c,v 1.25 2012/06/03 21:42:46 joerg Exp $ */
/*
* Copyright (c) 1988, 1993
@@ -34,53 +34,36 @@
#if 0
static char sccsid[] = "@(#)ttyname.c 8.2 (Berkeley) 1/27/94";
#else
-__RCSID("$NetBSD: ttyname.c,v 1.24 2008/06/25 11:47:29 ad Exp $");
+__RCSID("$NetBSD: ttyname.c,v 1.25 2012/06/03 21:42:46 joerg Exp $");
#endif
#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));
diff --git a/lib/libc/include/namespace.h b/lib/libc/include/namespace.h
index 5bb8270c2b9..584fbd7420f 100644
--- a/lib/libc/include/namespace.h
+++ b/lib/libc/include/namespace.h
@@ -1,4 +1,4 @@
-/* $NetBSD: namespace.h,v 1.153 2012/04/12 22:08:46 christos Exp $ */
+/* $NetBSD: namespace.h,v 1.154 2012/06/03 21:42:46 joerg Exp $ */
/*-
* Copyright (c) 1997-2004 The NetBSD Foundation, Inc.
@@ -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