1 /*****************************************************************************\
2 * parse_value.c - helper functions to simplify typed values management in
3 * Slurm parser (see parse_config.{h,c})
4 *****************************************************************************
5 * Initially written by Francois Chevallier <chevallierfrancois@free.fr> @ BULL
6 * for slurm-2.6. Adapted by Matthieu Hautreux <matthieu.hautreux@cea.fr>, CEA,
7 * for slurm-14.11.
8 *
9 * This file is part of Slurm, a resource management program.
10 * For details, see <https://slurm.schedmd.com/>.
11 * Please also read the included file: DISCLAIMER.
12 *
13 * Slurm is free software; you can redistribute it and/or modify it under
14 * the terms of the GNU General Public License as published by the Free
15 * Software Foundation; either version 2 of the License, or (at your option)
16 * any later version.
17 *
18 * In addition, as a special exception, the copyright holders give permission
19 * to link the code of portions of this program with the OpenSSL library under
20 * certain conditions as described in each individual source file, and
21 * distribute linked combinations including the two. You must obey the GNU
22 * General Public License in all respects for all of the code used other than
23 * OpenSSL. If you modify file(s) with this exception, you may extend this
24 * exception to your version of the file(s), but you are not obligated to do
25 * so. If you do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source files in
27 * the program, then also delete it here.
28 *
29 * Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
30 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
31 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
32 * details.
33 *
34 * You should have received a copy of the GNU General Public License along
35 * with Slurm; if not, write to the Free Software Foundation, Inc.,
36 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
37 \*****************************************************************************/
38
39 #ifndef _ISOC99_SOURCE
40 # define _ISOC99_SOURCE /* strtof() */
41 #endif
42
43 #include <stdint.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <math.h>
48
49 #include "src/common/log.h"
50 #include "src/common/macros.h"
51 #include "src/common/xmalloc.h"
52 #include "src/common/xstring.h"
53
54 #include "src/common/parse_value.h"
55
56 #include "slurm/slurm.h"
57
s_p_handle_long(long * data,const char * key,const char * value)58 int s_p_handle_long(long* data, const char* key, const char* value)
59 {
60 char *endptr;
61 long num;
62 errno = 0;
63 num = strtol(value, &endptr, 0);
64 if ((num == 0 && errno == EINVAL)
65 || (*endptr != '\0')) {
66 if (xstrcasecmp(value, "UNLIMITED") == 0
67 || xstrcasecmp(value, "INFINITE") == 0) {
68 num = (long) INFINITE;
69 } else {
70 error("\"%s\" is not a valid number", value);
71 return SLURM_ERROR;
72 }
73 } else if (errno == ERANGE) {
74 error("\"%s\" is out of range", value);
75 return SLURM_ERROR;
76 }
77 *data = num;
78 return SLURM_SUCCESS;
79 }
80
s_p_handle_uint16(uint16_t * data,const char * key,const char * value)81 int s_p_handle_uint16(uint16_t* data, const char* key, const char *value)
82 {
83 char *endptr;
84 unsigned long num;
85
86 errno = 0;
87 num = strtoul(value, &endptr, 0);
88 if ((num == 0 && errno == EINVAL)
89 || (*endptr != '\0')) {
90 if (xstrcasecmp(value, "UNLIMITED") == 0
91 || xstrcasecmp(value, "INFINITE") == 0) {
92 num = INFINITE16;
93 } else {
94 error("%s value \"%s\" is not a valid number",
95 key, value);
96 return SLURM_ERROR;
97 }
98 } else if (errno == ERANGE) {
99 error("%s value (%s) is out of range", key, value);
100 return SLURM_ERROR;
101 } else if (value[0] == '-') {
102 error("%s value (%s) is less than zero", key,
103 value);
104 return SLURM_ERROR;
105 } else if (num > 0xffff) {
106 error("%s value (%s) is greater than 65535", key,
107 value);
108 return SLURM_ERROR;
109 }
110 *data = (uint16_t)num;
111 return SLURM_SUCCESS;
112 }
113
s_p_handle_uint32(uint32_t * data,const char * key,const char * value)114 int s_p_handle_uint32(uint32_t* data, const char* key, const char* value)
115 {
116 char *endptr;
117 unsigned long num;
118
119 errno = 0;
120 num = strtoul(value, &endptr, 0);
121 if ((endptr[0] == 'k') || (endptr[0] == 'K')) {
122 num *= 1024;
123 endptr++;
124 }
125 if ((num == 0 && errno == EINVAL)
126 || (*endptr != '\0')) {
127 if ((xstrcasecmp(value, "UNLIMITED") == 0) ||
128 (xstrcasecmp(value, "INFINITE") == 0)) {
129 num = INFINITE;
130 } else {
131 error("%s value (%s) is not a valid number",
132 key, value);
133 return SLURM_ERROR;
134 }
135 } else if (errno == ERANGE) {
136 error("%s value (%s) is out of range", key, value);
137 return SLURM_ERROR;
138 } else if (value[0] == '-') {
139 error("%s value (%s) is less than zero", key,
140 value);
141 return SLURM_ERROR;
142 } else if (num > 0xffffffff) {
143 error("%s value (%s) is greater than 4294967295",
144 key, value);
145 return SLURM_ERROR;
146 }
147 *data = (uint32_t)num;
148 return SLURM_SUCCESS;
149 }
150
s_p_handle_uint64(uint64_t * data,const char * key,const char * value)151 int s_p_handle_uint64(uint64_t* data, const char* key, const char* value)
152 {
153 char *endptr;
154 unsigned long long num;
155
156 errno = 0;
157 num = strtoull(value, &endptr, 0);
158 if ((endptr[0] == 'k') || (endptr[0] == 'K')) {
159 num *= 1024;
160 endptr++;
161 }
162 if ((num == 0 && errno == EINVAL)
163 || (*endptr != '\0')) {
164 if ((xstrcasecmp(value, "UNLIMITED") == 0) ||
165 (xstrcasecmp(value, "INFINITE") == 0)) {
166 num = INFINITE64;
167 } else {
168 error("%s value (%s) is not a valid number",
169 key, value);
170 return SLURM_ERROR;
171 }
172 } else if (errno == ERANGE) {
173 error("%s value (%s) is out of range", key, value);
174 return SLURM_ERROR;
175 } else if (value[0] == '-') {
176 error("%s value (%s) is less than zero", key,
177 value);
178 return SLURM_ERROR;
179 } else if (num > 0xffffffffffffffff) {
180 error("%s value (%s) is greater than 4294967295",
181 key, value);
182 return SLURM_ERROR;
183 }
184 *data = (uint64_t)num;
185 return SLURM_SUCCESS;
186 }
187
s_p_handle_boolean(bool * data,const char * key,const char * value)188 int s_p_handle_boolean(bool* data, const char* key, const char* value)
189 {
190 bool flag;
191
192 if (!xstrcasecmp(value, "yes")
193 || !xstrcasecmp(value, "up")
194 || !xstrcasecmp(value, "true")
195 || !xstrcasecmp(value, "1")) {
196 flag = true;
197 } else if (!xstrcasecmp(value, "no")
198 || !xstrcasecmp(value, "down")
199 || !xstrcasecmp(value, "false")
200 || !xstrcasecmp(value, "0")) {
201 flag = false;
202 } else {
203 error("\"%s\" is not a valid option for \"%s\"",
204 value, key);
205 return SLURM_ERROR;
206 }
207
208 *data = flag;
209 return SLURM_SUCCESS;
210 }
211
s_p_handle_float(float * data,const char * key,const char * value)212 int s_p_handle_float(float* data, const char* key, const char* value)
213 {
214 char *endptr;
215 float num;
216
217 errno = 0;
218 num = strtof(value, &endptr);
219 if ((num == 0 && errno == EINVAL)
220 || (*endptr != '\0')) {
221 if ((xstrcasecmp(value, "UNLIMITED") == 0) ||
222 (xstrcasecmp(value, "INFINITE") == 0)) {
223 num = INFINITY;
224 } else {
225 error("%s value (%s) is not a valid number",
226 key, value);
227 return SLURM_ERROR;
228 }
229 } else if (errno == ERANGE) {
230 error("%s value (%s) is out of range", key, value);
231 return SLURM_ERROR;
232 }
233 *data = num;
234 return SLURM_SUCCESS;
235 }
236
s_p_handle_double(double * data,const char * key,const char * value)237 int s_p_handle_double(double* data, const char* key, const char* value)
238 {
239 char *endptr;
240 double num;
241
242 errno = 0;
243 num = strtod(value, &endptr);
244 if ((num == 0 && errno == EINVAL)
245 || (*endptr != '\0')) {
246 if ((xstrcasecmp(value, "UNLIMITED") == 0) ||
247 (xstrcasecmp(value, "INFINITE") == 0)) {
248 num = HUGE_VAL;
249 } else {
250 error("%s value (%s) is not a valid number",
251 key, value);
252 return SLURM_ERROR;
253 }
254 } else if (errno == ERANGE) {
255 error("%s value (%s) is out of range", key, value);
256 return SLURM_ERROR;
257 }
258 *data = num;
259 return SLURM_SUCCESS;
260 }
261
s_p_handle_long_double(long double * data,const char * key,const char * value)262 int s_p_handle_long_double(long double* data, const char* key,
263 const char* value)
264 {
265 char *endptr;
266 long double num;
267
268 errno = 0;
269 num = strtold(value, &endptr);
270 if ((num == 0 && errno == EINVAL)
271 || (*endptr != '\0')) {
272 if ((xstrcasecmp(value, "UNLIMITED") == 0) ||
273 (xstrcasecmp(value, "INFINITE") == 0)) {
274 num = HUGE_VALL;
275 } else {
276 error("%s value (%s) is not a valid number",
277 key, value);
278 return SLURM_ERROR;
279 }
280 } else if (errno == ERANGE) {
281 error("%s value (%s) is out of range", key, value);
282 return SLURM_ERROR;
283 }
284 *data = num;
285 return SLURM_SUCCESS;
286 }
287