]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libfrog/convert.c
libfrog: create xfd_open function
[thirdparty/xfsprogs-dev.git] / libfrog / convert.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0
b95410da
DW
2/*
3 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
b95410da
DW
5 */
6#include "platform_defs.h"
7#include "input.h"
8#include <ctype.h>
9#include <stdbool.h>
10
11size_t
12numlen(
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 */
30int64_t
31cvt_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. */
b6ad9957 50 errno = ERANGE;
b95410da
DW
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 */
60int32_t
61cvt_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) {
b6ad9957 71 errno = ERANGE;
b95410da
DW
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 */
83int16_t
84cvt_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) {
b6ad9957 94 errno = ERANGE;
b95410da
DW
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 */
106uint64_t
107cvt_u64(
b089256c
DW
108 char *s,
109 int base)
b95410da 110{
b089256c
DW
111 unsigned long long i;
112 char *sp;
b95410da
DW
113
114 errno = 0;
b089256c 115 i = strtoull(s, &sp, base);
b95410da
DW
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. */
b6ad9957 126 errno = ERANGE;
b95410da
DW
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 */
136uint32_t
137cvt_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) {
b6ad9957 147 errno = ERANGE;
b95410da
DW
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 */
159uint16_t
160cvt_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) {
b6ad9957 170 errno = ERANGE;
b95410da
DW
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
183long long
184cvtnum(
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
231void
232cvtstr(
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
270unsigned long
271cvttime(
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
307prid_t
308prid_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
332uid_t
333uid_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
353gid_t
354gid_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}