From b01f409ffeda38212a2f6a62e1343526c7a8be98 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Mon, 28 Feb 2022 14:27:28 -0700 Subject: [PATCH] libdevctl: Add devctl_getpath Helper routine to call the kernel to get a path to the named device. Different path enumeration methods (called locators) can be used for different path types depending on what the kernel implements. Sponsored by: Netflix Reviewed by: jhb Differential Revision: https://reviews.freebsd.org/D32746 --- lib/libdevctl/devctl.3 | 15 +++++++++++++++ lib/libdevctl/devctl.c | 41 +++++++++++++++++++++++++++++++++++++++++ lib/libdevctl/devctl.h | 1 + 3 files changed, 57 insertions(+) diff --git a/lib/libdevctl/devctl.3 b/lib/libdevctl/devctl.3 index 34d1c03c2840..4299a81f783c 100644 --- a/lib/libdevctl/devctl.3 +++ b/lib/libdevctl/devctl.3 @@ -36,6 +36,7 @@ .Nm devctl_disable , .Nm devctl_enable , .Nm devctl_freeze , +.Nm devctl_getpath , .Nm devctl_rescan , .Nm devctl_reset , .Nm devctl_resume , @@ -62,6 +63,8 @@ .Ft int .Fn devctl_freeze "void" .Ft int +.Fn devctl_getpath "const char *device" "const char *locator" "char **buffer" +.Ft int .Fn devctl_rescan "const char *device" .Ft int .Fn devctl_reset "const char *device" "bool detach" @@ -199,6 +202,18 @@ function rescans a bus device checking for devices that have been added or removed. .Pp The +.Fn devctl_getpath +retrieves the path to the +.Fa device +from the kernel using the +.Fa locator +method to construct the path. +The +.Fa buffer +pointer is updated with an allocated buffer that must be freed with +.Xr free . +.Pp +The .Fn devctl_freeze function freezes probe and attach processing initiated in response to drivers being loaded. 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 #include #include +#include #include #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); +} diff --git a/lib/libdevctl/devctl.h b/lib/libdevctl/devctl.h index c6af8c480d47..05a6e8bec674 100644 --- a/lib/libdevctl/devctl.h +++ b/lib/libdevctl/devctl.h @@ -44,6 +44,7 @@ int devctl_delete(const char *device, bool force); int devctl_freeze(void); int devctl_thaw(void); int devctl_reset(const char *device, bool detach); +int devctl_getpath(const char *device, const char *locator, char **buffer); __END_DECLS #endif /* !__DEVCTL_H__ */