summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortblume <Thomas.Blume@suse.com>2017-11-10 10:31:44 +0100
committerSven Eden <yamakuzure@gmx.net>2017-11-10 10:31:44 +0100
commitf56ba2f20e14bd1422ea3b080772b602d079a8fc (patch)
treef3002c93643d3d9801a6d0d0b50ed2eab2ffa082 /src
parentea088fe1f51e8679b64e4536c6da1437435f45e6 (diff)
elogind-firstboot: add vconsole keymap support (#7035)
Enable elogind-firstboot to set the keymap. RFE: https://github.com/elogind/elogind/issues/6346
Diffstat (limited to 'src')
-rw-r--r--src/basic/locale-util.c95
-rw-r--r--src/basic/locale-util.h3
-rw-r--r--src/test/test-locale-util.c29
3 files changed, 127 insertions, 0 deletions
diff --git a/src/basic/locale-util.c b/src/basic/locale-util.c
index ada0a28cd..0e546c050 100644
--- a/src/basic/locale-util.c
+++ b/src/basic/locale-util.c
@@ -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) {
diff --git a/src/basic/locale-util.h b/src/basic/locale-util.h
index 0630a034a..104864501 100644
--- a/src/basic/locale-util.h
+++ b/src/basic/locale-util.h
@@ -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);
diff --git a/src/test/test-locale-util.c b/src/test/test-locale-util.c
index 427c698d1..9e69567e4 100644
--- a/src/test/test-locale-util.c
+++ b/src/test/test-locale-util.c
@@ -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;
}