chiark / gitweb /
util: avoid divide by zero FPE
[elogind.git] / src / shared / util.c
index 2f0aba88ae6e1c443f54b1d821ed25d73649a069..9a45e6058e200813fed1bae7ff9d27f0ebb164a5 100644 (file)
@@ -148,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;
@@ -175,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;
@@ -216,45 +223,38 @@ char* endswith(const char *s, const char *postfix) {
         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) {
@@ -5698,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);
 
@@ -6072,8 +6096,7 @@ finish:
 
 /* 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) {
+                 int (*compar) (const void *, const void *, void *), void *arg) {
         size_t l, u, idx;
         const void *p;
         int comparison;