]>
Commit | Line | Data |
---|---|---|
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 |
30 | extern char *progname; |
31 | ||
d4b9ebda NS |
32 | static char * |
33 | get_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) | |
43 | char * | |
44 | fetchline(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) | |
54 | static char *el_get_prompt(EditLine *e) { return get_prompt(); } | |
55 | char * | |
56 | fetchline(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 |
84 | char * |
85 | fetchline(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 |
104 | char ** |
105 | breakline( | |
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 | ||
129 | void | |
130 | doneline( | |
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 |
145 | long long |
146 | cvtnum( | |
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 | ||
193 | void | |
194 | cvtstr( | |
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 | ||
232 | unsigned long | |
233 | cvttime( | |
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 | ||
263 | struct timeval | |
264 | tadd(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 |
275 | struct timeval |
276 | tsub(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 | ||
287 | double | |
288 | tdiv(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 | ||
297 | void | |
298 | timestr( | |
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 | ||
334 | prid_t | |
335 | prid_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 | ||
355 | uid_t | |
356 | uid_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 | ||
372 | gid_t | |
373 | gid_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 | |
392 | int | |
393 | nftw( | |
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 |