git: 7208b3b845a6 - main - libsa: Add a generic URI-syntax devspec parser
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 11 Sep 2026 05:04:23 UTC
The branch main has been updated by imp:
URL: https://cgit.FreeBSD.org/src/commit/?id=7208b3b845a6fca40099a4eab0d86afc2fb84aa7
commit 7208b3b845a6fca40099a4eab0d86afc2fb84aa7
Author: Warner Losh <imp@FreeBSD.org>
AuthorDate: 2026-09-11 04:13:37 +0000
Commit: Warner Losh <imp@FreeBSD.org>
CommitDate: 2026-09-11 04:15:28 +0000
libsa: Add a generic URI-syntax devspec parser
Add parse_uri(), a helper for devices whose devspec can take a
"[N]://host[:port][/path]" form in addition to the traditional "N:path"
form. It returns EINVAL when devspec doesn't match that pattern, so a
caller's own dv_parsedev can fall back to the traditional form.
Un-static default_parsedev() so it can serve as that fallback.
Sponsored by: Netflix
Differential Revision: https://reviews.freebsd.org/D59422
---
stand/libsa/dev.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
stand/libsa/stand.h | 2 ++
2 files changed, 66 insertions(+), 1 deletion(-)
diff --git a/stand/libsa/dev.c b/stand/libsa/dev.c
index 1edc843d508c..fdaa9a84bcc1 100644
--- a/stand/libsa/dev.c
+++ b/stand/libsa/dev.c
@@ -64,7 +64,7 @@ devformat(struct devdesc *d)
}
/* NB: devspec points to the remainder of the device name after dv_name */
-static int
+int
default_parsedev(struct devdesc **dev, const char *devspec,
const char **path)
{
@@ -102,6 +102,69 @@ fail:
return (err);
}
+/*
+ * Helper for URI-syntax devices. NB: like default_parsedev(), devspec is
+ * the remainder after dv_name. Parses "[N]://host[:port][/path]"; EINVAL
+ * if devspec doesn't match that pattern.
+ */
+int
+parse_uri(const char *devspec, int *unitp, char **hostp, int *portp,
+ const char **pathp)
+{
+ const char *cp, *p;
+ char *end;
+ int unit;
+
+ cp = devspec;
+ unit = 0;
+ if (*cp != '\0' && *cp != ':') {
+ errno = 0;
+ unit = strtol(cp, &end, 0);
+ if (errno != 0 || end == cp)
+ return (EINVAL);
+ cp = end;
+ }
+ if (strncmp(cp, "://", 3) != 0)
+ return (EINVAL);
+ cp += 3;
+
+ p = cp;
+ while (*p != '\0' && *p != '/' && *p != ':')
+ p++;
+ if (p == cp)
+ return (EINVAL); /* empty host */
+
+ *hostp = malloc(p - cp + 1);
+ if (*hostp == NULL)
+ return (ENOMEM);
+ memcpy(*hostp, cp, p - cp);
+ (*hostp)[p - cp] = '\0';
+
+ *portp = 0;
+ if (*p == ':') {
+ p++;
+ errno = 0;
+ *portp = strtol(p, &end, 10);
+ if (errno != 0 || end == p) {
+ free(*hostp);
+ *hostp = NULL;
+ return (EINVAL);
+ }
+ p = end;
+ }
+
+ if (*p != '\0' && *p != '/') {
+ free(*hostp);
+ *hostp = NULL;
+ return (EINVAL);
+ }
+
+ *unitp = unit;
+ if (pathp != NULL)
+ *pathp = p;
+ return (0);
+}
+
/* NB: devspec points to the whole device spec, and possible trailing path */
int
devparse(struct devdesc **dev, const char *devspec, const char **path)
diff --git a/stand/libsa/stand.h b/stand/libsa/stand.h
index 6e363b145595..b024247fcafb 100644
--- a/stand/libsa/stand.h
+++ b/stand/libsa/stand.h
@@ -196,6 +196,8 @@ struct devdesc {
char *devformat(struct devdesc *d);
int devparse(struct devdesc **, const char *, const char **);
+int default_parsedev(struct devdesc **, const char *, const char **);
+int parse_uri(const char *, int *, char **, int *, const char **);
int devinit(void);
void dev_cleanup(void);