summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-02-23 03:13:54 +0100
committerLennart Poettering <lennart@poettering.net>2014-02-23 03:19:04 +0100
commit5556b5fe41173107a67dbe875fbd916a46e52a02 (patch)
treea9ca468b7c030c5c95a87bb35b4f986dedb1bba8 /src
parente342365c27ecae32a7f20ada0b2c623ce22e5ea8 (diff)
core: clean up some confusing regarding SI decimal and IEC binary suffixes for sizes
According to Wikipedia it is customary to specify hardware metrics and transfer speeds to the basis 1000 (SI decimal), while software metrics and physical volatile memory (RAM) sizes to the basis 1024 (IEC binary). So far we specified everything in IEC, let's fix that and be more true to what's otherwise customary. Since we don't want to parse "Mi" instead of "M" we document each time what the context used is.
Diffstat (limited to 'src')
-rw-r--r--src/core/load-fragment-gperf.gperf.m46
-rw-r--r--src/core/load-fragment.c14
-rw-r--r--src/journal/journald-gperf.gperf12
-rw-r--r--src/shared/conf-parser.c44
-rw-r--r--src/shared/conf-parser.h5
-rw-r--r--src/shared/util.c53
-rw-r--r--src/shared/util.h3
-rw-r--r--src/systemctl/systemctl.c4
-rw-r--r--src/test/test-util.c32
-rw-r--r--src/udev/net/link-config-gperf.gperf4
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)