diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/load-fragment-gperf.gperf.m4 | 6 | ||||
-rw-r--r-- | src/core/load-fragment.c | 14 | ||||
-rw-r--r-- | src/journal/journald-gperf.gperf | 12 | ||||
-rw-r--r-- | src/shared/conf-parser.c | 44 | ||||
-rw-r--r-- | src/shared/conf-parser.h | 5 | ||||
-rw-r--r-- | src/shared/util.c | 53 | ||||
-rw-r--r-- | src/shared/util.h | 3 | ||||
-rw-r--r-- | src/systemctl/systemctl.c | 4 | ||||
-rw-r--r-- | src/test/test-util.c | 32 | ||||
-rw-r--r-- | src/udev/net/link-config-gperf.gperf | 4 |
10 files changed, 122 insertions, 55 deletions
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index e1bab7a264..26146b1927 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -219,12 +219,12 @@ Socket.Accept, config_parse_bool, 0, Socket.MaxConnections, config_parse_unsigned, 0, offsetof(Socket, max_connections) Socket.KeepAlive, config_parse_bool, 0, offsetof(Socket, keep_alive) Socket.Priority, config_parse_int, 0, offsetof(Socket, priority) -Socket.ReceiveBuffer, config_parse_bytes_size, 0, offsetof(Socket, receive_buffer) -Socket.SendBuffer, config_parse_bytes_size, 0, offsetof(Socket, send_buffer) +Socket.ReceiveBuffer, config_parse_iec_size, 0, offsetof(Socket, receive_buffer) +Socket.SendBuffer, config_parse_iec_size, 0, offsetof(Socket, send_buffer) Socket.IPTOS, config_parse_ip_tos, 0, offsetof(Socket, ip_tos) Socket.IPTTL, config_parse_int, 0, offsetof(Socket, ip_ttl) Socket.Mark, config_parse_int, 0, offsetof(Socket, mark) -Socket.PipeSize, config_parse_bytes_size, 0, offsetof(Socket, pipe_size) +Socket.PipeSize, config_parse_iec_size, 0, offsetof(Socket, pipe_size) Socket.FreeBind, config_parse_bool, 0, offsetof(Socket, free_bind) Socket.Transparent, config_parse_bool, 0, offsetof(Socket, transparent) Socket.Broadcast, config_parse_bool, 0, offsetof(Socket, broadcast) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 5b1e990921..82aed1eb92 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -2327,10 +2327,9 @@ int config_parse_memory_limit( assert_cc(sizeof(uint64_t) == sizeof(off_t)); - r = parse_bytes(rvalue, &bytes); + r = parse_size(rvalue, 1024, &bytes); if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Memory limit '%s' invalid. Ignoring.", rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Memory limit '%s' invalid. Ignoring.", rvalue); return 0; } @@ -2563,10 +2562,9 @@ int config_parse_blockio_bandwidth( return 0; } - r = parse_bytes(bandwidth, &bytes); + r = parse_size(bandwidth, 1000, &bytes); if (r < 0 || bytes <= 0) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue); return 0; } @@ -2964,7 +2962,9 @@ void unit_dump_config_items(FILE *f) { #endif { config_parse_int, "INTEGER" }, { config_parse_unsigned, "UNSIGNED" }, - { config_parse_bytes_size, "SIZE" }, + { config_parse_iec_size, "SIZE" }, + { config_parse_iec_off, "SIZE" }, + { config_parse_si_size, "SIZE" }, { config_parse_bool, "BOOLEAN" }, { config_parse_string, "STRING" }, { config_parse_path, "PATH" }, diff --git a/src/journal/journald-gperf.gperf b/src/journal/journald-gperf.gperf index 2ecba3bd0e..84efee3176 100644 --- a/src/journal/journald-gperf.gperf +++ b/src/journal/journald-gperf.gperf @@ -21,12 +21,12 @@ Journal.Seal, config_parse_bool, 0, offsetof(Server, seal) Journal.SyncIntervalSec, config_parse_sec, 0, offsetof(Server, sync_interval_usec) Journal.RateLimitInterval, config_parse_sec, 0, offsetof(Server, rate_limit_interval) Journal.RateLimitBurst, config_parse_unsigned, 0, offsetof(Server, rate_limit_burst) -Journal.SystemMaxUse, config_parse_bytes_off, 0, offsetof(Server, system_metrics.max_use) -Journal.SystemMaxFileSize, config_parse_bytes_off, 0, offsetof(Server, system_metrics.max_size) -Journal.SystemKeepFree, config_parse_bytes_off, 0, offsetof(Server, system_metrics.keep_free) -Journal.RuntimeMaxUse, config_parse_bytes_off, 0, offsetof(Server, runtime_metrics.max_use) -Journal.RuntimeMaxFileSize, config_parse_bytes_off, 0, offsetof(Server, runtime_metrics.max_size) -Journal.RuntimeKeepFree, config_parse_bytes_off, 0, offsetof(Server, runtime_metrics.keep_free) +Journal.SystemMaxUse, config_parse_iec_off, 0, offsetof(Server, system_metrics.max_use) +Journal.SystemMaxFileSize, config_parse_iec_off, 0, offsetof(Server, system_metrics.max_size) +Journal.SystemKeepFree, config_parse_iec_off, 0, offsetof(Server, system_metrics.keep_free) +Journal.RuntimeMaxUse, config_parse_iec_off, 0, offsetof(Server, runtime_metrics.max_use) +Journal.RuntimeMaxFileSize, config_parse_iec_off, 0, offsetof(Server, runtime_metrics.max_size) +Journal.RuntimeKeepFree, config_parse_iec_off, 0, offsetof(Server, runtime_metrics.keep_free) Journal.MaxRetentionSec, config_parse_sec, 0, offsetof(Server, max_retention_usec) Journal.MaxFileSec, config_parse_sec, 0, offsetof(Server, max_file_usec) Journal.ForwardToSyslog, config_parse_bool, 0, offsetof(Server, forward_to_syslog) diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index dde62b5755..cfa669b113 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -447,8 +447,7 @@ DEFINE_PARSER(double, double, safe_atod) DEFINE_PARSER(nsec, nsec_t, parse_nsec) DEFINE_PARSER(sec, usec_t, parse_sec) - -int config_parse_bytes_size(const char* unit, +int config_parse_iec_size(const char* unit, const char *filename, unsigned line, const char *section, @@ -468,10 +467,9 @@ int config_parse_bytes_size(const char* unit, assert(rvalue); assert(data); - r = parse_bytes(rvalue, &o); + r = parse_size(rvalue, 1024, &o); if (r < 0 || (off_t) (size_t) o != o) { - log_syntax(unit, LOG_ERR, filename, line, -r, - "Failed to parse byte value, ignoring: %s", rvalue); + log_syntax(unit, LOG_ERR, filename, line, r < 0 ? -r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue); return 0; } @@ -479,8 +477,37 @@ int config_parse_bytes_size(const char* unit, return 0; } +int config_parse_si_size(const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + size_t *sz = data; + off_t o; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = parse_size(rvalue, 1000, &o); + if (r < 0 || (off_t) (size_t) o != o) { + log_syntax(unit, LOG_ERR, filename, line, r < 0 ? -r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue); + return 0; + } + + *sz = (size_t) o; + return 0; +} -int config_parse_bytes_off(const char* unit, +int config_parse_iec_off(const char* unit, const char *filename, unsigned line, const char *section, @@ -501,10 +528,9 @@ int config_parse_bytes_off(const char* unit, assert_cc(sizeof(off_t) == sizeof(uint64_t)); - r = parse_bytes(rvalue, bytes); + r = parse_size(rvalue, 1024, bytes); if (r < 0) - log_syntax(unit, LOG_ERR, filename, line, -r, - "Failed to parse bytes value, ignoring: %s", rvalue); + log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to parse size value, ignoring: %s", rvalue); return 0; } diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h index ebbcaa54fe..4ccdaddd29 100644 --- a/src/shared/conf-parser.h +++ b/src/shared/conf-parser.h @@ -97,8 +97,9 @@ int config_parse_unsigned(const char *unit, const char *filename, unsigned line, int config_parse_long(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_uint64(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_double(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); -int config_parse_bytes_size(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); -int config_parse_bytes_off(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_iec_size(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_si_size(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_iec_off(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bool(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_show_status(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_string(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); diff --git a/src/shared/util.c b/src/shared/util.c index b33f1203e6..5cb598c4c5 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -2135,11 +2135,28 @@ ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) { return n; } -int parse_bytes(const char *t, off_t *bytes) { - static const struct { +int parse_size(const char *t, off_t base, off_t *size) { + + /* Soo, sometimes we want to parse IEC binary suffxies, and + * sometimes SI decimal suffixes. This function can parse + * both. Which one is the right way depends on the + * context. Wikipedia suggests that SI is customary for + * hardrware metrics and network speeds, while IEC is + * customary for most data sizes used by software and volatile + * (RAM) memory. Hence be careful which one you pick! + * + * In either case we use just K, M, G as suffix, and not Ki, + * Mi, Gi or so (as IEC would suggest). That's because that's + * frickin' ugly. But this means you really need to make sure + * to document which base you are parsing when you use this + * call. */ + + struct table { const char *suffix; unsigned long long factor; - } table[] = { + }; + + static const struct table iec[] = { { "B", 1 }, { "K", 1024ULL }, { "M", 1024ULL*1024ULL }, @@ -2150,11 +2167,33 @@ int parse_bytes(const char *t, off_t *bytes) { { "", 1 }, }; + static const struct table si[] = { + { "B", 1 }, + { "K", 1000ULL }, + { "M", 1000ULL*1000ULL }, + { "G", 1000ULL*1000ULL*1000ULL }, + { "T", 1000ULL*1000ULL*1000ULL*1000ULL }, + { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL }, + { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL }, + { "", 1 }, + }; + + const struct table *table; const char *p; unsigned long long r = 0; + unsigned n_entries; assert(t); - assert(bytes); + assert(base == 1000 || base == 1024); + assert(size); + + if (base == 1000) { + table = si; + n_entries = ELEMENTSOF(si); + } else { + table = iec; + n_entries = ELEMENTSOF(iec); + } p = t; do { @@ -2176,7 +2215,7 @@ int parse_bytes(const char *t, off_t *bytes) { e += strspn(e, WHITESPACE); - for (i = 0; i < ELEMENTSOF(table); i++) + for (i = 0; i < n_entries; i++) if (startswith(e, table[i].suffix)) { unsigned long long tmp; if ((unsigned long long) l > ULLONG_MAX / table[i].factor) @@ -2193,12 +2232,12 @@ int parse_bytes(const char *t, off_t *bytes) { break; } - if (i >= ELEMENTSOF(table)) + if (i >= n_entries) return -EINVAL; } while (*p); - *bytes = r; + *size = r; return 0; } diff --git a/src/shared/util.h b/src/shared/util.h index d1230d2b64..9913fcefae 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -144,8 +144,9 @@ int close_nointr(int fd); void close_nointr_nofail(int fd); void close_many(const int fds[], unsigned n_fd); +int parse_size(const char *t, off_t base, off_t *size); + int parse_boolean(const char *v) _pure_; -int parse_bytes(const char *t, off_t *bytes); int parse_pid(const char *s, pid_t* ret_pid); int parse_uid(const char *s, uid_t* ret_uid); #define parse_gid(s, ret_uid) parse_uid(s, ret_uid) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 3375bac985..c5ca8dc11d 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -4045,7 +4045,7 @@ static int append_assignment(sd_bus_message *m, const char *assignment) { } else if (streq(field, "MemoryLimit")) { off_t bytes; - r = parse_bytes(eq, &bytes); + r = parse_size(eq, 1024, &bytes); if (r < 0) { log_error("Failed to parse bytes specification %s", assignment); return -EINVAL; @@ -4115,7 +4115,7 @@ static int append_assignment(sd_bus_message *m, const char *assignment) { return -EINVAL; } - r = parse_bytes(bandwidth, &bytes); + r = parse_size(bandwidth, 1000, &bytes); if (r < 0) { log_error("Failed to parse byte value %s.", bandwidth); return -EINVAL; diff --git a/src/test/test-util.c b/src/test/test-util.c index 1ac4a1edd1..b718206e86 100644 --- a/src/test/test-util.c +++ b/src/test/test-util.c @@ -435,42 +435,42 @@ static void test_protect_errno(void) { assert(errno == 12); } -static void test_parse_bytes(void) { +static void test_parse_size(void) { off_t bytes; - assert_se(parse_bytes("111", &bytes) == 0); + assert_se(parse_size("111", 1024, &bytes) == 0); assert_se(bytes == 111); - assert_se(parse_bytes(" 112 B", &bytes) == 0); + assert_se(parse_size(" 112 B", 1024, &bytes) == 0); assert_se(bytes == 112); - assert_se(parse_bytes("3 K", &bytes) == 0); + assert_se(parse_size("3 K", 1024, &bytes) == 0); assert_se(bytes == 3*1024); - assert_se(parse_bytes(" 4 M 11K", &bytes) == 0); + assert_se(parse_size(" 4 M 11K", 1024, &bytes) == 0); assert_se(bytes == 4*1024*1024 + 11 * 1024); - assert_se(parse_bytes("3B3G", &bytes) == 0); + assert_se(parse_size("3B3G", 1024, &bytes) == 0); assert_se(bytes == 3ULL*1024*1024*1024 + 3); - assert_se(parse_bytes("3B3G4T", &bytes) == 0); + assert_se(parse_size("3B3G4T", 1024, &bytes) == 0); assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3); - assert_se(parse_bytes("12P", &bytes) == 0); + assert_se(parse_size("12P", 1024, &bytes) == 0); assert_se(bytes == 12ULL * 1024*1024*1024*1024*1024); - assert_se(parse_bytes("3E 2P", &bytes) == 0); + assert_se(parse_size("3E 2P", 1024, &bytes) == 0); assert_se(bytes == (3 * 1024 + 2ULL) * 1024*1024*1024*1024*1024); - assert_se(parse_bytes("12X", &bytes) == -EINVAL); + assert_se(parse_size("12X", 1024, &bytes) == -EINVAL); - assert_se(parse_bytes("1024E", &bytes) == -ERANGE); - assert_se(parse_bytes("-1", &bytes) == -ERANGE); - assert_se(parse_bytes("-1024E", &bytes) == -ERANGE); + assert_se(parse_size("1024E", 1024, &bytes) == -ERANGE); + assert_se(parse_size("-1", 1024, &bytes) == -ERANGE); + assert_se(parse_size("-1024E", 1024, &bytes) == -ERANGE); - assert_se(parse_bytes("-1024P", &bytes) == -ERANGE); + assert_se(parse_size("-1024P", 1024, &bytes) == -ERANGE); - assert_se(parse_bytes("-10B 20K", &bytes) == -ERANGE); + assert_se(parse_size("-10B 20K", 1024, &bytes) == -ERANGE); } static void test_strextend(void) { @@ -617,7 +617,7 @@ int main(int argc, char *argv[]) { test_u64log2(); test_get_process_comm(); test_protect_errno(); - test_parse_bytes(); + test_parse_size(); test_strextend(); test_strrep(); test_split_pair(); diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf index 3384ca0418..819e93c4d7 100644 --- a/src/udev/net/link-config-gperf.gperf +++ b/src/udev/net/link-config-gperf.gperf @@ -30,7 +30,7 @@ Link.MACAddress, config_parse_hwaddr, 0, Link.NamePolicy, config_parse_name_policy, 0, offsetof(link_config, name_policy) Link.Name, config_parse_ifname, 0, offsetof(link_config, name) Link.Alias, config_parse_ifalias, 0, offsetof(link_config, alias) -Link.MTUBytes, config_parse_bytes_size, 0, offsetof(link_config, mtu) -Link.BitsPerSecond, config_parse_bytes_size, 0, offsetof(link_config, speed) +Link.MTUBytes, config_parse_iec_size, 0, offsetof(link_config, mtu) +Link.BitsPerSecond, config_parse_si_size, 0, offsetof(link_config, speed) Link.Duplex, config_parse_duplex, 0, offsetof(link_config, duplex) Link.WakeOnLan, config_parse_wol, 0, offsetof(link_config, wol) |