chiark / gitweb /
elogind-firstboot: add vconsole keymap support (#7035)
authortblume <Thomas.Blume@suse.com>
Fri, 10 Nov 2017 09:31:44 +0000 (10:31 +0100)
committerSven Eden <yamakuzure@gmx.net>
Fri, 10 Nov 2017 09:31:44 +0000 (10:31 +0100)
Enable elogind-firstboot to set the keymap.

RFE:

https://github.com/elogind/elogind/issues/6346

src/basic/locale-util.c
src/basic/locale-util.h
src/test/test-locale-util.c

index ada0a28cd8423d84ec628422a3c9a4622dd83dd3..0e546c050726732c5daac3546379165d8a609397 100644 (file)
@@ -20,6 +20,7 @@
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <ftw.h>
 #include <langinfo.h>
 #include <libintl.h>
 #include <locale.h>
@@ -30,6 +31,7 @@
 #include <sys/mman.h>
 #include <sys/stat.h>
 
+#include "def.h"
 #include "dirent-util.h"
 #include "fd-util.h"
 #include "hashmap.h"
@@ -270,6 +272,99 @@ 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);
+
+                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;
+        }
+
+        set_free(keymaps);
+
+        if (strv_isempty(l))
+                return -ENOENT;
+
+        strv_sort(l);
+
+        *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) {
 
index 0630a034ab475f48552062c43d9567c9b2a42f7c..104864501dd13080d15fbc7ede47efb60f966d3e 100644 (file)
@@ -71,3 +71,6 @@ const char *special_glyph(SpecialGlyph code) _const_;
 
 const char* locale_variable_to_string(LocaleVariable i) _const_;
 LocaleVariable locale_variable_from_string(const char *s) _pure_;
+
+int get_keymaps(char ***l);
+bool keymap_is_valid(const char *name);
index 427c698d1d0cb2a1829122d58226fb6cd7d9be56..9e69567e4cadee8b76d0230e5be9167290a387de 100644 (file)
@@ -50,9 +50,38 @@ static void test_locale_is_valid(void) {
         assert_se(!locale_is_valid("\x01gar\x02 bage\x03"));
 }
 
+static void test_keymaps(void) {
+        _cleanup_strv_free_ char **kmaps = NULL;
+        char **p;
+        int r;
+
+        assert_se(!keymap_is_valid(""));
+        assert_se(!keymap_is_valid("/usr/bin/foo"));
+        assert_se(!keymap_is_valid("\x01gar\x02 bage\x03"));
+
+        r = get_keymaps(&kmaps);
+        if (r == -ENOENT)
+                return; /* skip test if no keymaps are installed */
+
+        assert_se(r >= 0);
+        assert_se(kmaps);
+
+        STRV_FOREACH(p, kmaps) {
+                puts(*p);
+                assert_se(keymap_is_valid(*p));
+        }
+
+        assert_se(keymap_is_valid("uk"));
+        assert_se(keymap_is_valid("de-nodeadkeys"));
+        assert_se(keymap_is_valid("ANSI-dvorak"));
+        assert_se(keymap_is_valid("unicode"));
+}
+
 int main(int argc, char *argv[]) {
         test_get_locales();
         test_locale_is_valid();
 
+        test_keymaps();
+
         return 0;
 }