diff options
author | 2016-12-09 17:24:55 +0000 | |
---|---|---|
committer | 2016-12-09 17:24:55 +0000 | |
commit | 0f3f7c4ee0345c0e321d5c6f0b708f4f7d37dbf1 (patch) | |
tree | cdbe4f28b0747af02e6ebe560f851091d4d8d4be | |
parent | log connections dropped in excess of MaxStartups at verbose LogLevel; (diff) | |
download | wireguard-openbsd-0f3f7c4ee0345c0e321d5c6f0b708f4f7d37dbf1.tar.xz wireguard-openbsd-0f3f7c4ee0345c0e321d5c6f0b708f4f7d37dbf1.zip |
New XenStore public API function to read numeric values
A need for a function to perform string to number conversion arose
when domain identifier needed to be read and converted to numerical
representation. With xbf(4) the usage became broader as greater
values (such as the sector count) needed to be converted. And as a
result another function was implemented to perform string to unsigned
long long conversion but unfortunately multiplication overflows were
not handled correctly. This new version consolidates the code in
one place and exports a proper XenStore API function to get and set
numeric values. The new atoull function borrows multiplication
overflow detection logic from the libc.
-rw-r--r-- | sys/dev/pv/xenstore.c | 70 | ||||
-rw-r--r-- | sys/dev/pv/xenvar.h | 4 |
2 files changed, 72 insertions, 2 deletions
diff --git a/sys/dev/pv/xenstore.c b/sys/dev/pv/xenstore.c index b55e934dfe4..fa057682ab9 100644 --- a/sys/dev/pv/xenstore.c +++ b/sys/dev/pv/xenstore.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xenstore.c,v 1.35 2016/12/07 15:21:04 mikeb Exp $ */ +/* $OpenBSD: xenstore.c,v 1.36 2016/12/09 17:24:55 mikeb Exp $ */ /* * Copyright (c) 2015 Mike Belopuhov @@ -863,6 +863,74 @@ xs_watch(void *xsc, const char *path, const char *property, struct task *task, return (0); } +static unsigned long long +atoull(const char *cp, int *error) +{ + unsigned long long res, cutoff; + int ch; + int cutlim; + + res = 0; + cutoff = ULLONG_MAX / (unsigned long long)10; + cutlim = ULLONG_MAX % (unsigned long long)10; + + do { + if (*cp < '0' || *cp > '9') { + *error = EINVAL; + return (res); + } + ch = *cp - '0'; + if (res > cutoff || (res == cutoff && ch > cutlim)) { + *error = ERANGE; + return (res); + } + res *= 10; + res += ch; + } while (*(++cp) != '\0'); + + *error = 0; + return (res); +} + +int +xs_getnum(void *xsc, const char *path, const char *property, + unsigned long long *val) +{ + char *buf; + int error = 0; + + buf = malloc(XS_MAX_PAYLOAD, M_DEVBUF, M_ZERO | + (cold ? M_NOWAIT : M_WAITOK)); + if (buf == NULL) + return (ENOMEM); + + error = xs_getprop(xsc, path, property, buf, XS_MAX_PAYLOAD); + if (error) + goto out; + + *val = atoull(buf, &error); + if (error) + goto out; + + out: + free(buf, M_DEVBUF, XS_MAX_PAYLOAD); + return (error); +} + +int +xs_setnum(void *xsc, const char *path, const char *property, + unsigned long long val) +{ + char buf[32]; + int ret; + + ret = snprintf(buf, sizeof(buf), "%llu", val); + if (ret == -1 || ret >= sizeof(buf)) + return (ERANGE); + + return (xs_setprop(xsc, path, property, buf, strlen(buf))); +} + int xs_getprop(void *xsc, const char *path, const char *property, char *value, int size) diff --git a/sys/dev/pv/xenvar.h b/sys/dev/pv/xenvar.h index 5d7bf147a7c..5c97d142b7f 100644 --- a/sys/dev/pv/xenvar.h +++ b/sys/dev/pv/xenvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: xenvar.h,v 1.42 2016/12/07 15:21:04 mikeb Exp $ */ +/* $OpenBSD: xenvar.h,v 1.43 2016/12/09 17:24:55 mikeb Exp $ */ /* * Copyright (c) 2015 Mike Belopuhov @@ -176,6 +176,8 @@ int xs_cmd(struct xs_transaction *, int, const char *, struct iovec **, void xs_resfree(struct xs_transaction *, struct iovec *, int); int xs_watch(void *, const char *, const char *, struct task *, void (*)(void *), void *); +int xs_getnum(void *, const char *, const char *, unsigned long long *); +int xs_setnum(void *, const char *, const char *, unsigned long long); int xs_getprop(void *, const char *, const char *, char *, int); int xs_setprop(void *, const char *, const char *, char *, int); int xs_kvop(void *, int, char *, char *, size_t); |