summaryrefslogtreecommitdiff
path: root/libmailutils
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2020-08-08 23:19:11 +0300
committerSergey Poznyakoff <gray@gnu.org>2020-08-08 23:32:42 +0300
commitfd9a86d37b96789d59e25e64b5d9db8974158a2c (patch)
treeb9e48255ed4dce2167d01812d41de521e53d07fb /libmailutils
parent0fe801338b9dd8387caa6f69daf9435744a5a6b2 (diff)
downloadmailutils-fd9a86d37b96789d59e25e64b5d9db8974158a2c.tar.gz
mailutils-fd9a86d37b96789d59e25e64b5d9db8974158a2c.tar.bz2
New function: mu_strtosize
* include/mailutils/cstr.h (mu_strtosize): New proto. * libmailutils/string/strtosize.c: New file. * libmailutils/string/Makefile.am: Add strtosize.c * libmailutils/string/str_to_c.c: Implement conversions for mu_c_hsize. * include/mailutils/util.h (mu_c_hsize): New mu_c_type, * libmailutils/tests/strtoc.c: Add tests for mu_c_hsize. * libmu_auth/ldap.c: Use mu_strtosize to parse quota. * mda/lib/mailquota.c: Likewise.
Diffstat (limited to 'libmailutils')
-rw-r--r--libmailutils/string/Makefile.am1
-rw-r--r--libmailutils/string/str_to_c.c13
-rw-r--r--libmailutils/string/strtosize.c132
-rw-r--r--libmailutils/tests/strtoc.c23
4 files changed, 165 insertions, 4 deletions
diff --git a/libmailutils/string/Makefile.am b/libmailutils/string/Makefile.am
index 7afa8b801..644ed733d 100644
--- a/libmailutils/string/Makefile.am
+++ b/libmailutils/string/Makefile.am
@@ -38,6 +38,7 @@ libstring_la_SOURCES = \
stripws.c\
strlst.c\
strrtrim.c\
+ strtosize.c\
trueans.c\
unfold.c\
asnprintf.c\
diff --git a/libmailutils/string/str_to_c.c b/libmailutils/string/str_to_c.c
index cb401722d..7676a0d7a 100644
--- a/libmailutils/string/str_to_c.c
+++ b/libmailutils/string/str_to_c.c
@@ -31,6 +31,7 @@
#include <mailutils/cctype.h>
#include <mailutils/io.h>
#include <mailutils/nls.h>
+#include <mailutils/cstr.h>
typedef int (*str_to_c_t) (void *tgt, char const *string, char **errmsg);
@@ -245,6 +246,12 @@ to_incr (void *tgt, char const *string, char **errmsg)
return 0;
}
+static int
+to_hsize (void *tgt, char const *string, char **errmsg)
+{
+ return mu_strtosize (string, NULL, tgt);
+}
+
static str_to_c_t str_to_c[] = {
[mu_c_string] = to_string,
[mu_c_short] = to_short,
@@ -254,13 +261,14 @@ static str_to_c_t str_to_c[] = {
[mu_c_long] = to_long,
[mu_c_ulong] = to_ulong,
[mu_c_size] = to_size_t,
+ [mu_c_hsize] = to_hsize,
/* FIXME [mu_c_off] = { to_off, generic_dealloc }, */
[mu_c_time] = to_time_t,
[mu_c_bool] = to_bool,
/* FIXME [mu_c_ipv4] = to_ipv4, */
[mu_c_cidr] = to_cidr,
/* FIXME [mu_c_host] = { to_host, generic_dealloc } */
- [mu_c_incr] = to_incr
+ [mu_c_incr] = to_incr,
};
char const *mu_c_type_str[] = {
@@ -272,6 +280,7 @@ char const *mu_c_type_str[] = {
[mu_c_long] = "mu_c_long",
[mu_c_ulong] = "mu_c_ulong",
[mu_c_size] = "mu_c_size",
+ [mu_c_hsize] = "mu_c_hsize",
[mu_c_off] = "mu_c_off",
[mu_c_time] = "mu_c_time",
[mu_c_bool] = "mu_c_bool",
@@ -279,7 +288,7 @@ char const *mu_c_type_str[] = {
[mu_c_cidr] = "mu_c_cidr",
[mu_c_host] = "mu_c_host",
[mu_c_incr] = "mu_c_incr",
- [mu_c_void] = "mu_c_void"
+ [mu_c_void] = "mu_c_void",
};
int
diff --git a/libmailutils/string/strtosize.c b/libmailutils/string/strtosize.c
new file mode 100644
index 000000000..9ba0ba0d7
--- /dev/null
+++ b/libmailutils/string/strtosize.c
@@ -0,0 +1,132 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2016-2020 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <mailutils/errno.h>
+#include <mailutils/cctype.h>
+#include <mailutils/cstr.h>
+
+#ifndef SIZE_MAX
+# define SIZE_MAX (~((size_t)0))
+#endif
+
+/*
+ * Converts the initial part of the string in STR to a size_t value.
+ * A valid input consists of a sequence of decimal digits, and optional
+ * size suffix: K, M, or G. Any amount of whitespace is allowed at the
+ * beginning of STR and between the last digit and size suffix.
+ *
+ * On success, the result is stored in RET_VAL and 0 is returned.
+ * On error, RET_VAL remains untouched and one of the following error
+ * codes is returned:
+ * EINVAL - STR is NULL.
+ * MU_ERR_OUT_PTR_NULL
+ * RET_VAL is NULL.
+ * ERANGE - Result is out of allowed range for size_t.
+ * MU_ERR_PARSE - (0) Unexpected character encountered or
+ * (1) STR is empty or
+ * (2) STR contains only whitespace characters or
+ * (3) ENDP is NULL and the portion of STR that remains
+ * after conversion contains characters other than
+ * \0 and whitespace,
+ *
+ * If ENDP is not NULL, a pointer to the character in STR at which
+ * the conversion has stopped is stored in *ENDP.
+ */
+int
+mu_strtosize (char const *str, char **endp, size_t *ret_val)
+{
+ size_t n = 0;
+ int rc = 0;
+ char const *start, *s;
+
+ if (!str)
+ return EINVAL;
+ if (!ret_val)
+ return MU_ERR_OUT_PTR_NULL;
+
+ s = start = mu_str_skip_class (str, MU_CTYPE_SPACE);
+
+ while (*s && mu_isdigit (*s))
+ {
+ size_t x = n * 10 + *s - '0';
+ if (x < n)
+ {
+ rc = ERANGE;
+ goto end;
+ }
+ n = x;
+ s++;
+ }
+
+ if (s == start)
+ {
+ rc = MU_ERR_PARSE;
+ goto end;
+ }
+
+ str = s;
+ s = mu_str_skip_class (s, MU_CTYPE_SPACE);
+
+ switch (*s++)
+ {
+ case 'g':
+ case 'G':
+ if (SIZE_MAX / n < 1024)
+ {
+ rc = ERANGE;
+ break;
+ }
+ n <<= 10;
+ case 'm':
+ case 'M':
+ if (SIZE_MAX / n < 1024)
+ {
+ rc = ERANGE;
+ break;
+ }
+ n <<= 10;
+ case 'k':
+ case 'K':
+ if (SIZE_MAX / n < 1024)
+ {
+ rc = ERANGE;
+ break;
+ }
+ n <<= 10;
+ break;
+
+ case 0:
+ s = str;
+ break;
+
+ default:
+ s = str;
+ rc = MU_ERR_PARSE;
+ }
+ end:
+ if (endp)
+ *endp = (char*) s;
+ else if (rc == 0 && *mu_str_skip_class (s, MU_CTYPE_SPACE))
+ rc = MU_ERR_PARSE;
+
+ if (rc == 0)
+ *ret_val = n;
+ return rc;
+}
diff --git a/libmailutils/tests/strtoc.c b/libmailutils/tests/strtoc.c
index 68978120e..dbb15e21b 100644
--- a/libmailutils/tests/strtoc.c
+++ b/libmailutils/tests/strtoc.c
@@ -197,6 +197,7 @@ struct value_handler value_handler[] = {
[mu_c_long] = { v_long_format, v_long_compare },
[mu_c_ulong] = { v_ulong_format, v_ulong_compare },
[mu_c_size] = { v_size_format, v_size_compare },
+ [mu_c_hsize] = { v_size_format, v_size_compare },
#if 0
mu_c_time,
#endif
@@ -244,7 +245,6 @@ struct testdata tests[] = {
{ mu_c_short, "115", 0, { .v_short = 115 } },
{ mu_c_short, "-400", 0, { .v_short = -400 } },
{ mu_c_short, "1a", EINVAL, },
-
{ mu_c_ushort, "110", 0, { .v_ushort = 110 } },
{ mu_c_ushort, "-110", ERANGE },
@@ -258,6 +258,19 @@ struct testdata tests[] = {
{ mu_c_ulong, "10568", 0, { .v_ulong = 10568 } },
+ { mu_c_size, "10568", 0, { .v_size = 10568 } },
+
+ { mu_c_hsize, "0", 0, { .v_size = 0 } },
+ { mu_c_hsize, "10", 0, { .v_size = 10 } },
+ { mu_c_hsize, "10K", 0, { .v_size = 10240 } },
+ { mu_c_hsize, " 10 M ", 0, { .v_size = 10485760 } },
+ { mu_c_hsize, "10s", MU_ERR_PARSE },
+ { mu_c_hsize, "-1", MU_ERR_PARSE },
+ { mu_c_hsize, "", MU_ERR_PARSE },
+ { mu_c_hsize, " ", MU_ERR_PARSE },
+ { mu_c_hsize, " 1 M b ", MU_ERR_PARSE },
+
+
{ mu_c_bool, "true", 0, { .v_int = 1 } },
{ mu_c_bool, "false", 0, { .v_int = 0 } },
@@ -289,7 +302,7 @@ print_test_id (int i, FILE *fp)
void
usage (int code, FILE *fp, char const *argv0)
{
- fprintf (fp, "usage: %s [-v]", argv0);
+ fprintf (fp, "usage: %s [-v]\n", argv0);
exit (code);
}
@@ -341,6 +354,12 @@ main (int argc, char **argv)
++failures;
}
}
+ else if (tests[i].err)
+ {
+ print_test_id (i, stderr);
+ fprintf (stderr, "FAIL: unexpected success\n");
+ ++failures;
+ }
else if (valcmp (tests[i].type, &tests[i].val, &val))
{
fprintf (stderr, "%d: FAIL: %s value differ: ",

Return to:

Send suggestions and report system problems to the System administrator.