Imported Upstream version 4.5.10
[platform/upstream/findutils.git] / lib / safe-atoi.c
1 /* safe-atoi.c -- checked string-to-int conversion.
2    Copyright (C) 2007, 2010 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <config.h>
19 #include <limits.h>
20 #include <stdlib.h>
21 #include <errno.h>
22
23 #include "safe-atoi.h"
24 #include "quotearg.h"
25 #include "error.h"
26
27
28 #if ENABLE_NLS
29 # include <libintl.h>
30 # define _(Text) gettext (Text)
31 #else
32 # define _(Text) Text
33 #endif
34 #ifdef gettext_noop
35 # define N_(String) gettext_noop (String)
36 #else
37 /* See locate.c for explanation as to why not use (String) */
38 # define N_(String) String
39 #endif
40
41
42 int
43 safe_atoi (const char *s, enum quoting_style style)
44 {
45   long lval;
46   char *end;
47
48   errno = 0;
49   lval = strtol (s, &end, 10);
50   if ( (LONG_MAX == lval) || (LONG_MIN == lval) )
51     {
52       /* max/min possible value, or an error. */
53       if (errno == ERANGE)
54         {
55           /* too big, or too small. */
56           error (EXIT_FAILURE, errno, "%s", s);
57         }
58       else
59         {
60           /* not a valid number */
61           error (EXIT_FAILURE, errno, "%s", s);
62         }
63       /* Otherwise, we do a range chack against INT_MAX and INT_MIN
64        * below.
65        */
66     }
67
68   if (lval > INT_MAX || lval < INT_MIN)
69     {
70       /* The number was in range for long, but not int. */
71       errno = ERANGE;
72       error (EXIT_FAILURE, errno, "%s", s);
73     }
74   else if (*end)
75     {
76       error (EXIT_FAILURE, errno, _("Unexpected suffix %s on %s"),
77              quotearg_n_style (0, style, end),
78              quotearg_n_style (1, style, s));
79     }
80   else if (end == s)
81     {
82       error (EXIT_FAILURE, errno, _("Expected an integer: %s"),
83              quotearg_n_style (0, style, s));
84     }
85   return (int)lval;
86 }