]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxcmd/input.c
xfsprogs: fix depend targets
[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
2a1888c5 19#include <xfs/xfs.h>
3d93ccb7 20#include <xfs/input.h>
fd2d0648 21#include <ctype.h>
e246ba5f 22
d4b9ebda 23#if defined(ENABLE_READLINE)
e246ba5f
NS
24# include <readline/history.h>
25# include <readline/readline.h>
d4b9ebda
NS
26#elif defined(ENABLE_EDITLINE)
27# include <histedit.h>
28#endif
29
2a1888c5
NS
30extern char *progname;
31
d4b9ebda
NS
32static char *
33get_prompt(void)
34{
3d93ccb7 35 static char prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ];
d4b9ebda
NS
36
37 if (!prompt[0])
38 snprintf(prompt, sizeof(prompt), "%s> ", progname);
39 return prompt;
40}
41
42#if defined(ENABLE_READLINE)
43char *
44fetchline(void)
45{
46 char *line;
47
48 line = readline(get_prompt());
49 if (line && *line)
50 add_history(line);
51 return line;
52}
53#elif defined(ENABLE_EDITLINE)
54static char *el_get_prompt(EditLine *e) { return get_prompt(); }
55char *
56fetchline(void)
57{
58 static EditLine *el;
59 static History *hist;
60 HistEvent hevent;
61 char *line;
62 int count;
63
64 if (!el) {
65 hist = history_init();
66 history(hist, &hevent, H_SETSIZE, 100);
67 el = el_init(progname, stdin, stdout, stderr);
68 el_source(el, NULL);
69 el_set(el, EL_SIGNAL, 1);
70 el_set(el, EL_PROMPT, el_get_prompt);
71 el_set(el, EL_HIST, history, (const char *)hist);
72 }
73 line = strdup(el_gets(el, &count));
74 if (line) {
75 if (count > 0)
76 line[count-1] = '\0';
77 if (*line)
78 history(hist, &hevent, H_ENTER, line);
79 }
80 return line;
81}
e246ba5f
NS
82#else
83# define MAXREADLINESZ 1024
d4b9ebda
NS
84char *
85fetchline(void)
e246ba5f
NS
86{
87 char *p, *line = malloc(MAXREADLINESZ);
88
89 if (!line)
90 return NULL;
d4b9ebda 91 printf(get_prompt());
e246ba5f
NS
92 fflush(stdout);
93 if (!fgets(line, MAXREADLINESZ, stdin)) {
94 free(line);
95 return NULL;
96 }
97 p = line + strlen(line);
98 if (p != line && p[-1] == '\n')
99 p[-1] = '\0';
100 return line;
101}
e246ba5f
NS
102#endif
103
e246ba5f
NS
104char **
105breakline(
106 char *input,
107 int *count)
108{
109 int c = 0;
110 char *p;
111 char **rval = calloc(sizeof(char *), 1);
112
3d93ccb7 113 while (rval && (p = strsep(&input, " ")) != NULL) {
e246ba5f
NS
114 if (!*p)
115 continue;
116 c++;
117 rval = realloc(rval, sizeof(*rval) * (c + 1));
3d93ccb7
NS
118 if (!rval) {
119 c = 0;
120 break;
121 }
e246ba5f
NS
122 rval[c - 1] = p;
123 rval[c] = NULL;
124 }
125 *count = c;
126 return rval;
127}
128
129void
130doneline(
131 char *input,
132 char **vec)
133{
134 free(input);
135 free(vec);
136}
638473d8 137
92d9b902
NS
138#define EXABYTES(x) ((long long)(x) << 60)
139#define PETABYTES(x) ((long long)(x) << 50)
140#define TERABYTES(x) ((long long)(x) << 40)
141#define GIGABYTES(x) ((long long)(x) << 30)
142#define MEGABYTES(x) ((long long)(x) << 20)
143#define KILOBYTES(x) ((long long)(x) << 10)
144
638473d8
NS
145long long
146cvtnum(
2c2f6d79
NS
147 size_t blocksize,
148 size_t sectorsize,
638473d8
NS
149 char *s)
150{
151 long long i;
152 char *sp;
d347f827 153 int c;
638473d8
NS
154
155 i = strtoll(s, &sp, 0);
156 if (i == 0 && sp == s)
157 return -1LL;
158 if (*sp == '\0')
159 return i;
160
f63b46a2 161 if (sp[1] != '\0')
d347f827
NS
162 return -1LL;
163
164 c = tolower(*sp);
165 switch (c) {
166 case 'b':
638473d8 167 return i * blocksize;
d347f827 168 case 's':
638473d8 169 return i * sectorsize;
d347f827 170 case 'k':
92d9b902 171 return KILOBYTES(i);
d347f827 172 case 'm':
92d9b902 173 return MEGABYTES(i);
d347f827 174 case 'g':
92d9b902 175 return GIGABYTES(i);
d347f827 176 case 't':
92d9b902 177 return TERABYTES(i);
d347f827 178 case 'p':
92d9b902 179 return PETABYTES(i);
d347f827 180 case 'e':
92d9b902 181 return EXABYTES(i);
d347f827 182 }
638473d8
NS
183 return -1LL;
184}
92d9b902
NS
185
186#define TO_EXABYTES(x) ((x) / EXABYTES(1))
187#define TO_PETABYTES(x) ((x) / PETABYTES(1))
188#define TO_TERABYTES(x) ((x) / TERABYTES(1))
189#define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
190#define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
191#define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
192
193void
194cvtstr(
195 double value,
196 char *str,
197 size_t size)
198{
199 char *fmt;
200 int precise;
201
202 precise = ((double)value * 1000 == (double)(int)value * 1000);
203
204 if (value >= EXABYTES(1)) {
205 fmt = precise ? "%.f EiB" : "%.3f EiB";
206 snprintf(str, size, fmt, TO_EXABYTES(value));
207 } else if (value >= PETABYTES(1)) {
208 fmt = precise ? "%.f PiB" : "%.3f PiB";
209 snprintf(str, size, fmt, TO_PETABYTES(value));
210 } else if (value >= TERABYTES(1)) {
211 fmt = precise ? "%.f TiB" : "%.3f TiB";
212 snprintf(str, size, fmt, TO_TERABYTES(value));
213 } else if (value >= GIGABYTES(1)) {
214 fmt = precise ? "%.f GiB" : "%.3f GiB";
215 snprintf(str, size, fmt, TO_GIGABYTES(value));
216 } else if (value >= MEGABYTES(1)) {
217 fmt = precise ? "%.f MiB" : "%.3f MiB";
218 snprintf(str, size, fmt, TO_MEGABYTES(value));
219 } else if (value >= KILOBYTES(1)) {
220 fmt = precise ? "%.f KiB" : "%.3f KiB";
221 snprintf(str, size, fmt, TO_KILOBYTES(value));
222 } else {
223 snprintf(str, size, "%f bytes", value);
224 }
225}
226
3d93ccb7
NS
227#define MINUTES_TO_SECONDS(m) ((m) * 60)
228#define HOURS_TO_SECONDS(h) ((h) * MINUTES_TO_SECONDS(60))
229#define DAYS_TO_SECONDS(d) ((d) * HOURS_TO_SECONDS(24))
230#define WEEKS_TO_SECONDS(w) ((w) * DAYS_TO_SECONDS(7))
231
232unsigned long
233cvttime(
234 char *s)
235{
236 unsigned long i;
237 char *sp;
238
239 i = strtoul(s, &sp, 0);
240 if (i == 0 && sp == s)
241 return 0;
242 if (*sp == '\0')
243 return i;
244 if ((*sp == 'm' && sp[1] == '\0') ||
245 (strcmp(sp, "minutes") == 0) ||
246 (strcmp(sp, "minute") == 0))
247 return MINUTES_TO_SECONDS(i);
248 if ((*sp == 'h' && sp[1] == '\0') ||
249 (strcmp(sp, "hours") == 0) ||
250 (strcmp(sp, "hour") == 0))
251 return HOURS_TO_SECONDS(i);
252 if ((*sp == 'd' && sp[1] == '\0') ||
253 (strcmp(sp, "days") == 0) ||
254 (strcmp(sp, "day") == 0))
255 return DAYS_TO_SECONDS(i);
256 if ((*sp == 'w' && sp[1] == '\0') ||
257 (strcmp(sp, "weeks") == 0) ||
258 (strcmp(sp, "week") == 0))
259 return WEEKS_TO_SECONDS(i);
260 return 0;
261}
262
263struct timeval
264tadd(struct timeval t1, struct timeval t2)
265{
266 t1.tv_usec += t2.tv_usec;
267 if (t1.tv_usec > 1000000) {
268 t1.tv_usec -= 1000000;
269 t1.tv_sec++;
270 }
271 t1.tv_sec += t2.tv_sec;
272 return t1;
273}
274
92d9b902
NS
275struct timeval
276tsub(struct timeval t1, struct timeval t2)
277{
278 t1.tv_usec -= t2.tv_usec;
279 if (t1.tv_usec < 0) {
280 t1.tv_usec += 1000000;
281 t1.tv_sec--;
282 }
283 t1.tv_sec -= t2.tv_sec;
284 return t1;
285}
286
287double
288tdiv(double value, struct timeval tv)
289{
290 return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
291}
292
293#define HOURS(sec) ((sec) / (60 * 60))
294#define MINUTES(sec) (((sec) % (60 * 60)) / 60)
295#define SECONDS(sec) ((sec) % 60)
296
297void
298timestr(
299 struct timeval *tv,
300 char *ts,
5c7bef67
NS
301 size_t size,
302 int format)
92d9b902 303{
5c7bef67
NS
304 double usec = (double)tv->tv_usec / 1000000.0;
305
306 if (format & TERSE_FIXED_TIME) {
307 if (!HOURS(tv->tv_sec)) {
308 snprintf(ts, size, "%u:%02u.%02u",
309 (unsigned int) MINUTES(tv->tv_sec),
310 (unsigned int) SECONDS(tv->tv_sec),
311 (unsigned int) usec * 100);
312 return;
313 }
314 format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
315 }
316
317 if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
318 snprintf(ts, size, "%u:%02u:%02u.%02u",
92d9b902
NS
319 (unsigned int) HOURS(tv->tv_sec),
320 (unsigned int) MINUTES(tv->tv_sec),
321 (unsigned int) SECONDS(tv->tv_sec),
5c7bef67
NS
322 (unsigned int) usec * 100);
323 } else {
324 snprintf(ts, size, "0.%04u sec", (unsigned int) usec * 10000);
325 }
92d9b902 326}
3d93ccb7
NS
327
328/*
329 * Convert from arbitrary user strings into a numeric ID.
ff1f79a7 330 * If it's all numeric, we convert that inplace, else we do
3d93ccb7
NS
331 * the name lookup, and return the found identifier.
332 */
333
334prid_t
335prid_from_string(
336 char *project)
337{
338 fs_project_t *prj;
339 prid_t prid;
340 char *sp;
341
1d9d5700
LB
342 /*
343 * Allow either a full numeric or a valid projectname, even
344 * if it starts with a digit.
345 */
2a1888c5 346 prid = (prid_t)strtoul(project, &sp, 10);
1d9d5700 347 if (*project != '\0' && *sp == '\0')
3d93ccb7
NS
348 return prid;
349 prj = getprnam(project);
350 if (prj)
351 return prj->pr_prid;
352 return -1;
353}
354
355uid_t
356uid_from_string(
357 char *user)
358{
359 struct passwd *pwd;
360 uid_t uid;
361 char *sp;
362
2a1888c5 363 uid = (uid_t)strtoul(user, &sp, 10);
3d93ccb7
NS
364 if (sp != user)
365 return uid;
366 pwd = getpwnam(user);
367 if (pwd)
368 return pwd->pw_uid;
369 return -1;
370}
371
372gid_t
373gid_from_string(
374 char *group)
375{
376 struct group *grp;
377 gid_t gid;
378 char *sp;
379
2a1888c5 380 gid = (gid_t)strtoul(group, &sp, 10);
3d93ccb7
NS
381 if (sp != group)
382 return gid;
383 grp = getgrnam(group);
384 if (grp)
385 return grp->gr_gid;
386 return -1;
387}
388
389#define HAVE_FTW_H 1 /* TODO: configure me */
390
391#ifndef HAVE_FTW_H
392int
393nftw(
394 char *dir,
395 int (*fn)(const char *, const struct stat *, int, struct FTW *),
396 int depth,
397 int flags)
398{
399 fprintf(stderr, "%s: not implemented, no recursion available\n",
400 __FUNCTION__);
401 return 0;
402}
403#endif