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;
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;
+
+ 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;
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);
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;
+
+ 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;
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);
pl = strlen(postfix);
if (pl == 0)
- return true;
+ return (char*) s + sl;
if (sl < pl)
- return false;
+ return NULL;
- return memcmp(s + sl - pl, postfix, pl) == 0;
+ if (memcmp(s + sl - pl, postfix, pl) != 0)
+ return NULL;
+
+ 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) {
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;
}
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);
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 (_likely_(cached_columns > 0))
+ return cached_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 (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) {
}
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 (parsed_lines <= 0)
- parsed_lines = fd_lines(STDOUT_FILENO);
+ if (l <= 0)
+ l = 24;
- if (parsed_lines <= 0)
- parsed_lines = 25;
+ 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 parsed_lines;
+ return cached_on_tty;
}
int running_in_chroot(void) {
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);
assert(p);
for (t = p; *t; t++) {
- if (*t < ' ')
+ if (*t > 0 && *t < ' ')
return false;
if (strchr("\\\"\'", *t))
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;
+}