Inspired by espie@'s ttyname.c diff, here's a simplification of libc's
fallback-to-scanning-/dev code for devname(). Since devname() returns
the "name under /dev", this eliminates the string manipulation == win!
Works when tested with "stat -Lf %Sr" on a symlink to a device with
/var/run/dev.db chmoded to 600.
ok?
Philip Guenther
Index: lib/libc/gen/devname.c
===================================================================
RCS file: /data/src/openbsd/src/lib/libc/gen/devname.c,v
retrieving revision 1.12
diff -u -p -r1.12 devname.c
--- lib/libc/gen/devname.c 13 Sep 2015 08:31:47 -0000 1.12
+++ lib/libc/gen/devname.c 28 Jun 2016 07:44:03 -0000
@@ -28,23 +28,20 @@
* SUCH DAMAGE.
*/
-#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <db.h>
#include <dirent.h>
#include <fcntl.h>
-#include <limits.h>
#include <paths.h>
#include <stdbool.h>
-#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static char *
devname_nodb(dev_t dev, mode_t type)
{
- static char buf[sizeof(_PATH_DEV) + NAME_MAX];
char *name = NULL;
struct dirent *dp;
struct stat sb;
@@ -52,19 +49,13 @@ devname_nodb(dev_t dev, mode_t type)
if ((dirp = opendir(_PATH_DEV)) == NULL)
return (NULL);
- if (strlcpy(buf, _PATH_DEV, sizeof(buf)) >= sizeof(buf))
- return (NULL);
while ((dp = readdir(dirp)) != NULL) {
if (dp->d_type != DT_UNKNOWN && DTTOIF(dp->d_type) != type)
continue;
- buf[sizeof(_PATH_DEV) - 1] = '\0';
- if (strlcat(buf, dp->d_name, sizeof(buf)) >= sizeof(buf))
- continue;
- if (lstat(buf, &sb) == -1)
- continue;
- if (sb.st_rdev != dev || (sb.st_mode & S_IFMT) != type)
+ if (fstatat(dirfd(dirp), dp->d_name, &sb, AT_SYMLINK_NOFOLLOW)
+ || sb.st_rdev != dev || (sb.st_mode & S_IFMT) != type)
continue;
- name = buf + sizeof(_PATH_DEV) - 1;
+ name = dp->d_name;
break;
}
closedir(dirp);