Index: sys/geom/geom_dev.c =================================================================== RCS file: /srv/ncvs/src/sys/geom/geom_dev.c,v retrieving revision 1.96 diff -u -r1.96 geom_dev.c --- sys/geom/geom_dev.c 16 Dec 2007 19:38:26 -0000 1.96 +++ sys/geom/geom_dev.c 15 Apr 2008 12:52:23 -0000 @@ -244,6 +244,7 @@ { struct g_geom *gp; struct g_consumer *cp; + struct g_provider *pp; struct g_kerneldump kd; off_t offset, length, chunk; int i, error; @@ -251,6 +252,7 @@ gp = dev->si_drv1; cp = dev->si_drv2; + pp = cp->provider; error = 0; KASSERT(cp->acr || cp->acw, @@ -329,6 +331,12 @@ case DIOCGIDENT: error = g_io_getattr("GEOM::ident", cp, &i, data); break; + case DIOCGPROVIDERNAME: + if (pp == NULL) + return (ENOENT); + + strlcpy(data, pp->name, MAXPATHLEN); + break; default: if (cp->provider->geom->ioctl != NULL) { Index: sys/sys/disk.h =================================================================== RCS file: /srv/ncvs/src/sys/sys/disk.h,v retrieving revision 1.42 diff -u -r1.42 disk.h --- sys/sys/disk.h 5 May 2007 17:02:19 -0000 1.42 +++ sys/sys/disk.h 15 Apr 2008 12:52:23 -0000 @@ -98,4 +98,9 @@ * - ident is optional and applications can't relay on its presence. */ +#define DIOCGPROVIDERNAME _IOR('d', 138, char[MAXPATHLEN]) + /*- + * Store the provider name, given a device path, in a buffer. + */ + #endif /* _SYS_DISK_H_ */ Index: lib/libgeom/geom_util.c =================================================================== RCS file: /srv/ncvs/src/lib/libgeom/geom_util.c,v retrieving revision 1.1 diff -u -r1.1 geom_util.c --- lib/libgeom/geom_util.c 6 May 2007 01:17:46 -0000 1.1 +++ lib/libgeom/geom_util.c 15 Apr 2008 12:52:23 -0000 @@ -234,3 +234,70 @@ } return (fd); } + +/* + * Return the provider name of a device given a partial or full path to its + * node. + */ +char * +g_provider_from_path(const char *devpath) +{ + struct stat st; + char path[MAXPATHLEN]; + char buffer[MAXPATHLEN]; + int fd; + + /* Use the device node if we're able to open it. */ + do { + fd = open(devpath, O_RDONLY); + if (fd < 0) + break; + + /* Make sure we're doing the ioctl on a device. */ + if (fstat(fd, &st) < 0) { + close(fd); + break; + } + if (!(S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) { + close(fd); + errno = EFTYPE; + break; + } + if (ioctl(fd, DIOCGPROVIDERNAME, buffer) < 0) { + close(fd); + if (errno == ENOTTY) + break; + errno = EFTYPE; + return (NULL); + } + close(fd); + return (strdup(buffer)); + } while (0); + + /* If we're not given an absolute path, assume /dev/ prefix. */ + if (*devpath != '/') { + snprintf(path, MAXPATHLEN, "%s%s", _PATH_DEV, devpath); + fd = open(path, O_RDONLY); + if (fd < 0) + return (NULL); + + /* Make sure we're doing the ioctl on a device. */ + if (fstat(fd, &st) < 0) { + close(fd); + return (NULL); + } + if (!(S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) { + close(fd); + errno = EFTYPE; + return (NULL); + } + if (ioctl(fd, DIOCGPROVIDERNAME, buffer) < 0) { + close(fd); + errno = EFTYPE; + return (NULL); + } + close(fd); + return (strdup(buffer)); + } + return (NULL); +} Index: lib/libgeom/libgeom.h =================================================================== RCS file: /srv/ncvs/src/lib/libgeom/libgeom.h,v retrieving revision 1.12 diff -u -r1.12 libgeom.h --- lib/libgeom/libgeom.h 6 May 2007 10:00:27 -0000 1.12 +++ lib/libgeom/libgeom.h 15 Apr 2008 12:52:23 -0000 @@ -154,6 +154,7 @@ int g_get_ident(int, char *, size_t); int g_get_name(const char *, char *, size_t); int g_open_by_ident(const char *, int, char *, size_t); +char *g_provider_from_path(const char *); __END_DECLS