From: Alejandro Colomar Date: Fri, 1 Dec 2023 21:34:31 +0000 (+0100) Subject: lib/atoi/strtoi.[ch]: strtoi_(), strtou_(): Add functions X-Git-Tag: 4.15.0-rc1~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=34ff8edb63f17032c6a215331249883a9bdf8cd1;p=thirdparty%2Fshadow.git lib/atoi/strtoi.[ch]: strtoi_(), strtou_(): Add functions These functions are identical to strtoi(3bsd) and strtou(3bsd), except for one important thing: if both ERANGE and ENOTSUP conditions happen, the BSD functions report ENOTSUP, which is bogus; our strtoi_() and strtou_() report ERANGE. Link: Link: Cc: Thorsten Glaser Cc: christos Cc: roy Cc: Guillem Jover Signed-off-by: Alejandro Colomar --- diff --git a/lib/Makefile.am b/lib/Makefile.am index 5b1121c4c..baef9cd2f 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -31,6 +31,8 @@ libshadow_la_SOURCES = \ agetpass.h \ alloc.c \ alloc.h \ + atoi/strtoi.c \ + atoi/strtoi.h \ atoi/strtou_noneg.c \ atoi/strtou_noneg.h \ attr.h \ diff --git a/lib/atoi/strtoi.c b/lib/atoi/strtoi.c new file mode 100644 index 000000000..197707b10 --- /dev/null +++ b/lib/atoi/strtoi.c @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: 2023, Alejandro Colomar +// SPDX-License-Identifier: BSD-3-Clause + + +#include + +#include "atoi/strtoi.h" + +#include + + +extern inline intmax_t strtoi_(const char *s, char **restrict endp, int base, + intmax_t min, intmax_t max, int *restrict status); +extern inline uintmax_t strtou_(const char *s, char **restrict endp, int base, + uintmax_t min, uintmax_t max, int *restrict status); diff --git a/lib/atoi/strtoi.h b/lib/atoi/strtoi.h new file mode 100644 index 000000000..1f061fc0c --- /dev/null +++ b/lib/atoi/strtoi.h @@ -0,0 +1,96 @@ +// SPDX-FileCopyrightText: 2023, Alejandro Colomar +// SPDX-License-Identifier: BSD-3-Clause + + +#ifndef SHADOW_INCLUDE_LIB_ATOI_STRTOI_H_ +#define SHADOW_INCLUDE_LIB_ATOI_STRTOI_H_ + + +#include + +#include +#include +#include +#include +#include +#include + +#include "attr.h" + + +#define strtoNmax(TYPE, ...) \ +( \ + _Generic((TYPE) 0, \ + intmax_t: strtoimax, \ + uintmax_t: strtoumax \ + )(__VA_ARGS__) \ +) + + +#define strtoN(s, endp, base, min, max, status, TYPE) \ +({ \ + const char *s_ = s; \ + char **endp_ = endp; \ + int base_ = base; \ + TYPE min_ = min; \ + TYPE max_ = max; \ + int *status_ = status; \ + \ + int e_, st_; \ + char *end_; \ + TYPE n_; \ + \ + if (endp_ == NULL) \ + endp_ = &end_; \ + if (status_ == NULL) \ + status_ = &st_; \ + \ + if (base_ != 0 && (base_ < 0 || base_ > 36)) { \ + *status_ = EINVAL; \ + n_ = 0; \ + \ + } else { \ + e_ = errno; \ + errno = 0; \ + n_ = strtoNmax(TYPE, s_, endp_, base_); \ + \ + if (*endp_ == s_) \ + *status_ = ECANCELED; \ + else if (errno == ERANGE || n_ < min_ || n_ > max_) \ + *status_ = ERANGE; \ + else if (**endp_ != '\0') \ + *status_ = ENOTSUP; \ + else \ + *status_ = 0; \ + \ + errno = e_; \ + } \ + MAX(min_, MIN(max_, n_)); \ +}) + + +ATTR_STRING(1) ATTR_ACCESS(write_only, 2) ATTR_ACCESS(write_only, 6) +inline intmax_t strtoi_(const char *s, char **restrict endp, int base, + intmax_t min, intmax_t max, int *restrict status); +ATTR_STRING(1) ATTR_ACCESS(write_only, 2) ATTR_ACCESS(write_only, 6) +inline uintmax_t strtou_(const char *s, char **restrict endp, int base, + uintmax_t min, uintmax_t max, int *restrict status); + + +inline intmax_t +strtoi_(const char *s, char **restrict endp, int base, + intmax_t min, intmax_t max, int *restrict status) +{ + return strtoN(s, endp, base, min, max, status, intmax_t); +} + + +inline uintmax_t +strtou_(const char *s, char **restrict endp, int base, + uintmax_t min, uintmax_t max, int *restrict status) +{ + return strtoN(s, endp, base, min, max, status, uintmax_t); +} + + +#endif // include guard