chiark / gitweb /
Properly check for overflow in offsets
[elogind.git] / src / shared / util.c
index 1fc6c5aa1adf63476e1c7406b527b51f2896bd1f..17928ec36ee287c4f2ffb2e9ef541cc3eeee5cf3 100644 (file)
@@ -80,15 +80,6 @@ char **saved_argv = NULL;
 static volatile unsigned cached_columns = 0;
 static volatile unsigned cached_lines = 0;
 
-#define procfs_file_alloca(pid, field)                                  \
-        ({                                                              \
-                pid_t _pid_ = (pid);                                    \
-                char *_r_;                                              \
-                _r_ = alloca(sizeof("/proc/") -1 + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
-                sprintf(_r_, "/proc/%lu/" field, (unsigned long) _pid_); \
-                _r_;                                                    \
-        })
-
 size_t page_size(void) {
         static __thread size_t pgsz = 0;
         long r;
@@ -381,8 +372,10 @@ int safe_atod(const char *s, double *ret_d) {
         assert(s);
         assert(ret_d);
 
-        errno = 0;
-        d = strtod(s, &x);
+        RUN_WITH_LOCALE(LC_NUMERIC_MASK, "C") {
+                errno = 0;
+                d = strtod(s, &x);
+        }
 
         if (!x || x == s || *x || errno)
                 return errno ? -errno : -EINVAL;
@@ -857,18 +850,18 @@ int readlink_malloc(const char *p, char **r) {
 }
 
 int readlink_and_make_absolute(const char *p, char **r) {
-        char *target, *k;
+        _cleanup_free_ char *target = NULL;
+        char *k;
         int j;
 
         assert(p);
         assert(r);
 
-        if ((j = readlink_malloc(p, &target)) < 0)
+        j = readlink_malloc(p, &target);
+        if (j < 0)
                 return j;
 
         k = file_in_same_dir(p, target);
-        free(target);
-
         if (!k)
                 return -ENOMEM;
 
@@ -1456,7 +1449,7 @@ char *ascii_strlower(char *t) {
         return t;
 }
 
-static bool ignore_file_allow_backup(const char *filename) {
+_pure_ static bool ignore_file_allow_backup(const char *filename) {
         assert(filename);
 
         return
@@ -1519,7 +1512,7 @@ int fd_cloexec(int fd, bool cloexec) {
         return 0;
 }
 
-static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
+_pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
         unsigned i;
 
         assert(n_fdset == 0 || fdset);
@@ -2268,7 +2261,7 @@ ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
 int parse_bytes(const char *t, off_t *bytes) {
         static const struct {
                 const char *suffix;
-                off_t factor;
+                unsigned long long factor;
         } table[] = {
                 { "B", 1 },
                 { "K", 1024ULL },
@@ -2281,7 +2274,7 @@ int parse_bytes(const char *t, off_t *bytes) {
         };
 
         const char *p;
-        off_t r = 0;
+        unsigned long long r = 0;
 
         assert(t);
         assert(bytes);
@@ -2308,7 +2301,17 @@ int parse_bytes(const char *t, off_t *bytes) {
 
                 for (i = 0; i < ELEMENTSOF(table); i++)
                         if (startswith(e, table[i].suffix)) {
-                                r += (off_t) l * table[i].factor;
+                                unsigned long long tmp;
+                                if ((unsigned long long) l > ULLONG_MAX / table[i].factor)
+                                        return -ERANGE;
+                                tmp = l * table[i].factor;
+                                if (tmp > ULLONG_MAX - r)
+                                        return -ERANGE;
+
+                                r += tmp;
+                                if ((unsigned long long) (off_t) r != r)
+                                        return -ERANGE;
+
                                 p = e + strlen(table[i].suffix);
                                 break;
                         }
@@ -2316,7 +2319,7 @@ int parse_bytes(const char *t, off_t *bytes) {
                 if (i >= ELEMENTSOF(table))
                         return -EINVAL;
 
-        } while (*p != 0);
+        } while (*p);
 
         *bytes = r;
 
@@ -2777,7 +2780,7 @@ int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct
         return ret;
 }
 
-static int is_temporary_fs(struct statfs *s) {
+_pure_ static int is_temporary_fs(struct statfs *s) {
         assert(s);
         return
                 F_TYPE_CMP(s->f_type, TMPFS_MAGIC) ||
@@ -3845,24 +3848,29 @@ bool hostname_is_valid(const char *s) {
         return true;
 }
 
-char* hostname_cleanup(char *s) {
+char* hostname_cleanup(char *s, bool lowercase) {
         char *p, *d;
         bool dot;
 
         for (p = s, d = s, dot = true; *p; p++) {
                 if (*p == '.') {
-                        if (dot || p[1] == 0)
+                        if (dot)
                                 continue;
 
+                        *(d++) = '.';
                         dot = true;
-                } else
+                } else if (hostname_valid_char(*p)) {
+                        *(d++) = lowercase ? tolower(*p) : *p;
                         dot = false;
+                }
 
-                if (hostname_valid_char(*p))
-                        *(d++) = *p;
         }
 
-        *d = 0;
+        if (dot && d > s)
+                d[-1] = 0;
+        else
+                *d = 0;
+
         strshorten(s, HOST_NAME_MAX);
 
         return s;
@@ -5097,59 +5105,6 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value) {
         return r;
 }
 
-int can_sleep(const char *type) {
-        char *w, *state;
-        size_t l, k;
-        int r;
-        _cleanup_free_ char *p = NULL;
-
-        assert(type);
-
-        /* If /sys is read-only we cannot sleep */
-        if (access("/sys/power/state", W_OK) < 0)
-                return false;
-
-        r = read_one_line_file("/sys/power/state", &p);
-        if (r < 0)
-                return false;
-
-        k = strlen(type);
-        FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state)
-                if (l == k && memcmp(w, type, l) == 0)
-                        return true;
-
-        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);
-
-        /* If /sys is read-only we cannot sleep */
-        if (access("/sys/power/state", W_OK) < 0 ||
-            access("/sys/power/disk", W_OK) < 0)
-                return false;
-
-        r = read_one_line_file("/sys/power/disk", &p);
-        if (r < 0)
-                return false;
-
-        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);
 
@@ -5861,3 +5816,58 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need) {
         *allocated = a;
         return q;
 }
+
+bool id128_is_valid(const char *s) {
+        size_t i, l;
+
+        l = strlen(s);
+        if (l == 32) {
+
+                /* Simple formatted 128bit hex string */
+
+                for (i = 0; i < l; i++) {
+                        char c = s[i];
+
+                        if (!(c >= '0' && c <= '9') &&
+                            !(c >= 'a' && c <= 'z') &&
+                            !(c >= 'A' && c <= 'Z'))
+                                return false;
+                }
+
+        } else if (l == 36) {
+
+                /* Formatted UUID */
+
+                for (i = 0; i < l; i++) {
+                        char c = s[i];
+
+                        if ((i == 8 || i == 13 || i == 18 || i == 23)) {
+                                if (c != '-')
+                                        return false;
+                        } else {
+                                if (!(c >= '0' && c <= '9') &&
+                                    !(c >= 'a' && c <= 'z') &&
+                                    !(c >= 'A' && c <= 'Z'))
+                                        return false;
+                        }
+                }
+
+        } else
+                return false;
+
+        return true;
+}
+
+void parse_user_at_host(char *arg, char **user, char **host) {
+        assert(arg);
+        assert(user);
+        assert(host);
+
+        *host = strchr(arg, '@');
+        if (*host == NULL)
+                *host = arg;
+        else {
+                *host[0]++ = '\0';
+                *user = arg;
+        }
+}