chiark / gitweb /
shared/util: Fix glob_extend() argument
[elogind.git] / src / shared / util.c
index 31cea79f8b4674b6db33b96768bc9ebe760d5078..182277030440d34840ce9d1ad032736d25f5b6be 100644 (file)
@@ -74,6 +74,8 @@
 #include "env-util.h"
 #include "fileio.h"
 #include "device-nodes.h"
+#include "utf8.h"
+#include "gunicode.h"
 
 int saved_argc = 0;
 char **saved_argv = NULL;
@@ -641,7 +643,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
 
         /* Kernel threads have no argv[] */
         if (r == NULL || r[0] == 0) {
-                char *t;
+                _cleanup_free_ char *t = NULL;
                 int h;
 
                 free(r);
@@ -654,8 +656,6 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
                         return h;
 
                 r = strjoin("[", t, "]", NULL);
-                free(t);
-
                 if (!r)
                         return -ENOMEM;
         }
@@ -3288,7 +3288,7 @@ int running_in_chroot(void) {
                 a.st_ino != b.st_ino;
 }
 
-char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
+static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
         size_t x;
         char *r;
 
@@ -3319,6 +3319,80 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
         return r;
 }
 
+char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
+        size_t x;
+        char *e;
+        const char *i, *j;
+        unsigned k, len, len2;
+
+        assert(s);
+        assert(percent <= 100);
+        assert(new_length >= 3);
+
+        /* if no multibyte characters use ascii_ellipsize_mem for speed */
+        if (ascii_is_valid(s))
+                return ascii_ellipsize_mem(s, old_length, new_length, percent);
+
+        if (old_length <= 3 || old_length <= new_length)
+                return strndup(s, old_length);
+
+        x = (new_length * percent) / 100;
+
+        if (x > new_length - 3)
+                x = new_length - 3;
+
+        k = 0;
+        for (i = s; k < x && i < s + old_length; i = utf8_next_char(i)) {
+                int c;
+
+                c = utf8_encoded_to_unichar(i);
+                if (c < 0)
+                        return NULL;
+                k += unichar_iswide(c) ? 2 : 1;
+        }
+
+        if (k > x) /* last character was wide and went over quota */
+                x ++;
+
+        for (j = s + old_length; k < new_length && j > i; ) {
+                int c;
+
+                j = utf8_prev_char(j);
+                c = utf8_encoded_to_unichar(j);
+                if (c < 0)
+                        return NULL;
+                k += unichar_iswide(c) ? 2 : 1;
+        }
+        assert(i <= j);
+
+        /* we don't actually need to ellipsize */
+        if (i == j)
+                return memdup(s, old_length + 1);
+
+        /* make space for ellipsis */
+        j = utf8_next_char(j);
+
+        len = i - s;
+        len2 = s + old_length - j;
+        e = new(char, len + 3 + len2 + 1);
+        if (!e)
+                return NULL;
+
+        /*
+        printf("old_length=%zu new_length=%zu x=%zu len=%u len2=%u k=%u\n",
+               old_length, new_length, x, len, len2, k);
+        */
+
+        memcpy(e, s, len);
+        e[len]   = 0xe2; /* tri-dot ellipsis: … */
+        e[len + 1] = 0x80;
+        e[len + 2] = 0xa6;
+
+        memcpy(e + len + 3, j, len2 + 1);
+
+        return e;
+}
+
 char *ellipsize(const char *s, size_t length, unsigned percent) {
         return ellipsize_mem(s, strlen(s), length, percent);
 }
@@ -4387,7 +4461,7 @@ int glob_extend(char ***strv, const char *path) {
         char **p;
 
         errno = 0;
-        k = glob(optarg, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
+        k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
 
         if (k == GLOB_NOMATCH)
                 return -ENOENT;