diff options
| author | Warner Losh <imp@FreeBSD.org> | 2022-02-28 21:27:28 +0000 |
|---|---|---|
| committer | Warner Losh <imp@FreeBSD.org> | 2022-03-01 15:06:41 +0000 |
| commit | b01f409ffeda38212a2f6a62e1343526c7a8be98 (patch) | |
| tree | d42a84f32f3eb54a59a11d0847b67402e2c39694 /lib/libdevctl/devctl.c | |
| parent | 38e942a3452fed040d1e344da25187aa54696eeb (diff) | |
Diffstat (limited to 'lib/libdevctl/devctl.c')
| -rw-r--r-- | lib/libdevctl/devctl.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/lib/libdevctl/devctl.c b/lib/libdevctl/devctl.c index 528e3a3c407a..8a1f6bbc9d39 100644 --- a/lib/libdevctl/devctl.c +++ b/lib/libdevctl/devctl.c @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <errno.h> #include <fcntl.h> +#include <stdlib.h> #include <string.h> #include "devctl.h" @@ -166,3 +167,43 @@ devctl_reset(const char *device, bool detach) return (devctl_simple_request(DEV_RESET, device, detach ? DEVF_RESET_DETACH : 0)); } + +#define BUFLEN 1024 + +int +devctl_getpath(const char *device, const char *locator, char **buffer) +{ + struct devreq req; + int serrno; + + memset(&req, 0, sizeof(req)); + if (strlcpy(req.dr_name, device, sizeof(req.dr_name)) >= + sizeof(req.dr_name)) { + errno = EINVAL; + *buffer = NULL; + return (-1); + } + + /* + * Maybe do the request twice. Once to get the length, and then again to + * get the string if BUFLEN bytes is insufficient. + */ + req.dr_flags = 0; + req.dr_buffer.length = BUFLEN; +again: + req.dr_buffer.buffer = malloc(req.dr_buffer.length); + strlcpy(req.dr_buffer.buffer, locator, req.dr_buffer.length); + if (devctl_request(DEV_GET_PATH, &req) == 0) { + *buffer = req.dr_buffer.buffer; + return (0); + } + if (errno == ENAMETOOLONG && req.dr_buffer.length != BUFLEN) { + free(req.dr_buffer.buffer); + goto again; + } + serrno = errno; + free(req.dr_buffer.buffer); + errno = serrno; + *buffer = NULL; + return (-1); +} |
