]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - libfrog/convert.c
libfrog: fix bitmap error communication problems
[thirdparty/xfsprogs-dev.git] / libfrog / convert.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
5 */
6 #include "platform_defs.h"
7 #include "input.h"
8 #include <ctype.h>
9 #include <stdbool.h>
10
11 size_t
12 numlen(
13 uint64_t val,
14 size_t base)
15 {
16 uint64_t tmp;
17 size_t len;
18
19 for (len = 0, tmp = val; tmp > 0; tmp = tmp / base)
20 len++;
21 return len == 0 ? 1 : len;
22 }
23
24 /*
25 * Convert string to int64_t, set errno if the conversion fails or
26 * doesn't fit. Does not allow unit specifiers. Sets errno to zero
27 * prior to conversion so you can check for bad inputs by examining
28 * errno immediately after the call.
29 */
30 int64_t
31 cvt_s64(
32 char *s,
33 int base)
34 {
35 long long i;
36 char *sp;
37
38 errno = 0;
39 i = strtoll(s, &sp, base);
40 /*
41 * If the input would over or underflow, return the clamped
42 * value and let the user check errno. If we went all the
43 * way to the end of the input, return the converted value;
44 * errno will be zero.
45 */
46 if (errno || (*sp == '\0' && sp != s))
47 return i;
48
49 /* Not all the input was consumed, return error. */
50 errno = ERANGE;
51 return INT64_MIN;
52 }
53
54 /*
55 * Convert string to int32_t, set errno if the conversion fails or
56 * doesn't fit. Does not allow unit specifiers. Sets errno to zero
57 * prior to conversion so you can check for bad inputs by examining
58 * errno immediately after the call.
59 */
60 int32_t
61 cvt_s32(
62 char *s,
63 int base)
64 {
65 int64_t i;
66
67 i = cvt_s64(s, base);
68 if (errno)
69 return i;
70 if (i > INT32_MAX || i < INT32_MIN) {
71 errno = ERANGE;
72 return INT32_MIN;
73 }
74 return i;
75 }
76
77 /*
78 * Convert string to int16_t, set errno if the conversion fails or
79 * doesn't fit. Does not allow unit specifiers. Sets errno to zero
80 * prior to conversion so you can check for bad inputs by examining
81 * errno immediately after the call.
82 */
83 int16_t
84 cvt_s16(
85 char *s,
86 int base)
87 {
88 int64_t i;
89
90 i = cvt_s64(s, base);
91 if (errno)
92 return i;
93 if (i > INT16_MAX || i < INT16_MIN) {
94 errno = ERANGE;
95 return INT16_MIN;
96 }
97 return i;
98 }
99
100 /*
101 * Convert string to uint64_t, set errno if the conversion fails or
102 * doesn't fit. Does not allow unit specifiers. Sets errno to zero
103 * prior to conversion so you can check for bad inputs by examining
104 * errno immediately after the call.
105 */
106 uint64_t
107 cvt_u64(
108 char *s,
109 int base)
110 {
111 unsigned long long i;
112 char *sp;
113
114 errno = 0;
115 i = strtoull(s, &sp, base);
116 /*
117 * If the input would over or underflow, return the clamped
118 * value and let the user check errno. If we went all the
119 * way to the end of the input, return the converted value;
120 * errno will be zero.
121 */
122 if (errno || (*sp == '\0' && sp != s))
123 return i;
124
125 /* Not all the input was consumed, return error. */
126 errno = ERANGE;
127 return UINT64_MAX;
128 }
129
130 /*
131 * Convert string to uint32_t, set errno if the conversion fails or
132 * doesn't fit. Does not allow unit specifiers. Sets errno to zero
133 * prior to conversion so you can check for bad inputs by examining
134 * errno immediately after the call.
135 */
136 uint32_t
137 cvt_u32(
138 char *s,
139 int base)
140 {
141 uint64_t i;
142
143 i = cvt_u64(s, base);
144 if (errno)
145 return i;
146 if (i > UINT32_MAX) {
147 errno = ERANGE;
148 return UINT32_MAX;
149 }
150 return i;
151 }
152
153 /*
154 * Convert string to uint16_t, set errno if the conversion fails or
155 * doesn't fit. Does not allow unit specifiers. Sets errno to zero
156 * prior to conversion so you can check for bad inputs by examining
157 * errno immediately after the call.
158 */
159 uint16_t
160 cvt_u16(
161 char *s,
162 int base)
163 {
164 uint64_t i;
165
166 i = cvt_u64(s, base);
167 if (errno)
168 return i;
169 if (i > UINT16_MAX) {
170 errno = ERANGE;
171 return UINT16_MAX;
172 }
173 return i;
174 }
175
176 #define EXABYTES(x) ((long long)(x) << 60)
177 #define PETABYTES(x) ((long long)(x) << 50)
178 #define TERABYTES(x) ((long long)(x) << 40)
179 #define GIGABYTES(x) ((long long)(x) << 30)
180 #define MEGABYTES(x) ((long long)(x) << 20)
181 #define KILOBYTES(x) ((long long)(x) << 10)
182
183 long long
184 cvtnum(
185 size_t blocksize,
186 size_t sectorsize,
187 char *s)
188 {
189 long long i;
190 char *sp;
191 int c;
192
193 i = strtoll(s, &sp, 0);
194 if (i == 0 && sp == s)
195 return -1LL;
196 if (*sp == '\0')
197 return i;
198
199 if (sp[1] != '\0')
200 return -1LL;
201
202 c = tolower(*sp);
203 switch (c) {
204 case 'b':
205 return i * blocksize;
206 case 's':
207 return i * sectorsize;
208 case 'k':
209 return KILOBYTES(i);
210 case 'm':
211 return MEGABYTES(i);
212 case 'g':
213 return GIGABYTES(i);
214 case 't':
215 return TERABYTES(i);
216 case 'p':
217 return PETABYTES(i);
218 case 'e':
219 return EXABYTES(i);
220 }
221 return -1LL;
222 }
223
224 #define TO_EXABYTES(x) ((x) / EXABYTES(1))
225 #define TO_PETABYTES(x) ((x) / PETABYTES(1))
226 #define TO_TERABYTES(x) ((x) / TERABYTES(1))
227 #define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
228 #define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
229 #define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
230
231 void
232 cvtstr(
233 double value,
234 char *str,
235 size_t size)
236 {
237 char *fmt;
238 int precise;
239
240 precise = ((double)value * 1000 == (double)(int)value * 1000);
241
242 if (value >= EXABYTES(1)) {
243 fmt = precise ? "%.f EiB" : "%.3f EiB";
244 snprintf(str, size, fmt, TO_EXABYTES(value));
245 } else if (value >= PETABYTES(1)) {
246 fmt = precise ? "%.f PiB" : "%.3f PiB";
247 snprintf(str, size, fmt, TO_PETABYTES(value));
248 } else if (value >= TERABYTES(1)) {
249 fmt = precise ? "%.f TiB" : "%.3f TiB";
250 snprintf(str, size, fmt, TO_TERABYTES(value));
251 } else if (value >= GIGABYTES(1)) {
252 fmt = precise ? "%.f GiB" : "%.3f GiB";
253 snprintf(str, size, fmt, TO_GIGABYTES(value));
254 } else if (value >= MEGABYTES(1)) {
255 fmt = precise ? "%.f MiB" : "%.3f MiB";
256 snprintf(str, size, fmt, TO_MEGABYTES(value));
257 } else if (value >= KILOBYTES(1)) {
258 fmt = precise ? "%.f KiB" : "%.3f KiB";
259 snprintf(str, size, fmt, TO_KILOBYTES(value));
260 } else {
261 snprintf(str, size, "%f bytes", value);
262 }
263 }
264
265 #define MINUTES_TO_SECONDS(m) ((m) * 60)
266 #define HOURS_TO_SECONDS(h) ((h) * MINUTES_TO_SECONDS(60))
267 #define DAYS_TO_SECONDS(d) ((d) * HOURS_TO_SECONDS(24))
268 #define WEEKS_TO_SECONDS(w) ((w) * DAYS_TO_SECONDS(7))
269
270 unsigned long
271 cvttime(
272 char *s)
273 {
274 unsigned long i;
275 char *sp;
276
277 i = strtoul(s, &sp, 0);
278 if (i == 0 && sp == s)
279 return 0;
280 if (*sp == '\0')
281 return i;
282 if ((*sp == 'm' && sp[1] == '\0') ||
283 (strcmp(sp, "minutes") == 0) ||
284 (strcmp(sp, "minute") == 0))
285 return MINUTES_TO_SECONDS(i);
286 if ((*sp == 'h' && sp[1] == '\0') ||
287 (strcmp(sp, "hours") == 0) ||
288 (strcmp(sp, "hour") == 0))
289 return HOURS_TO_SECONDS(i);
290 if ((*sp == 'd' && sp[1] == '\0') ||
291 (strcmp(sp, "days") == 0) ||
292 (strcmp(sp, "day") == 0))
293 return DAYS_TO_SECONDS(i);
294 if ((*sp == 'w' && sp[1] == '\0') ||
295 (strcmp(sp, "weeks") == 0) ||
296 (strcmp(sp, "week") == 0))
297 return WEEKS_TO_SECONDS(i);
298 return 0;
299 }
300
301 /*
302 * Convert from arbitrary user strings into a numeric ID.
303 * If it's all numeric, we convert that inplace, else we do
304 * the name lookup, and return the found identifier.
305 */
306
307 prid_t
308 prid_from_string(
309 char *project)
310 {
311 fs_project_t *prj;
312 unsigned long prid_long;
313 char *sp;
314
315 /*
316 * Allow either a full numeric or a valid projectname, even
317 * if it starts with a digit.
318 */
319 prid_long = strtoul(project, &sp, 10);
320 if (*project != '\0' && *sp == '\0') {
321 if ((prid_long == ULONG_MAX && errno == ERANGE)
322 || (prid_long > (prid_t)-1))
323 return -1;
324 return (prid_t)prid_long;
325 }
326 prj = getprnam(project);
327 if (prj)
328 return prj->pr_prid;
329 return -1;
330 }
331
332 uid_t
333 uid_from_string(
334 char *user)
335 {
336 struct passwd *pwd;
337 unsigned long uid_long;
338 char *sp;
339
340 uid_long = strtoul(user, &sp, 10);
341 if (sp != user && *sp == '\0') {
342 if ((uid_long == ULONG_MAX && errno == ERANGE)
343 || (uid_long > (uid_t)-1))
344 return -1;
345 return (uid_t)uid_long;
346 }
347 pwd = getpwnam(user);
348 if (pwd)
349 return pwd->pw_uid;
350 return -1;
351 }
352
353 gid_t
354 gid_from_string(
355 char *group)
356 {
357 struct group *grp;
358 unsigned long gid_long;
359 char *sp;
360
361 gid_long = strtoul(group, &sp, 10);
362 if (sp != group && *sp == '\0') {
363 if ((gid_long == ULONG_MAX && errno == ERANGE)
364 || (gid_long > (gid_t)-1))
365 return -1;
366 return (gid_t)gid_long;
367 }
368 grp = getgrnam(group);
369 if (grp)
370 return grp->gr_gid;
371 return -1;
372 }