From f805931ffeead47dff1991818f5d5a725b319401 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Wed, 26 Aug 2015 17:55:08 +0200 Subject: [PATCH 1/5] mx_util: Add mxq_strto{seconds,minutes}() --- mx_util.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++ mx_util.h | 3 ++ test_mx_util.c | 64 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+) diff --git a/mx_util.c b/mx_util.c index b6f404b..1e92deb 100644 --- a/mx_util.c +++ b/mx_util.c @@ -79,6 +79,88 @@ inline int mx_stribeginswithany(char *str, char **starts, char **endptr) return _mx_strbeginswithany(str, starts, endptr, 1); } +inline int mx_strtoseconds(char *str, unsigned long long int *seconds) +{ + unsigned long long int s = 0; + unsigned long long int t; + + char *end; + + if (!str || !*str) + return -(errno=EINVAL); + + if (strchr(str, '-')) + return -(errno=ERANGE); + + do { + errno = 0; + t = strtoull(str, &end, 10); + + if (errno) + return -errno; + + if (str == end) + return -(errno=EINVAL); + + for (;*end && *end == ' '; end++) + /* empty */; + + //if (mx_strtounit(end, &end)); + + switch (*end) { + + case 'y': /* years */ + t *= 52; + + case 'w': /* weeks */ + t *= 7; + + case 'd': /* days */ + t *= 24; + + case 'h': /* hours */ + t *= 60; + + case 'm': /* minutes */ + t *= 60; + + case 's': /* seconds */ + end++; + break; + + default: + return -(errno=EINVAL); + } + + if (s+t < s) + return -(errno=ERANGE); + + s += t; + + for (;*end && *end == ' '; end++) + /* empty */; + + str = end; + + } while (*str); + + *seconds = s; + + return 0; +} + +inline int mx_strtominutes(char *str, unsigned long long int *minutes) +{ + int res; + + res = mx_strtoseconds(str, minutes); + + if (res >= 0) + *minutes /= 60; + + return res; +} + inline char *mx_strskipwhitespaces(char *str) { char *s; diff --git a/mx_util.h b/mx_util.h index 227007b..aad1aff 100644 --- a/mx_util.h +++ b/mx_util.h @@ -67,6 +67,9 @@ int mx_strbeginswithany(char *str, char **starts, char **endptr); char *mx_strskipwhitespaces(char *str); +int mx_strtoseconds(char *str, unsigned long long int *seconds); +int mx_strtominutes(char *str, unsigned long long int *minutes); + int mx_strtoul(char *str, unsigned long int *to); int mx_strtoull(char *str, unsigned long long int *to); diff --git a/test_mx_util.c b/test_mx_util.c index 5bb570b..1ffcfe9 100644 --- a/test_mx_util.c +++ b/test_mx_util.c @@ -181,6 +181,68 @@ static void test_mx_strbeginswithany(void) assert(end == NULL); } +static void test_mx_strtoseconds(void) +{ + unsigned long long int l; + + assert(mx_strtoseconds("123s", &l) == 0); + assert(l == 123); + + assert(mx_strtoseconds("0123s", &l) == 0); + assert(l == 123); + + assert(mx_strtoseconds("123s0s", &l) == 0); + assert(l == 123); + + assert(mx_strtoseconds("2m3s", &l) == 0); + assert(l == 123); + + assert(mx_strtoseconds(" 2 m 3 s ", &l) == 0); + assert(l == 123); + + assert(mx_strtoseconds("1h 2m 3s", &l) == 0); + assert(l == 60*60 + 2*60 + 3); + + assert(mx_strtoseconds("2m 3s 1h", &l) == 0); + assert(l == 60*60 + 2*60 + 3); + + assert(mx_strtoseconds("2m 3s 1h1y", &l) == 0); + assert(l == 60*60 + 2*60 + 3 + 52*7*24*60*60); + + assert(mx_strtoseconds("2m 3s 1h1y", &l) == 0); + assert(l == 60*60 + 2*60 + 3 + 52*7*24*60*60); + + assert(mx_strtoseconds("-1", &l) == -ERANGE); + assert(mx_strtoseconds(" -1", &l) == -ERANGE); + + assert(mx_strtoseconds("123", &l) == -EINVAL); + assert(mx_strtoseconds("0123", &l) == -EINVAL); + assert(mx_strtoseconds("1.2", &l) == -EINVAL); + assert(mx_strtoseconds("1,2", &l) == -EINVAL); + assert(mx_strtoseconds("test", &l) == -EINVAL); +} + +static void test_mx_strtominutes(void) +{ + unsigned long long int l; + + assert(mx_strtominutes("123s", &l) == 0); + assert(l == 2); + + assert(mx_strtominutes("20d", &l) == 0); + assert(l == 20*24*60); + + + assert(mx_strtominutes("-1", &l) == -ERANGE); + assert(mx_strtominutes(" -1", &l) == -ERANGE); + + assert(mx_strtominutes("123", &l) == -EINVAL); + assert(mx_strtominutes("0123", &l) == -EINVAL); + assert(mx_strtominutes("1.2", &l) == -EINVAL); + assert(mx_strtominutes("1,2", &l) == -EINVAL); + assert(mx_strtominutes("test", &l) == -EINVAL); +} + int main(int argc, char *argv[]) { test_mx_strskipwhitespaces(); @@ -191,5 +253,7 @@ int main(int argc, char *argv[]) test_mx_strbeginswith(); test_mx_stribeginswith(); test_mx_strbeginswithany(); + test_mx_strtoseconds(); + test_mx_strtominutes(); return 0; } From 366ae7fe642a60e4e80b6f57e5389ed3fc7b3084 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Wed, 26 Aug 2015 17:55:50 +0200 Subject: [PATCH 2/5] mxqsub: Use mx_strtominutes() to parse --runtime option --- mxqsub.c | 14 ++++++++++++-- test_mx_util.c | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/mxqsub.c b/mxqsub.c index d4d8eb2..15c9ba9 100644 --- a/mxqsub.c +++ b/mxqsub.c @@ -784,8 +784,18 @@ int main(int argc, char *argv[]) mx_log_warning("option '--time' is deprecated. please use '--runtime' or '-t' in future calls."); case 't': if (mx_strtou32(optctl.optarg, &arg_time) < 0) { - mx_log_crit("--runtime '%s': %m", optctl.optarg); - exit(EX_CONFIG); + unsigned long long int minutes; + + if(mx_strtominutes(optctl.optarg, &minutes) < 0) { + mx_log_crit("--runtime '%s': %m", optctl.optarg); + exit(EX_CONFIG); + } + if ((unsigned long long int)(uint32_t)minutes != minutes) { + errno = ERANGE; + mx_log_crit("--runtime '%s': %m", optctl.optarg); + exit(EX_CONFIG); + } + arg_time = (uint32_t)minutes; } break; diff --git a/test_mx_util.c b/test_mx_util.c index 1ffcfe9..d4ba5db 100644 --- a/test_mx_util.c +++ b/test_mx_util.c @@ -44,6 +44,7 @@ static void test_mx_strtoul(void) assert(mx_strtoul("-1", &l) == -ERANGE); assert(mx_strtoul(" -1", &l) == -ERANGE); + assert(mx_strtoul("123s", &l) == -EINVAL); assert(mx_strtoul("0888", &l) == -EINVAL); assert(mx_strtoul("1.2", &l) == -EINVAL); assert(mx_strtoul("1,2", &l) == -EINVAL); From b92053b6828998f7d4b96d18b55e1daa56ff4f22 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Wed, 26 Aug 2015 18:15:26 +0200 Subject: [PATCH 3/5] mx_util: Add mxq_strtobytes() --- mx_util.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++ mx_util.h | 2 ++ test_mx_util.c | 28 +++++++++++++++++++++ 3 files changed, 96 insertions(+) diff --git a/mx_util.c b/mx_util.c index 1e92deb..199bcd5 100644 --- a/mx_util.c +++ b/mx_util.c @@ -79,6 +79,72 @@ inline int mx_stribeginswithany(char *str, char **starts, char **endptr) return _mx_strbeginswithany(str, starts, endptr, 1); } +inline int mx_strtobytes(char *str, unsigned long long int *bytes) +{ + unsigned long long int s = 0; + unsigned long long int t; + + char *end; + + if (!str || !*str) + return -(errno=EINVAL); + + if (strchr(str, '-')) + return -(errno=ERANGE); + + do { + errno = 0; + t = strtoull(str, &end, 10); + + if (errno) + return -errno; + + if (str == end) + return -(errno=EINVAL); + + for (;*end && *end == ' '; end++) + /* empty */; + + switch (*end) { + + case 'T': /* tebi */ + t *= 1024; + + case 'G': /* gibi */ + t *= 1024; + + case 'M': /* mebi */ + t *= 1024; + + case 'k': /* kibi */ + case 'K': + t *= 1024; + + case 'B': /* bytes */ + end++; + break; + + default: + return -(errno=EINVAL); + } + + if (s+t < s) + return -(errno=ERANGE); + + s += t; + + for (;*end && *end == ' '; end++) + /* empty */; + + str = end; + + } while (*str); + + *bytes = s; + + return 0; +} + inline int mx_strtoseconds(char *str, unsigned long long int *seconds) { unsigned long long int s = 0; diff --git a/mx_util.h b/mx_util.h index aad1aff..d805aef 100644 --- a/mx_util.h +++ b/mx_util.h @@ -67,6 +67,8 @@ int mx_strbeginswithany(char *str, char **starts, char **endptr); char *mx_strskipwhitespaces(char *str); +int mx_strtobytes(char *str, unsigned long long int *bytes); + int mx_strtoseconds(char *str, unsigned long long int *seconds); int mx_strtominutes(char *str, unsigned long long int *minutes); diff --git a/test_mx_util.c b/test_mx_util.c index d4ba5db..66dd776 100644 --- a/test_mx_util.c +++ b/test_mx_util.c @@ -244,6 +244,33 @@ static void test_mx_strtominutes(void) assert(mx_strtominutes("test", &l) == -EINVAL); } +static void test_mx_strtobytes(void) +{ + unsigned long long int l; + + assert(mx_strtobytes("123B", &l) == 0); + assert(l == 123); + + assert(mx_strtobytes("2M", &l) == 0); + assert(l == 2*1024*1024); + + assert(mx_strtobytes("1M1024k", &l) == 0); + assert(l == 2*1024*1024); + + assert(mx_strtobytes("1024k1024K", &l) == 0); + assert(l == 2*1024*1024); + + assert(mx_strtobytes("-1", &l) == -ERANGE); + assert(mx_strtobytes(" -1", &l) == -ERANGE); + + assert(mx_strtobytes("2.5M", &l) == -EINVAL); + assert(mx_strtobytes("123", &l) == -EINVAL); + assert(mx_strtobytes("0123", &l) == -EINVAL); + assert(mx_strtobytes("1.2", &l) == -EINVAL); + assert(mx_strtobytes("1,2", &l) == -EINVAL); + assert(mx_strtobytes("test", &l) == -EINVAL); +} + int main(int argc, char *argv[]) { test_mx_strskipwhitespaces(); @@ -256,5 +283,6 @@ int main(int argc, char *argv[]) test_mx_strbeginswithany(); test_mx_strtoseconds(); test_mx_strtominutes(); + test_mx_strtobytes(); return 0; } From e9222d8ceaed9277310005198fcebac2cabf0347 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Wed, 26 Aug 2015 18:15:54 +0200 Subject: [PATCH 4/5] mxqsub: Use mx_strtobytes() to parse --memory option --- mxqsub.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mxqsub.c b/mxqsub.c index 15c9ba9..5a48b0c 100644 --- a/mxqsub.c +++ b/mxqsub.c @@ -775,8 +775,13 @@ int main(int argc, char *argv[]) case 'm': if (mx_strtou64(optctl.optarg, &arg_memory) < 0) { - mx_log_crit("--memory '%s': %m", optctl.optarg); - exit(EX_CONFIG); + unsigned long long int bytes; + + if(mx_strtobytes(optctl.optarg, &bytes) < 0) { + mx_log_crit("--memory '%s': %m", optctl.optarg); + exit(EX_CONFIG); + } + arg_memory = bytes/1024/1024; } break; From 1cf63064ad814f838125cc68233d452e343f416a Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Wed, 26 Aug 2015 18:20:22 +0200 Subject: [PATCH 5/5] mxqd: Use mx_strtobytes() to parse --memory and --max-memory-per-slot options --- mxqd.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/mxqd.c b/mxqd.c index b5e6697..8bd485c 100644 --- a/mxqd.c +++ b/mxqd.c @@ -290,8 +290,13 @@ int server_init(struct mxq_server *server, int argc, char *argv[]) case 'm': if (mx_strtoul(optctl.optarg, &memory_total) < 0) { - mx_log_err("Invalid argument supplied for option --memory '%s': %m", optctl.optarg); - exit(1); + unsigned long long int bytes; + + if(mx_strtobytes(optctl.optarg, &bytes) < 0) { + mx_log_err("Invalid argument supplied for option --memory '%s': %m", optctl.optarg); + exit(1); + } + memory_total = bytes/1024/1024; } if (!memory_total) memory_total = 2048; @@ -299,8 +304,13 @@ int server_init(struct mxq_server *server, int argc, char *argv[]) case 'x': if (mx_strtoul(optctl.optarg, &memory_max) < 0) { - mx_log_err("Invalid argument supplied for option --max-memory-per-slot '%s': %m", optctl.optarg); - exit(1); + unsigned long long int bytes; + + if(mx_strtobytes(optctl.optarg, &bytes) < 0) { + mx_log_err("Invalid argument supplied for option --max-memory-per-slot '%s': %m", optctl.optarg); + exit(1); + } + memory_max = bytes/1024/1024; } break;