diff options
Diffstat (limited to 'utils/open-isns/util.c')
-rw-r--r-- | utils/open-isns/util.c | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/utils/open-isns/util.c b/utils/open-isns/util.c new file mode 100644 index 0000000..4c0a7b2 --- /dev/null +++ b/utils/open-isns/util.c @@ -0,0 +1,263 @@ +/* + * util.c + * + * Misc utility functions + * + * Copyright (C) 2006, 2007 Olaf Kirch <olaf.kirch@oracle.com> + */ + +#include <sys/stat.h> +#include <stdlib.h> +#include <string.h> +#include <err.h> +#include <errno.h> +#include "util.h" + +unsigned long +parse_size(const char *arg) +{ + unsigned long mult = 1, ret; + char *s; + + ret = strtol(arg, &s, 0); + + switch (*s++) { + case 'g': + case 'G': + mult = 1024 * 1024 * 1024; + break; + case 'm': + case 'M': + mult = 1024 * 1024; + break; + case 'k': + case 'K': + mult = 1024; + break; + + case '\0': + return ret; + + default: + bad: + err(1, "parse_size: unknown unit in \"%s\"\n", arg); + } + + if (*s != '\0') + goto bad; + + return mult * ret; +} + +char * +print_size(unsigned long size) +{ + static char unit[] = "-kMG"; + static char buffer[64]; + unsigned int power = 0; + + while (size && !(size % 1024) && power < sizeof(unit)) { + size /= 1024; + power++; + } + + if (!power) { + snprintf(buffer, sizeof(buffer), "%lu", size); + } else { + snprintf(buffer, sizeof(buffer), "%lu%c", + size, unit[power]); + } + return buffer; +} + +unsigned int +parse_count(const char *arg) +{ + unsigned long ret; + char *s; + + ret = strtoul(arg, &s, 0); + if (*s != '\0') + err(1, "parse_count: unexpected character in \"%s\"\n", arg); + + return ret; +} + +int +parse_int(const char *arg) +{ + long ret; + char *s; + + ret = strtol(arg, &s, 0); + if (*s != '\0') + err(1, "parse_count: unexpected character in \"%s\"\n", arg); + + return ret; +} + +long long +parse_longlong(const char *arg) +{ + long long ret; + char *s; + + ret = strtoll(arg, &s, 0); + if (*s != '\0') + err(1, "parse_count: unexpected character in \"%s\"\n", arg); + + return ret; +} + +double +parse_double(const char *arg) +{ + double ret; + char *s; + + ret = strtod(arg, &s); + if (*s != '\0') + err(1, "parse_count: unexpected character in \"%s\"\n", arg); + + return ret; +} + +unsigned int +parse_timeout(const char *arg) +{ + unsigned int v, ret = 0; + char *s; + + do { + v = strtoul(arg, &s, 10); + switch (*s) { + case '\0': + ret += v; + break; + case 'd': + v *= 24; + case 'h': + v *= 60; + case 'm': + v *= 60; + case 's': + ret += v; + ++s; + break; + + default: + errx(1, "parse_timeout: unexpected character in \"%s\"\n", + arg); + } + + arg = s; + } while (*arg); + + return ret; +} + +void +isns_string_array_append(struct string_array *array, const char *val) +{ + if (!(array->count % 32)) { + array->list = isns_realloc(array->list, + (array->count + 32) * sizeof(val)); + } + array->list[array->count++] = val? isns_strdup(val) : NULL; +} + +void +isns_string_array_destroy(struct string_array *array) +{ + unsigned int i; + + for (i = 0; i < array->count; ++i) + isns_free(array->list[i]); + isns_free(array->list); + memset(array, 0, sizeof(*array)); +} + +void +isns_assign_string(char **var, const char *val) +{ + char *s = NULL; + + if (val && !(s = isns_strdup(val))) + errx(1, "out of memory"); + + if (*var) + isns_free(*var); + *var = s; +} + +/* + * Recursively create a directory + */ +int +isns_mkdir_recursive(const char *pathname) +{ + const char *orig_pathname = pathname; + char *squirrel[64]; + char *copy = NULL, *s; + int ns = 0; + + if (!pathname || !strcmp(pathname, ".")) + return 0; + while (1) { + if (mkdir(pathname, 0755) >= 0) { + if (ns == 0) + break; + *squirrel[--ns] = '/'; + continue; + } + + if (errno == EEXIST) + goto good; + if (errno != ENOENT) + goto bad; + + if (copy == NULL) { + copy = isns_strdup(pathname); + pathname = copy; + } + + s = strrchr(copy, '/'); + while (s > copy && s[-1] == '/') + --s; + *s = '\0'; + + isns_assert(ns < 64); + squirrel[ns++] = s; + + if (s == copy) + goto bad; + } + +good: if (copy) + isns_free(copy); + errno = 0; + return 0; + +bad: if (copy) + isns_free(copy); + perror(orig_pathname); + return -1; +} + +/* + * This one differs from POSIX dirname; it does not + * modify its argument + */ +const char * +isns_dirname(const char *pathname) +{ + static char buffer[4096]; + char *s; + + strcpy(buffer, pathname); + if ((s = strrchr(buffer, '/')) != NULL) { + *s = '\0'; + return buffer; + } + return "."; +} |