]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxcmd/input.c
libxfs: fix xfs_trans_alloc_empty namespace
[thirdparty/xfsprogs-dev.git] / libxcmd / input.c
CommitLineData
e246ba5f 1/*
da23017d
NS
2 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
dfc130f3 4 *
da23017d
NS
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
e246ba5f 7 * published by the Free Software Foundation.
dfc130f3 8 *
da23017d
NS
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
dfc130f3 13 *
da23017d
NS
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
e246ba5f 17 */
dfc130f3 18
dcabd4e7 19#include "platform_defs.h"
6b803e5a 20#include "input.h"
fd2d0648 21#include <ctype.h>
fd537fc5 22#include <stdbool.h>
e246ba5f 23
d4b9ebda 24#if defined(ENABLE_READLINE)
e246ba5f
NS
25# include <readline/history.h>
26# include <readline/readline.h>
d4b9ebda
NS
27#elif defined(ENABLE_EDITLINE)
28# include <histedit.h>
29#endif
30
2a1888c5
NS
31extern char *progname;
32
d4b9ebda
NS
33static char *
34get_prompt(void)
35{
3d93ccb7 36 static char prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ];
d4b9ebda
NS
37
38 if (!prompt[0])
39 snprintf(prompt, sizeof(prompt), "%s> ", progname);
40 return prompt;
41}
42
43#if defined(ENABLE_READLINE)
44char *
45fetchline(void)
46{
47 char *line;
48
49 line = readline(get_prompt());
50 if (line && *line)
51 add_history(line);
52 return line;
53}
54#elif defined(ENABLE_EDITLINE)
55static char *el_get_prompt(EditLine *e) { return get_prompt(); }
56char *
57fetchline(void)
58{
59 static EditLine *el;
60 static History *hist;
61 HistEvent hevent;
62 char *line;
63 int count;
64
65 if (!el) {
66 hist = history_init();
67 history(hist, &hevent, H_SETSIZE, 100);
68 el = el_init(progname, stdin, stdout, stderr);
69 el_source(el, NULL);
70 el_set(el, EL_SIGNAL, 1);
71 el_set(el, EL_PROMPT, el_get_prompt);
72 el_set(el, EL_HIST, history, (const char *)hist);
73 }
74 line = strdup(el_gets(el, &count));
75 if (line) {
76 if (count > 0)
77 line[count-1] = '\0';
78 if (*line)
79 history(hist, &hevent, H_ENTER, line);
80 }
81 return line;
82}
e246ba5f
NS
83#else
84# define MAXREADLINESZ 1024
d4b9ebda
NS
85char *
86fetchline(void)
e246ba5f
NS
87{
88 char *p, *line = malloc(MAXREADLINESZ);
89
90 if (!line)
91 return NULL;
50a3aa89 92 printf("%s", get_prompt());
e246ba5f
NS
93 fflush(stdout);
94 if (!fgets(line, MAXREADLINESZ, stdin)) {
95 free(line);
96 return NULL;
97 }
98 p = line + strlen(line);
99 if (p != line && p[-1] == '\n')
100 p[-1] = '\0';
101 return line;
102}
e246ba5f
NS
103#endif
104
e246ba5f
NS
105char **
106breakline(
107 char *input,
108 int *count)
109{
110 int c = 0;
111 char *p;
112 char **rval = calloc(sizeof(char *), 1);
113
3d93ccb7 114 while (rval && (p = strsep(&input, " ")) != NULL) {
e246ba5f
NS
115 if (!*p)
116 continue;
117 c++;
118 rval = realloc(rval, sizeof(*rval) * (c + 1));
3d93ccb7
NS
119 if (!rval) {
120 c = 0;
121 break;
122 }
e246ba5f
NS
123 rval[c - 1] = p;
124 rval[c] = NULL;
125 }
126 *count = c;
127 return rval;
128}
129
130void
131doneline(
132 char *input,
133 char **vec)
134{
135 free(input);
136 free(vec);
137}
638473d8 138
92d9b902
NS
139#define EXABYTES(x) ((long long)(x) << 60)
140#define PETABYTES(x) ((long long)(x) << 50)
141#define TERABYTES(x) ((long long)(x) << 40)
142#define GIGABYTES(x) ((long long)(x) << 30)
143#define MEGABYTES(x) ((long long)(x) << 20)
144#define KILOBYTES(x) ((long long)(x) << 10)
145
638473d8
NS
146long long
147cvtnum(
2c2f6d79
NS
148 size_t blocksize,
149 size_t sectorsize,
638473d8
NS
150 char *s)
151{
152 long long i;
153 char *sp;
d347f827 154 int c;
638473d8
NS
155
156 i = strtoll(s, &sp, 0);
157 if (i == 0 && sp == s)
158 return -1LL;
159 if (*sp == '\0')
160 return i;
161
f63b46a2 162 if (sp[1] != '\0')
d347f827
NS
163 return -1LL;
164
165 c = tolower(*sp);
166 switch (c) {
167 case 'b':
638473d8 168 return i * blocksize;
d347f827 169 case 's':
638473d8 170 return i * sectorsize;
d347f827 171 case 'k':
92d9b902 172 return KILOBYTES(i);
d347f827 173 case 'm':
92d9b902 174 return MEGABYTES(i);
d347f827 175 case 'g':
92d9b902 176 return GIGABYTES(i);
d347f827 177 case 't':
92d9b902 178 return TERABYTES(i);
d347f827 179 case 'p':
92d9b902 180 return PETABYTES(i);
d347f827 181 case 'e':
92d9b902 182 return EXABYTES(i);
d347f827 183 }
638473d8
NS
184 return -1LL;
185}
92d9b902
NS
186
187#define TO_EXABYTES(x) ((x) / EXABYTES(1))
188#define TO_PETABYTES(x) ((x) / PETABYTES(1))
189#define TO_TERABYTES(x) ((x) / TERABYTES(1))
190#define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
191#define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
192#define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
193
194void
195cvtstr(
196 double value,
197 char *str,
198 size_t size)
199{
200 char *fmt;
201 int precise;
202
203 precise = ((double)value * 1000 == (double)(int)value * 1000);
204
205 if (value >= EXABYTES(1)) {
206 fmt = precise ? "%.f EiB" : "%.3f EiB";
207 snprintf(str, size, fmt, TO_EXABYTES(value));
208 } else if (value >= PETABYTES(1)) {
209 fmt = precise ? "%.f PiB" : "%.3f PiB";
210 snprintf(str, size, fmt, TO_PETABYTES(value));
211 } else if (value >= TERABYTES(1)) {
212 fmt = precise ? "%.f TiB" : "%.3f TiB";
213 snprintf(str, size, fmt, TO_TERABYTES(value));
214 } else if (value >= GIGABYTES(1)) {
215 fmt = precise ? "%.f GiB" : "%.3f GiB";
216 snprintf(str, size, fmt, TO_GIGABYTES(value));
217 } else if (value >= MEGABYTES(1)) {
218 fmt = precise ? "%.f MiB" : "%.3f MiB";
219 snprintf(str, size, fmt, TO_MEGABYTES(value));
220 } else if (value >= KILOBYTES(1)) {
221 fmt = precise ? "%.f KiB" : "%.3f KiB";
222 snprintf(str, size, fmt, TO_KILOBYTES(value));
223 } else {
224 snprintf(str, size, "%f bytes", value);
225 }
226}
227
3d93ccb7
NS
228#define MINUTES_TO_SECONDS(m) ((m) * 60)
229#define HOURS_TO_SECONDS(h) ((h) * MINUTES_TO_SECONDS(60))
230#define DAYS_TO_SECONDS(d) ((d) * HOURS_TO_SECONDS(24))
231#define WEEKS_TO_SECONDS(w) ((w) * DAYS_TO_SECONDS(7))
232
233unsigned long
234cvttime(
235 char *s)
236{
237 unsigned long i;
238 char *sp;
239
240 i = strtoul(s, &sp, 0);
241 if (i == 0 && sp == s)
242 return 0;
243 if (*sp == '\0')
244 return i;
245 if ((*sp == 'm' && sp[1] == '\0') ||
246 (strcmp(sp, "minutes") == 0) ||
247 (strcmp(sp, "minute") == 0))
248 return MINUTES_TO_SECONDS(i);
249 if ((*sp == 'h' && sp[1] == '\0') ||
250 (strcmp(sp, "hours") == 0) ||
251 (strcmp(sp, "hour") == 0))
252 return HOURS_TO_SECONDS(i);
253 if ((*sp == 'd' && sp[1] == '\0') ||
254 (strcmp(sp, "days") == 0) ||
255 (strcmp(sp, "day") == 0))
256 return DAYS_TO_SECONDS(i);
257 if ((*sp == 'w' && sp[1] == '\0') ||
258 (strcmp(sp, "weeks") == 0) ||
259 (strcmp(sp, "week") == 0))
260 return WEEKS_TO_SECONDS(i);
261 return 0;
262}
263
264struct timeval
265tadd(struct timeval t1, struct timeval t2)
266{
267 t1.tv_usec += t2.tv_usec;
268 if (t1.tv_usec > 1000000) {
269 t1.tv_usec -= 1000000;
270 t1.tv_sec++;
271 }
272 t1.tv_sec += t2.tv_sec;
273 return t1;
274}
275
92d9b902
NS
276struct timeval
277tsub(struct timeval t1, struct timeval t2)
278{
279 t1.tv_usec -= t2.tv_usec;
280 if (t1.tv_usec < 0) {
281 t1.tv_usec += 1000000;
282 t1.tv_sec--;
283 }
284 t1.tv_sec -= t2.tv_sec;
285 return t1;
286}
287
288double
289tdiv(double value, struct timeval tv)
290{
291 return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
292}
293
294#define HOURS(sec) ((sec) / (60 * 60))
295#define MINUTES(sec) (((sec) % (60 * 60)) / 60)
296#define SECONDS(sec) ((sec) % 60)
297
298void
299timestr(
300 struct timeval *tv,
301 char *ts,
5c7bef67
NS
302 size_t size,
303 int format)
92d9b902 304{
5c7bef67
NS
305 double usec = (double)tv->tv_usec / 1000000.0;
306
307 if (format & TERSE_FIXED_TIME) {
308 if (!HOURS(tv->tv_sec)) {
309 snprintf(ts, size, "%u:%02u.%02u",
310 (unsigned int) MINUTES(tv->tv_sec),
311 (unsigned int) SECONDS(tv->tv_sec),
312 (unsigned int) usec * 100);
313 return;
314 }
315 format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
316 }
317
318 if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
319 snprintf(ts, size, "%u:%02u:%02u.%02u",
92d9b902
NS
320 (unsigned int) HOURS(tv->tv_sec),
321 (unsigned int) MINUTES(tv->tv_sec),
322 (unsigned int) SECONDS(tv->tv_sec),
5c7bef67
NS
323 (unsigned int) usec * 100);
324 } else {
325 snprintf(ts, size, "0.%04u sec", (unsigned int) usec * 10000);
326 }
92d9b902 327}
3d93ccb7 328
8211d1b5
DD
329/*
330 * Convert from a pair of arbitrary user strings into a timespec.
331 */
332
333int
334timespec_from_string(
335 const char * secs,
336 const char * nsecs,
337 struct timespec * ts)
338{
339 char* p;
340 if (!secs || !nsecs || !ts)
341 return 1;
342 ts->tv_sec = strtoull(secs, &p, 0);
343 if (*p)
344 return 1;
345 ts->tv_nsec = strtoull(nsecs, &p, 0);
346 if (*p)
347 return 1;
348 return 0;
349}
350
3d93ccb7
NS
351/*
352 * Convert from arbitrary user strings into a numeric ID.
ff1f79a7 353 * If it's all numeric, we convert that inplace, else we do
3d93ccb7
NS
354 * the name lookup, and return the found identifier.
355 */
356
357prid_t
358prid_from_string(
359 char *project)
360{
361 fs_project_t *prj;
272f4db5 362 unsigned long prid_long;
3d93ccb7
NS
363 char *sp;
364
1d9d5700
LB
365 /*
366 * Allow either a full numeric or a valid projectname, even
367 * if it starts with a digit.
368 */
272f4db5
AM
369 prid_long = strtoul(project, &sp, 10);
370 if (*project != '\0' && *sp == '\0') {
371 if ((prid_long == ULONG_MAX && errno == ERANGE)
372 || (prid_long > (prid_t)-1))
373 return -1;
374 return (prid_t)prid_long;
375 }
3d93ccb7
NS
376 prj = getprnam(project);
377 if (prj)
378 return prj->pr_prid;
379 return -1;
380}
381
382uid_t
383uid_from_string(
384 char *user)
385{
386 struct passwd *pwd;
272f4db5 387 unsigned long uid_long;
3d93ccb7
NS
388 char *sp;
389
272f4db5 390 uid_long = strtoul(user, &sp, 10);
cef37d5a 391 if (sp != user && *sp == '\0') {
272f4db5
AM
392 if ((uid_long == ULONG_MAX && errno == ERANGE)
393 || (uid_long > (uid_t)-1))
394 return -1;
395 return (uid_t)uid_long;
396 }
3d93ccb7
NS
397 pwd = getpwnam(user);
398 if (pwd)
399 return pwd->pw_uid;
400 return -1;
401}
402
403gid_t
404gid_from_string(
405 char *group)
406{
407 struct group *grp;
272f4db5 408 unsigned long gid_long;
3d93ccb7
NS
409 char *sp;
410
272f4db5 411 gid_long = strtoul(group, &sp, 10);
cef37d5a 412 if (sp != group && *sp == '\0') {
272f4db5
AM
413 if ((gid_long == ULONG_MAX && errno == ERANGE)
414 || (gid_long > (gid_t)-1))
415 return -1;
416 return (gid_t)gid_long;
417 }
3d93ccb7
NS
418 grp = getgrnam(group);
419 if (grp)
420 return grp->gr_gid;
421 return -1;
422}
423
fd537fc5
RJ
424bool isdigits_only(
425 const char *str)
426{
427 int i;
428
429 for (i = 0; i < strlen(str); i++) {
430 if (!isdigit(str[i]))
431 return false;
432 }
433 return true;
434}
435
3d93ccb7
NS
436#define HAVE_FTW_H 1 /* TODO: configure me */
437
438#ifndef HAVE_FTW_H
439int
440nftw(
441 char *dir,
442 int (*fn)(const char *, const struct stat *, int, struct FTW *),
443 int depth,
444 int flags)
445{
446 fprintf(stderr, "%s: not implemented, no recursion available\n",
447 __FUNCTION__);
448 return 0;
449}
450#endif