X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;ds=sidebyside;f=src%2Fshared%2Futil.c;h=2d4a4c1102bd2f082c247f2c38dc27e873321210;hb=6524990fdc98370ecba5d9f73e67161e8798c010;hp=15481b6b9d933350cfeccc3e5668e3b10512268e;hpb=cfbc22abd0525570a6e58968d518ea9a7d0403ba;p=elogind.git diff --git a/src/shared/util.c b/src/shared/util.c index 15481b6b9..2d4a4c110 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; @@ -143,6 +144,10 @@ dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) { usec_t timespec_load(const struct timespec *ts) { assert(ts); + if (ts->tv_sec == (time_t) -1 && + ts->tv_nsec == (long) -1) + return (usec_t) -1; + return (usec_t) ts->tv_sec * USEC_PER_SEC + (usec_t) ts->tv_nsec / NSEC_PER_USEC; @@ -151,6 +156,12 @@ usec_t timespec_load(const struct timespec *ts) { struct timespec *timespec_store(struct timespec *ts, usec_t u) { assert(ts); + if (u == (usec_t) -1) { + ts->tv_sec = (time_t) -1; + ts->tv_nsec = (long) -1; + return ts; + } + ts->tv_sec = (time_t) (u / USEC_PER_SEC); ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC); @@ -160,6 +171,10 @@ struct timespec *timespec_store(struct timespec *ts, usec_t u) { usec_t timeval_load(const struct timeval *tv) { assert(tv); + if (tv->tv_sec == (time_t) -1 && + tv->tv_usec == (suseconds_t) -1) + return (usec_t) -1; + return (usec_t) tv->tv_sec * USEC_PER_SEC + (usec_t) tv->tv_usec; @@ -168,13 +183,19 @@ usec_t timeval_load(const struct timeval *tv) { struct timeval *timeval_store(struct timeval *tv, usec_t u) { assert(tv); + if (u == (usec_t) -1) { + tv->tv_sec = (time_t) -1; + tv->tv_usec = (suseconds_t) -1; + return tv; + } + tv->tv_sec = (time_t) (u / USEC_PER_SEC); tv->tv_usec = (suseconds_t) (u % USEC_PER_SEC); return tv; } -bool endswith(const char *s, const char *postfix) { +char* endswith(const char *s, const char *postfix) { size_t sl, pl; assert(s); @@ -184,53 +205,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) { @@ -1939,7 +1956,7 @@ char *format_timestamp(char *buf, size_t l, usec_t t) { sec = (time_t) (t / USEC_PER_SEC); - if (strftime(buf, l, "%a, %d %b %Y %H:%M:%S %z", localtime_r(&sec, &tm)) <= 0) + if (strftime(buf, l, "%a, %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm)) <= 0) return NULL; return buf; @@ -2155,28 +2172,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); @@ -3773,46 +3787,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 (_likely_(cached_columns > 0)) + return cached_columns; - if (parsed_columns <= 0 || !cached) - parsed_columns = fd_columns(STDOUT_FILENO); - - 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) { @@ -3829,23 +3823,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 (l <= 0) + l = fd_lines(STDOUT_FILENO); + + if (l <= 0) + l = 24; - if (parsed_lines <= 0) - parsed_lines = fd_lines(STDOUT_FILENO); + 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 (parsed_lines <= 0) - parsed_lines = 25; + if (_unlikely_(cached_on_tty < 0)) + cached_on_tty = isatty(STDOUT_FILENO) > 0; - return parsed_lines; + return cached_on_tty; } int running_in_chroot(void) { @@ -5680,6 +5691,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); @@ -5909,7 +5944,7 @@ bool string_is_safe(const char *p) { assert(p); for (t = p; *t; t++) { - if (*t < ' ') + if (*t > 0 && *t < ' ') return false; if (strchr("\\\"\'", *t)) @@ -6051,3 +6086,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; +}