mirror of
https://github.com/systemd/systemd.git
synced 2024-11-01 17:51:22 +03:00
util-lib: introduce parse_percent() for parsing percent specifications
And port a couple of users over to it.
This commit is contained in:
parent
d9ab2bcf05
commit
9184ca48ea
@ -532,3 +532,22 @@ int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_percent(const char *p) {
|
||||
const char *pc, *n;
|
||||
unsigned v;
|
||||
int r;
|
||||
|
||||
pc = endswith(p, "%");
|
||||
if (!pc)
|
||||
return -EINVAL;
|
||||
|
||||
n = strndupa(p, pc - p);
|
||||
r = safe_atou(n, &v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (v > 100)
|
||||
return -ERANGE;
|
||||
|
||||
return (int) v;
|
||||
}
|
||||
|
@ -105,3 +105,5 @@ static inline int safe_atozu(const char *s, size_t *ret_u) {
|
||||
int safe_atod(const char *s, double *ret_d);
|
||||
|
||||
int parse_fractional_part_u(const char **s, size_t digits, unsigned *res);
|
||||
|
||||
int parse_percent(const char *p);
|
||||
|
@ -2774,7 +2774,7 @@ int config_parse_cpu_quota(
|
||||
void *userdata) {
|
||||
|
||||
CGroupContext *c = data;
|
||||
double percent;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
@ -2785,18 +2785,13 @@ int config_parse_cpu_quota(
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!endswith(rvalue, "%")) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "CPU quota '%s' not ending in '%%'. Ignoring.", rvalue);
|
||||
r = parse_percent(rvalue);
|
||||
if (r <= 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "CPU quota '%s' invalid. Ignoring.", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sscanf(rvalue, "%lf%%", &percent) != 1 || percent <= 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "CPU quota '%s' invalid. Ignoring.", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
c->cpu_quota_per_sec_usec = (usec_t) (percent * USEC_PER_SEC / 100);
|
||||
|
||||
c->cpu_quota_per_sec_usec = ((usec_t) r * USEC_PER_SEC) / 100U;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -843,7 +843,6 @@ int config_parse_tmpfs_size(
|
||||
void *userdata) {
|
||||
|
||||
size_t *sz = data;
|
||||
const char *e;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
@ -851,29 +850,17 @@ int config_parse_tmpfs_size(
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
e = endswith(rvalue, "%");
|
||||
if (e) {
|
||||
unsigned long ul;
|
||||
char *f;
|
||||
|
||||
errno = 0;
|
||||
ul = strtoul(rvalue, &f, 10);
|
||||
if (errno > 0 || f != e) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, errno, "Failed to parse percentage value, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ul <= 0 || ul >= 100) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Percentage value out of range, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*sz = PAGE_ALIGN((size_t) ((physical_memory() * (uint64_t) ul) / (uint64_t) 100));
|
||||
} else {
|
||||
/* First, try to parse as percentage */
|
||||
r = parse_percent(rvalue);
|
||||
if (r > 0 && r < 100)
|
||||
*sz = PAGE_ALIGN((size_t) ((physical_memory() * (uint64_t) r) / 100U));
|
||||
else {
|
||||
uint64_t k;
|
||||
|
||||
/* If the passed argument was not a percentage, or out of range, parse as byte size */
|
||||
|
||||
r = parse_size(rvalue, 1024, &k);
|
||||
if (r < 0 || (uint64_t) (size_t) k != k) {
|
||||
if (r < 0 || k <= 0 || (uint64_t) (size_t) k != k) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
@ -83,18 +83,14 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
|
||||
|
||||
if (isempty(eq))
|
||||
r = sd_bus_message_append(m, "sv", "CPUQuotaPerSecUSec", "t", USEC_INFINITY);
|
||||
else if (endswith(eq, "%")) {
|
||||
double percent;
|
||||
|
||||
if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
|
||||
log_error("CPU quota '%s' invalid.", eq);
|
||||
else {
|
||||
r = parse_percent(eq);
|
||||
if (r <= 0) {
|
||||
log_error_errno(r, "CPU quota '%s' invalid.", eq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = sd_bus_message_append(m, "sv", "CPUQuotaPerSecUSec", "t", (usec_t) percent * USEC_PER_SEC / 100);
|
||||
} else {
|
||||
log_error("CPU quota needs to be in percent.");
|
||||
return -EINVAL;
|
||||
r = sd_bus_message_append(m, "sv", "CPUQuotaPerSecUSec", "t", (usec_t) r * USEC_PER_SEC / 100U);
|
||||
}
|
||||
|
||||
goto finish;
|
||||
@ -110,6 +106,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
|
||||
char *n;
|
||||
usec_t t;
|
||||
size_t l;
|
||||
|
||||
r = parse_sec(eq, &t);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse %s= parameter: %s", field, eq);
|
||||
|
@ -475,6 +475,24 @@ static void test_safe_atod(void) {
|
||||
assert_se(*e == ',');
|
||||
}
|
||||
|
||||
static void test_parse_percent(void) {
|
||||
assert_se(parse_percent("") == -EINVAL);
|
||||
assert_se(parse_percent("foo") == -EINVAL);
|
||||
assert_se(parse_percent("0") == -EINVAL);
|
||||
assert_se(parse_percent("50") == -EINVAL);
|
||||
assert_se(parse_percent("100") == -EINVAL);
|
||||
assert_se(parse_percent("-1") == -EINVAL);
|
||||
assert_se(parse_percent("0%") == 0);
|
||||
assert_se(parse_percent("55%") == 55);
|
||||
assert_se(parse_percent("100%") == 100);
|
||||
assert_se(parse_percent("-7%") == -ERANGE);
|
||||
assert_se(parse_percent("107%") == -ERANGE);
|
||||
assert_se(parse_percent("%") == -EINVAL);
|
||||
assert_se(parse_percent("%%") == -EINVAL);
|
||||
assert_se(parse_percent("%1") == -EINVAL);
|
||||
assert_se(parse_percent("1%%") == -EINVAL);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
log_parse_environment();
|
||||
log_open();
|
||||
@ -488,6 +506,7 @@ int main(int argc, char *argv[]) {
|
||||
test_safe_atou16();
|
||||
test_safe_atoi16();
|
||||
test_safe_atod();
|
||||
test_parse_percent();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user