chiark / gitweb /
detect-virt: install with fs caps by default to allow unprivileged access
[elogind.git] / src / shared / util.c
index 69c9437db83a826826435bcddbb04603cab02100..6310aec8aaf94342a1e4b141f1d3c8b91220dde6 100644 (file)
@@ -56,6 +56,7 @@
 #include <sys/mman.h>
 #include <sys/vfs.h>
 #include <linux/magic.h>
+#include <limits.h>
 
 #include "macro.h"
 #include "util.h"
@@ -71,6 +72,8 @@
 int saved_argc = 0;
 char **saved_argv = NULL;
 
+static int parsed_columns = 0;
+
 size_t page_size(void) {
         static __thread size_t pgsz = 0;
         long r;
@@ -1184,8 +1187,11 @@ char *strnappend(const char *s, const char *suffix, size_t b) {
         assert(suffix);
 
         a = strlen(s);
+        if (b > ((size_t) -1) - a)
+                return NULL;
 
-        if (!(r = new(char, a+b+1)))
+        r = new(char, a+b+1);
+        if (!r)
                 return NULL;
 
         memcpy(r, s, a);
@@ -1683,7 +1689,8 @@ char *xescape(const char *s, const char *bad) {
          * chars, in \xFF style escaping. May be reversed with
          * cunescape. */
 
-        if (!(r = new(char, strlen(s)*4+1)))
+        r = new(char, strlen(s) * 4 + 1);
+        if (!r)
                 return NULL;
 
         for (f = s, t = r; *f; f++) {
@@ -2956,9 +2963,10 @@ int dir_is_empty(const char *path) {
                 return -errno;
 
         for (;;) {
-                struct dirent buf, *de;
+                struct dirent *de;
+                union dirent_storage buf;
 
-                r = readdir_r(d, &buf, &de);
+                r = readdir_r(d, &buf.de, &de);
                 if (r > 0)
                         return -r;
 
@@ -3260,12 +3268,13 @@ int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct
         }
 
         for (;;) {
-                struct dirent buf, *de;
+                struct dirent *de;
+                union dirent_storage buf;
                 bool is_dir, keep_around;
                 struct stat st;
                 int r;
 
-                r = readdir_r(d, &buf, &de);
+                r = readdir_r(d, &buf.de, &de);
                 if (r != 0 && ret == 0) {
                         ret = -r;
                         break;
@@ -3735,7 +3744,7 @@ int fd_columns(int fd) {
 }
 
 static unsigned columns_cached(bool cached) {
-        static __thread int parsed_columns = 0, env_columns = -1;
+        static __thread int env_columns = -1;
         const char *e;
 
         if (_likely_(parsed_columns > 0 && cached))
@@ -3771,6 +3780,11 @@ 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;
+}
+
 int fd_lines(int fd) {
         struct winsize ws;
         zero(ws);
@@ -4942,10 +4956,11 @@ int get_files_in_directory(const char *path, char ***list) {
                 return -errno;
 
         for (;;) {
-                struct dirent buffer, *de;
+                struct dirent *de;
+                union dirent_storage buf;
                 int k;
 
-                k = readdir_r(d, &buffer, &de);
+                k = readdir_r(d, &buf.de, &de);
                 if (k != 0) {
                         r = -k;
                         goto finish;
@@ -5011,12 +5026,19 @@ char *strjoin(const char *x, ...) {
 
                 for (;;) {
                         const char *t;
+                        size_t n;
 
                         t = va_arg(ap, const char *);
                         if (!t)
                                 break;
 
-                        l += strlen(t);
+                        n = strlen(t);
+                        if (n > ((size_t) -1) - l) {
+                                va_end(ap);
+                                return NULL;
+                        }
+
+                        l += n;
                 }
         } else
                 l = 0;
@@ -5288,7 +5310,7 @@ int signal_from_string(const char *s) {
         int offset = 0;
         unsigned u;
 
-        signo =__signal_from_string(s);
+        signo = __signal_from_string(s);
         if (signo > 0)
                 return signo;
 
@@ -5680,7 +5702,7 @@ void warn_melody(void) {
         if (fd < 0)
                 return;
 
-        /* Yeah, this is synchronous. Kinda sucks. Bute well... */
+        /* Yeah, this is synchronous. Kinda sucks. But well... */
 
         ioctl(fd, KIOCSOUND, (int)(1193180/440));
         usleep(125*USEC_PER_MSEC);
@@ -5830,3 +5852,39 @@ void closedirp(DIR **d) {
 void umaskp(mode_t *u) {
         umask(*u);
 }
+
+bool filename_is_safe(const char *p) {
+
+        if (isempty(p))
+                return false;
+
+        if (strchr(p, '/'))
+                return false;
+
+        if (streq(p, "."))
+                return false;
+
+        if (streq(p, ".."))
+                return false;
+
+        if (strlen(p) > FILENAME_MAX)
+                return false;
+
+        return true;
+}
+
+bool string_is_safe(const char *p) {
+        const char *t;
+
+        assert(p);
+
+        for (t = p; *t; t++) {
+                if (*t < ' ')
+                        return false;
+
+                if (strchr("\\\"\'", *t))
+                        return false;
+        }
+
+        return true;
+}