1
0
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:
Lennart Poettering 2016-06-08 19:25:38 +02:00
parent d9ab2bcf05
commit 9184ca48ea
6 changed files with 59 additions and 40 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}