tests: rename logging test source
[gd/samba-autobuild/.git] / lib / util / smb_strtox.c
1 /*
2  * Unix SMB/CIFS implementation.
3  *
4  * Copyright (C) Swen Schillig 2019
5  *
6  *   ** NOTE! The following LGPL license applies to this file.
7  *   ** This does NOT imply that all of Samba is released
8  *   ** under the LGPL
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 3 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "replace.h"
25 #include "smb_strtox.h"
26
27 /**
28  * Convert a string to an unsigned long integer
29  *
30  * @param nptr          pointer to string which is to be converted
31  * @param endptr        [optional] reference to remainder of the string
32  * @param base          base of the numbering scheme
33  * @param err           error occured during conversion
34  * @flags               controlling conversion feature
35  * @result              result of the conversion as provided by strtoul
36  *
37  * The following flags are supported
38  *      SMB_STR_STANDARD # raise error if negative or non-numeric
39  *      SMB_STR_ALLOW_NEGATIVE # allow strings with a leading "-"
40  *      SMB_STR_FULL_STR_CONV # entire string must be converted
41  *      SMB_STR_ALLOW_NO_CONVERSION # allow empty strings or non-numeric
42  *      SMB_STR_GLIBC_STANDARD # act exactly as the standard glibc strtoul
43  *
44  * The following errors are detected
45  * - wrong base
46  * - value overflow
47  * - string with a leading "-" indicating a negative number
48  * - no conversion due to empty string or not representing a number
49  */
50 unsigned long int
51 smb_strtoul(const char *nptr, char **endptr, int base, int *err, int flags)
52 {
53         unsigned long int val;
54         int saved_errno = errno;
55         char *needle = NULL;
56         char *tmp_endptr = NULL;
57
58         errno = 0;
59         *err = 0;
60
61         val = strtoul(nptr, &tmp_endptr, base);
62
63         if (endptr != NULL) {
64                 *endptr = tmp_endptr;
65         }
66
67         if (errno != 0) {
68                 *err = errno;
69                 errno = saved_errno;
70                 return val;
71         }
72
73         if ((flags & SMB_STR_ALLOW_NO_CONVERSION) == 0) {
74                 /* got an invalid number-string resulting in no conversion */
75                 if (nptr == tmp_endptr) {
76                         *err = EINVAL;
77                         goto out;
78                 }
79         }
80
81         if ((flags & SMB_STR_ALLOW_NEGATIVE ) == 0) {
82                 /* did we convert a negative "number" ? */
83                 needle = strchr(nptr, '-');
84                 if (needle != NULL && needle < tmp_endptr) {
85                         *err = EINVAL;
86                         goto out;
87                 }
88         }
89
90         if ((flags & SMB_STR_FULL_STR_CONV) != 0) {
91                 /* did we convert the entire string ? */
92                 if (tmp_endptr[0] != '\0') {
93                         *err = EINVAL;
94                         goto out;
95                 }
96         }
97
98 out:
99         errno = saved_errno;
100         return val;
101 }
102
103 /**
104  * Convert a string to an unsigned long long integer
105  *
106  * @param nptr          pointer to string which is to be converted
107  * @param endptr        [optional] reference to remainder of the string
108  * @param base          base of the numbering scheme
109  * @param err           error occured during conversion
110  * @flags               controlling conversion feature
111  * @result              result of the conversion as provided by strtoull
112  *
113  * The following flags are supported
114  *      SMB_STR_STANDARD # raise error if negative or non-numeric
115  *      SMB_STR_ALLOW_NEGATIVE # allow strings with a leading "-"
116  *      SMB_STR_FULL_STR_CONV # entire string must be converted
117  *      SMB_STR_ALLOW_NO_CONVERSION # allow empty strings or non-numeric
118  *      SMB_STR_GLIBC_STANDARD # act exactly as the standard glibc strtoul
119  *
120  * The following errors are detected
121  * - wrong base
122  * - value overflow
123  * - string with a leading "-" indicating a negative number
124  * - no conversion due to empty string or not representing a number
125  */
126 unsigned long long int
127 smb_strtoull(const char *nptr, char **endptr, int base, int *err, int flags)
128 {
129         unsigned long long int val;
130         int saved_errno = errno;
131         char *needle = NULL;
132         char *tmp_endptr = NULL;
133
134         errno = 0;
135         *err = 0;
136
137         val = strtoull(nptr, &tmp_endptr, base);
138
139         if (endptr != NULL) {
140                 *endptr = tmp_endptr;
141         }
142
143         if (errno != 0) {
144                 *err = errno;
145                 errno = saved_errno;
146                 return val;
147         }
148
149         if ((flags & SMB_STR_ALLOW_NO_CONVERSION) == 0) {
150                 /* got an invalid number-string resulting in no conversion */
151                 if (nptr == tmp_endptr) {
152                         *err = EINVAL;
153                         goto out;
154                 }
155         }
156
157         if ((flags & SMB_STR_ALLOW_NEGATIVE ) == 0) {
158                 /* did we convert a negative "number" ? */
159                 needle = strchr(nptr, '-');
160                 if (needle != NULL && needle < tmp_endptr) {
161                         *err = EINVAL;
162                         goto out;
163                 }
164         }
165
166         if ((flags & SMB_STR_FULL_STR_CONV) != 0) {
167                 /* did we convert the entire string ? */
168                 if (tmp_endptr[0] != '\0') {
169                         *err = EINVAL;
170                         goto out;
171                 }
172         }
173
174 out:
175         errno = saved_errno;
176         return val;
177 }