]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/basic/locale-util.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / basic / locale-util.c
index 7784d021684ade1b501a31d8af1e67261f847bae..266cb29936c432e7e3b657d049fca50244c975e0 100644 (file)
@@ -1,5 +1,4 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /***
   This file is part of systemd.
 
@@ -22,6 +21,7 @@
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <ftw.h>
 #include <langinfo.h>
 #include <libintl.h>
 #include <locale.h>
@@ -32,6 +32,7 @@
 #include <sys/mman.h>
 #include <sys/stat.h>
 
+#include "def.h"
 #include "dirent-util.h"
 #include "fd-util.h"
 #include "hashmap.h"
@@ -155,6 +156,8 @@ static int add_locales_from_libdir (Set *locales) {
         FOREACH_DIRENT(entry, dir, return -errno) {
                 char *z;
 
+                dirent_ensure_type(dir, entry);
+
                 if (entry->d_type != DT_DIR)
                         continue;
 
@@ -270,35 +273,129 @@ out:
         return (bool) cached_answer;
 }
 
+static thread_local Set *keymaps = NULL;
+
+static int nftw_cb(
+                const char *fpath,
+                const struct stat *sb,
+                int tflag,
+                struct FTW *ftwbuf) {
+
+        char *p, *e;
+        int r;
+
+        if (tflag != FTW_F)
+                return 0;
+
+        if (!endswith(fpath, ".map") &&
+            !endswith(fpath, ".map.gz"))
+                return 0;
+
+        p = strdup(basename(fpath));
+        if (!p)
+                return FTW_STOP;
+
+        e = endswith(p, ".map");
+        if (e)
+                *e = 0;
+
+        e = endswith(p, ".map.gz");
+        if (e)
+                *e = 0;
+
+        r = set_consume(keymaps, p);
+        if (r < 0 && r != -EEXIST)
+                return r;
+
+        return 0;
+}
+
+int get_keymaps(char ***ret) {
+        _cleanup_strv_free_ char **l = NULL;
+        const char *dir;
+        int r;
+
+        keymaps = set_new(&string_hash_ops);
+        if (!keymaps)
+                return -ENOMEM;
+
+        NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) {
+                r = nftw(dir, nftw_cb, 20, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
 
-const char *draw_special_char(DrawSpecialChar ch) {
+                if (r == FTW_STOP)
+                        log_debug("Directory not found %s", dir);
+                else if (r < 0)
+                        log_debug_errno(r, "Can't add keymap: %m");
+        }
+
+        l = set_get_strv(keymaps);
+        if (!l) {
+                set_free_free(keymaps);
+                return -ENOMEM;
+        }
 
-        static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
+        set_free(keymaps);
+
+        if (strv_isempty(l))
+                return -ENOENT;
+
+        strv_sort(l);
 
-                /* UTF-8 */ {
-                        [DRAW_TREE_VERTICAL]      = "\342\224\202 ",            /* │  */
-                        [DRAW_TREE_BRANCH]        = "\342\224\234\342\224\200", /* ├─ */
-                        [DRAW_TREE_RIGHT]         = "\342\224\224\342\224\200", /* └─ */
-                        [DRAW_TREE_SPACE]         = "  ",                       /*    */
-                        [DRAW_TRIANGULAR_BULLET]  = "\342\200\243",             /* ‣ */
-                        [DRAW_BLACK_CIRCLE]       = "\342\227\217",             /* ● */
-                        [DRAW_ARROW]              = "\342\206\222",             /* → */
-                        [DRAW_DASH]               = "\342\200\223",             /* – */
+        *ret = l;
+        l = NULL;
+
+        return 0;
+}
+
+bool keymap_is_valid(const char *name) {
+
+        if (isempty(name))
+                return false;
+
+        if (strlen(name) >= 128)
+                return false;
+
+        if (!utf8_is_valid(name))
+                return false;
+
+        if (!filename_is_valid(name))
+                return false;
+
+        if (!string_is_safe(name))
+                return false;
+
+        return true;
+}
+
+const char *special_glyph(SpecialGlyph code) {
+
+        static const char* const draw_table[2][_SPECIAL_GLYPH_MAX] = {
+                /* ASCII fallback */
+                [false] = {
+                        [TREE_VERTICAL]      = "| ",
+                        [TREE_BRANCH]        = "|-",
+                        [TREE_RIGHT]         = "`-",
+                        [TREE_SPACE]         = "  ",
+                        [TRIANGULAR_BULLET]  = ">",
+                        [BLACK_CIRCLE]       = "*",
+                        [ARROW]              = "->",
+                        [MDASH]              = "-",
                 },
 
-                /* ASCII fallback */ {
-                        [DRAW_TREE_VERTICAL]      = "| ",
-                        [DRAW_TREE_BRANCH]        = "|-",
-                        [DRAW_TREE_RIGHT]         = "`-",
-                        [DRAW_TREE_SPACE]         = "  ",
-                        [DRAW_TRIANGULAR_BULLET]  = ">",
-                        [DRAW_BLACK_CIRCLE]       = "*",
-                        [DRAW_ARROW]              = "->",
-                        [DRAW_DASH]               = "-",
-                }
+                /* UTF-8 */
+                [ true ] = {
+                        [TREE_VERTICAL]      = "\342\224\202 ",            /* │  */
+                        [TREE_BRANCH]        = "\342\224\234\342\224\200", /* ├─ */
+                        [TREE_RIGHT]         = "\342\224\224\342\224\200", /* └─ */
+                        [TREE_SPACE]         = "  ",                       /*    */
+                        [TRIANGULAR_BULLET]  = "\342\200\243",             /* ‣ */
+                        [BLACK_CIRCLE]       = "\342\227\217",             /* ● */
+                        [ARROW]              = "\342\206\222",             /* → */
+                        [MDASH]              = "\342\200\223",             /* – */
+                },
         };
 
-        return draw_table[!is_locale_utf8()][ch];
+        return draw_table[is_locale_utf8()][code];
 }
 
 static const char * const locale_variable_table[_VARIABLE_LC_MAX] = {