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