From 59824e5c9b22dd9c007ce8bf4ea5acb755a50dee Mon Sep 17 00:00:00 2001 From: Enrico Scholz Date: Sun, 22 Jan 2006 11:23:47 +0000 Subject: [PATCH] enhanced the isNumber() method: * now, it accepts units like 'm' or 'K'; 'isNumber()' needs now a third parameter telling whether to interprete the number strictly or whether to accept such units * an 'isNumberUnsigned()' method was created for unsigned types; an 'util-isnumber.hc' template file was created for this purpose * proper tests for over/underflow were implemented git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/trunk@2255 94cd875c-1c1d-0410-91d2-eb244daf1a30 --- util-vserver/lib_internal/Makefile-files | 2 + util-vserver/lib_internal/util-isnumber.c | 21 ++++----- util-vserver/lib_internal/util-isnumber.hc | 52 +++++++++++++++++++++++ util-vserver/lib_internal/util-isnumberunsigned.c | 35 +++++++++++++++ util-vserver/lib_internal/util.h | 3 +- 5 files changed, 100 insertions(+), 13 deletions(-) create mode 100644 util-vserver/lib_internal/util-isnumber.hc create mode 100644 util-vserver/lib_internal/util-isnumberunsigned.c diff --git a/util-vserver/lib_internal/Makefile-files b/util-vserver/lib_internal/Makefile-files index aca43da..215eca1 100644 --- a/util-vserver/lib_internal/Makefile-files +++ b/util-vserver/lib_internal/Makefile-files @@ -96,7 +96,9 @@ lib_internal_libinternal_common_SRCS = \ lib_internal/unify-isiunlinkable.c \ lib_internal/util-canonify.c \ lib_internal/util-exitlikeprocess.c \ + lib_internal/util-isnumber.hc \ lib_internal/util-isnumber.c \ + lib_internal/util-isnumberunsigned.c \ lib_internal/util-lockfile.c \ lib_internal/util-safechdir.c \ $(command_SRCS) \ diff --git a/util-vserver/lib_internal/util-isnumber.c b/util-vserver/lib_internal/util-isnumber.c index f5a41c7..165b7a7 100644 --- a/util-vserver/lib_internal/util-isnumber.c +++ b/util-vserver/lib_internal/util-isnumber.c @@ -21,18 +21,15 @@ #endif #include "util.h" +#include "util-isnumber.hc" +#include -bool -isNumber(char const *str, signed long *result) +static inline bool +checkConstraints(signed long val, unsigned int fac) { - char * errptr; - signed long val; - - val = strtol(str, &errptr, 0); - if (*errptr!='\0' || errptr==str) - return false; - else { - if (result) *result = val; - return true; - } + if (val>0 && (signed long)(LONG_MAX/fac) <= val) return false; + if (val<0 && (signed long)(LONG_MIN/fac) >= val) return false; + return true; } + +ENSC_DECL_UTIL_ISNUMBER(isNumber, signed long, strtol) diff --git a/util-vserver/lib_internal/util-isnumber.hc b/util-vserver/lib_internal/util-isnumber.hc new file mode 100644 index 0000000..27ec093 --- /dev/null +++ b/util-vserver/lib_internal/util-isnumber.hc @@ -0,0 +1,52 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2006 Enrico Scholz +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include +#include +#include + +#define ENSC_DECL_UTIL_ISNUMBER(NAME,TYPE,FUNC) \ + bool \ + NAME(char const *str, TYPE *result, bool is_strict) \ + { \ + char * errptr; \ + TYPE val; \ + unsigned int fac = 1; \ + \ + errno = 0; \ + val = FUNC(str, &errptr, 0); \ + if (errno==ERANGE) \ + return false; \ + if (errptr!=str && !is_strict) { \ + switch (*errptr) { \ + case 'M' : fac *= 1024; /* fallthrough */ \ + case 'K' : fac *= 1024; ++errptr; break; \ + case 'm' : fac *= 1000; /* fallthrough */ \ + case 'k' : fac *= 1000; ++errptr; break; \ + default : break; \ + } \ + } \ + if (!checkConstraints(val,fac)) \ + return false; \ + \ + if (*errptr!='\0' || errptr==str) \ + return false; \ + else { \ + if (result) *result = val*fac; \ + return true; \ + } \ + } diff --git a/util-vserver/lib_internal/util-isnumberunsigned.c b/util-vserver/lib_internal/util-isnumberunsigned.c new file mode 100644 index 0000000..902c3e5 --- /dev/null +++ b/util-vserver/lib_internal/util-isnumberunsigned.c @@ -0,0 +1,35 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2005 Enrico Scholz +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "util.h" +#include "util-isnumber.hc" +#include + +static inline bool +checkConstraints(unsigned long val, unsigned int fac) +{ + if ((long)(val) < 0) return false; + if (ULONG_MAX/fac <= val) return false; + return true; +} + +ENSC_DECL_UTIL_ISNUMBER(isNumberUnsigned, unsigned long, strtoul) diff --git a/util-vserver/lib_internal/util.h b/util-vserver/lib_internal/util.h index 955fbe6..8a919d9 100644 --- a/util-vserver/lib_internal/util.h +++ b/util-vserver/lib_internal/util.h @@ -35,6 +35,7 @@ bool switchToWatchXid(char const **); size_t canonifyVserverName(char *); -bool isNumber(char const *, signed long *result); +bool isNumber(char const *, signed long *result, bool is_strict); +bool isNumberUnsigned(char const *, unsigned long *result, bool is_strict); #endif // H_UTILVSERVER_LIB_INTERNAL_UTIL_H -- 1.8.1.5