X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Futil.c;h=9a45e6058e200813fed1bae7ff9d27f0ebb164a5;hb=49371bb50e0fe6e9e90309a20006bcfd9e2fa8f4;hp=1c97a8a94ae65386b7731c672e4e1248d7f65826;hpb=01539d6ef9689ffdc7c0743e12740a78bb938b97;p=elogind.git diff --git a/src/shared/util.c b/src/shared/util.c index 1c97a8a94..9a45e6058 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -72,7 +72,8 @@ int saved_argc = 0; char **saved_argv = NULL; -static int parsed_columns = 0; +static volatile unsigned cached_columns = 0; +static volatile unsigned cached_lines = 0; size_t page_size(void) { static __thread size_t pgsz = 0; @@ -147,6 +148,10 @@ usec_t timespec_load(const struct timespec *ts) { ts->tv_nsec == (long) -1) return (usec_t) -1; + if (ts->tv_sec > 0 && + USEC_PER_SEC > ((UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / (usec_t) ts->tv_sec)) + return (usec_t) -1; + return (usec_t) ts->tv_sec * USEC_PER_SEC + (usec_t) ts->tv_nsec / NSEC_PER_USEC; @@ -174,6 +179,9 @@ usec_t timeval_load(const struct timeval *tv) { tv->tv_usec == (suseconds_t) -1) return (usec_t) -1; + if (USEC_PER_SEC > (UINT64_MAX - tv->tv_usec) / (usec_t) tv->tv_sec) + return (usec_t) -1; + return (usec_t) tv->tv_sec * USEC_PER_SEC + (usec_t) tv->tv_usec; @@ -194,7 +202,7 @@ struct timeval *timeval_store(struct timeval *tv, usec_t u) { return tv; } -bool endswith(const char *s, const char *postfix) { +char* endswith(const char *s, const char *postfix) { size_t sl, pl; assert(s); @@ -204,53 +212,49 @@ bool endswith(const char *s, const char *postfix) { pl = strlen(postfix); if (pl == 0) - return true; + return (char*) s + sl; if (sl < pl) - return false; + return NULL; + + if (memcmp(s + sl - pl, postfix, pl) != 0) + return NULL; - return memcmp(s + sl - pl, postfix, pl) == 0; + return (char*) s + sl - pl; } -bool startswith(const char *s, const char *prefix) { - size_t sl, pl; +char* startswith(const char *s, const char *prefix) { + const char *a, *b; assert(s); assert(prefix); - sl = strlen(s); - pl = strlen(prefix); - - if (pl == 0) - return true; - - if (sl < pl) - return false; + a = s, b = prefix; + for (;;) { + if (*b == 0) + return (char*) a; + if (*a != *b) + return NULL; - return memcmp(s, prefix, pl) == 0; + a++, b++; + } } -bool startswith_no_case(const char *s, const char *prefix) { - size_t sl, pl; - unsigned i; +char* startswith_no_case(const char *s, const char *prefix) { + const char *a, *b; assert(s); assert(prefix); - sl = strlen(s); - pl = strlen(prefix); - - if (pl == 0) - return true; - - if (sl < pl) - return false; - - for(i = 0; i < pl; ++i) - if (tolower(s[i]) != tolower(prefix[i])) - return false; + a = s, b = prefix; + for (;;) { + if (*b == 0) + return (char*) a; + if (tolower(*a) != tolower(*b)) + return NULL; - return true; + a++, b++; + } } bool first_word(const char *s, const char *word) { @@ -2175,28 +2179,25 @@ int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) { } int ask(char *ret, const char *replies, const char *text, ...) { - bool on_tty; assert(ret); assert(replies); assert(text); - on_tty = isatty(STDOUT_FILENO); - for (;;) { va_list ap; char c; int r; bool need_nl = true; - if (on_tty) + if (on_tty()) fputs(ANSI_HIGHLIGHT_ON, stdout); va_start(ap, text); vprintf(text, ap); va_end(ap); - if (on_tty) + if (on_tty()) fputs(ANSI_HIGHLIGHT_OFF, stdout); fflush(stdout); @@ -3793,46 +3794,26 @@ int fd_columns(int fd) { return ws.ws_col; } -static unsigned columns_cached(bool cached) { - static __thread int env_columns = -1; +unsigned columns(void) { const char *e; + unsigned c; - if (_likely_(parsed_columns > 0 && cached)) - return parsed_columns; - - if (_unlikely_(env_columns == -1)) { - e = getenv("COLUMNS"); - if (e) - env_columns = atoi(e); - else - env_columns = 0; - } - - if (env_columns > 0) { - parsed_columns = env_columns; - return parsed_columns; - } - - if (parsed_columns <= 0 || !cached) - parsed_columns = fd_columns(STDOUT_FILENO); + if (_likely_(cached_columns > 0)) + return cached_columns; - if (parsed_columns <= 0) - parsed_columns = 80; + c = 0; + e = getenv("COLUMNS"); + if (e) + safe_atou(e, &c); - return parsed_columns; -} + if (c <= 0) + c = fd_columns(STDOUT_FILENO); -unsigned columns(void) { - return columns_cached(true); -} + if (c <= 0) + c = 80; -unsigned columns_uncached(void) { - return columns_cached(false); -} - -/* intended to be used as a SIGWINCH sighandler */ -void columns_cache_reset(int signum) { - parsed_columns = 0; + cached_columns = c; + return c; } int fd_lines(int fd) { @@ -3849,23 +3830,40 @@ int fd_lines(int fd) { } unsigned lines(void) { - static __thread int parsed_lines = 0; const char *e; + unsigned l; - if (_likely_(parsed_lines > 0)) - return parsed_lines; + if (_likely_(cached_lines > 0)) + return cached_lines; + l = 0; e = getenv("LINES"); if (e) - parsed_lines = atoi(e); + safe_atou(e, &l); - if (parsed_lines <= 0) - parsed_lines = fd_lines(STDOUT_FILENO); + if (l <= 0) + l = fd_lines(STDOUT_FILENO); - if (parsed_lines <= 0) - parsed_lines = 25; + if (l <= 0) + l = 24; - return parsed_lines; + cached_lines = l; + return cached_lines; +} + +/* intended to be used as a SIGWINCH sighandler */ +void columns_lines_cache_reset(int signum) { + cached_columns = 0; + cached_lines = 0; +} + +bool on_tty(void) { + static int cached_on_tty = -1; + + if (_unlikely_(cached_on_tty < 0)) + cached_on_tty = isatty(STDOUT_FILENO) > 0; + + return cached_on_tty; } int running_in_chroot(void) { @@ -5700,6 +5698,30 @@ int can_sleep(const char *type) { return false; } +int can_sleep_disk(const char *type) { + char *w, *state; + size_t l, k; + int r; + _cleanup_free_ char *p = NULL; + + assert(type); + + r = read_one_line_file("/sys/power/disk", &p); + if (r < 0) + return r == -ENOENT ? 0 : r; + + k = strlen(type); + FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state) { + if (l == k && memcmp(w, type, l) == 0) + return true; + + if (l == k + 2 && w[0] == '[' && memcmp(w + 1, type, l - 2) == 0 && w[l-1] == ']') + return true; + } + + return false; +} + bool is_valid_documentation_url(const char *url) { assert(url); @@ -6071,3 +6093,26 @@ finish: return 0; } + +/* hey glibc, APIs with callbacks without a user pointer are so useless */ +void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size, + int (*compar) (const void *, const void *, void *), void *arg) { + size_t l, u, idx; + const void *p; + int comparison; + + l = 0; + u = nmemb; + while (l < u) { + idx = (l + u) / 2; + p = (void *)(((const char *) base) + (idx * size)); + comparison = compar(key, p, arg); + if (comparison < 0) + u = idx; + else if (comparison > 0) + l = idx + 1; + else + return (void *)p; + } + return NULL; +}