summaryrefslogtreecommitdiff
path: root/src/shared/kbd-util.c
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-03-04 09:39:29 +0100
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-03-04 09:39:29 +0100
commit315edc2c115a28e9a9463ad5e914610ce893e170 (patch)
tree7c8757828101b82585792cf8b41b40011b30041a /src/shared/kbd-util.c
parent7e40042b55c245ffd449e764edfc4dd7c0aa0094 (diff)
downloadsystemd-315edc2c115a28e9a9463ad5e914610ce893e170.tar.gz
Move basic/kbd-util to shared/
It is (or should be used) in localectl, localed, and a few other places, no reason to keep it in basic/.
Diffstat (limited to 'src/shared/kbd-util.c')
-rw-r--r--src/shared/kbd-util.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/src/shared/kbd-util.c b/src/shared/kbd-util.c
new file mode 100644
index 0000000000..79ae962530
--- /dev/null
+++ b/src/shared/kbd-util.c
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <ftw.h>
+
+#include "kbd-util.h"
+#include "log.h"
+#include "nulstr-util.h"
+#include "path-util.h"
+#include "set.h"
+#include "string-util.h"
+#include "strv.h"
+#include "utf8.h"
+
+static thread_local Set *keymaps = NULL;
+
+static int nftw_cb(
+ const char *fpath,
+ const struct stat *sb,
+ int tflag,
+ struct FTW *ftwbuf) {
+
+ _cleanup_free_ char *p = NULL;
+ char *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;
+
+ if (!keymap_is_valid(p))
+ return 0;
+
+ r = set_consume(keymaps, TAKE_PTR(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_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 = TAKE_PTR(l);
+
+ 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;
+}