]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
kbd-util: allow to override the default keymap directories 31778/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 14 Mar 2024 09:40:14 +0000 (18:40 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 14 Mar 2024 18:19:45 +0000 (03:19 +0900)
This introduces $SYSTEMD_KEYMAP_DIRECTORIES environment variable to
override the hardcoded keymap directories.

I think it is not necessary to provide the first class configuration
option for controlling the keymap directories, but it is not good to
hardcode the paths. So, let's introduce an environment variable to
override that.

Prompted by #31759.

Closes #31759.

docs/ENVIRONMENT.md
src/locale/localed-util.c
src/shared/kbd-util.c
src/shared/kbd-util.h

index cd6d66a81f1118205c9729d4ba09ec1640507edc..cb2c6a8df515c129f2ef0e0a0a65deb2cc39ca44 100644 (file)
@@ -348,12 +348,17 @@ All tools:
   `systemd-gpt-auto-generator` to ensure the root partition is mounted writable
   in accordance to the GPT partition flags.
 
-`systemd-firstboot` and `localectl`:
+`systemd-firstboot`, `localectl`, and `systemd-localed`:
 
 * `$SYSTEMD_LIST_NON_UTF8_LOCALES=1` — if set, non-UTF-8 locales are listed among
   the installed ones. By default non-UTF-8 locales are suppressed from the
   selection, since we are living in the 21st century.
 
+* `$SYSTEMD_KEYMAP_DIRECTORIES=` — takes a colon (`:`) separated list of keymap
+  directories. The directories must be absolute and normalized. If unset, the
+  default keymap directories (/usr/share/keymaps/, /usr/share/kbd/keymaps/, and
+  /usr/lib/kbd/keymaps/) will be used.
+
 `systemd-resolved`:
 
 * `$SYSTEMD_RESOLVED_SYNTHESIZE_HOSTNAME` — if set to "0", `systemd-resolved`
index de88df163d0417d9bbeaad4b10dad2f6c70c54aa..56996596fe13ce07134f498aef25a73ac6503cab 100644 (file)
@@ -736,6 +736,8 @@ int vconsole_convert_to_x11(const VCContext *vc, X11Context *ret) {
 
 int find_converted_keymap(const X11Context *xc, char **ret) {
         _cleanup_free_ char *n = NULL, *p = NULL, *pz = NULL;
+        _cleanup_strv_free_ char **keymap_dirs = NULL;
+        int r;
 
         assert(xc);
         assert(!isempty(xc->layout));
@@ -753,20 +755,24 @@ int find_converted_keymap(const X11Context *xc, char **ret) {
         if (!p || !pz)
                 return -ENOMEM;
 
-        NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) {
+        r = keymap_directories(&keymap_dirs);
+        if (r < 0)
+                return r;
+
+        STRV_FOREACH(dir, keymap_dirs) {
                 _cleanup_close_ int dir_fd = -EBADF;
                 bool uncompressed;
 
-                dir_fd = open(dir, O_CLOEXEC | O_DIRECTORY | O_PATH);
+                dir_fd = open(*dir, O_CLOEXEC | O_DIRECTORY | O_PATH);
                 if (dir_fd < 0) {
                         if (errno != ENOENT)
-                                log_debug_errno(errno, "Failed to open %s, ignoring: %m", dir);
+                                log_debug_errno(errno, "Failed to open %s, ignoring: %m", *dir);
                         continue;
                 }
 
                 uncompressed = faccessat(dir_fd, p, F_OK, 0) >= 0;
                 if (uncompressed || faccessat(dir_fd, pz, F_OK, 0) >= 0) {
-                        log_debug("Found converted keymap %s at %s/%s", n, dir, uncompressed ? p : pz);
+                        log_debug("Found converted keymap %s at %s/%s", n, *dir, uncompressed ? p : pz);
                         *ret = TAKE_PTR(n);
                         return 1;
                 }
index 2f2d161ca68e4d7941719f7b4c5eaaad14e68151..60e0429b82a8c12eb2b65aabde9a4529038b0ed2 100644 (file)
@@ -1,9 +1,9 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
+#include "env-util.h"
 #include "errno-util.h"
 #include "kbd-util.h"
 #include "log.h"
-#include "nulstr-util.h"
 #include "path-util.h"
 #include "recurse-dir.h"
 #include "set.h"
 #include "strv.h"
 #include "utf8.h"
 
+#define KBD_KEYMAP_DIRS                         \
+        "/usr/share/keymaps/",                  \
+        "/usr/share/kbd/keymaps/",              \
+        "/usr/lib/kbd/keymaps/"
+
+int keymap_directories(char ***ret) {
+        assert(ret);
+
+        if (getenv_path_list("SYSTEMD_KEYMAP_DIRECTORIES", ret) >= 0)
+                return 0;
+
+        char **paths = strv_new(KBD_KEYMAP_DIRS);
+        if (!paths)
+                return log_oom_debug();
+
+        *ret = TAKE_PTR(paths);
+        return 0;
+}
+
 struct recurse_dir_userdata {
         const char *keymap_name;
         Set *keymaps;
@@ -65,16 +84,21 @@ static int keymap_recurse_dir_callback(
 
 int get_keymaps(char ***ret) {
         _cleanup_set_free_free_ Set *keymaps = NULL;
+        _cleanup_strv_free_ char **keymap_dirs = NULL;
         int r;
 
+        r = keymap_directories(&keymap_dirs);
+        if (r < 0)
+                return r;
+
         keymaps = set_new(&string_hash_ops);
         if (!keymaps)
                 return -ENOMEM;
 
-        NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) {
+        STRV_FOREACH(dir, keymap_dirs) {
                 r = recurse_dir_at(
                                 AT_FDCWD,
-                                dir,
+                                *dir,
                                 /* statx_mask= */ 0,
                                 /* n_depth_max= */ UINT_MAX,
                                 RECURSE_DIR_IGNORE_DOT|RECURSE_DIR_ENSURE_TYPE,
@@ -85,9 +109,9 @@ int get_keymaps(char ***ret) {
                 if (r == -ENOENT)
                         continue;
                 if (ERRNO_IS_NEG_RESOURCE(r))
-                        return log_warning_errno(r, "Failed to read keymap list from %s: %m", dir);
+                        return log_warning_errno(r, "Failed to read keymap list from %s: %m", *dir);
                 if (r < 0)
-                        log_debug_errno(r, "Failed to read keymap list from %s, ignoring: %m", dir);
+                        log_debug_errno(r, "Failed to read keymap list from %s, ignoring: %m", *dir);
         }
 
         _cleanup_strv_free_ char **l = set_get_strv(keymaps);
@@ -127,15 +151,20 @@ bool keymap_is_valid(const char *name) {
 }
 
 int keymap_exists(const char *name) {
+        _cleanup_strv_free_ char **keymap_dirs = NULL;
         int r;
 
         if (!keymap_is_valid(name))
                 return -EINVAL;
 
-        NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) {
+        r = keymap_directories(&keymap_dirs);
+        if (r < 0)
+                return r;
+
+        STRV_FOREACH(dir, keymap_dirs) {
                 r = recurse_dir_at(
                                 AT_FDCWD,
-                                dir,
+                                *dir,
                                 /* statx_mask= */ 0,
                                 /* n_depth_max= */ UINT_MAX,
                                 RECURSE_DIR_IGNORE_DOT|RECURSE_DIR_ENSURE_TYPE,
@@ -148,7 +177,7 @@ int keymap_exists(const char *name) {
                 if (ERRNO_IS_NEG_RESOURCE(r))
                         return r;
                 if (r < 0 && r != -ENOENT)
-                        log_debug_errno(r, "Failed to read keymap list from %s, ignoring: %m", dir);
+                        log_debug_errno(r, "Failed to read keymap list from %s, ignoring: %m", *dir);
         }
 
         return false;
index aca0dee4bc0d2dced15050c3e967f9b77e0bf88c..a8e365e3ca43abaa4d20a00dc5535515506d4482 100644 (file)
@@ -3,11 +3,7 @@
 
 #include <stdbool.h>
 
-#define KBD_KEYMAP_DIRS                         \
-        "/usr/share/keymaps/\0"                 \
-        "/usr/share/kbd/keymaps/\0"             \
-        "/usr/lib/kbd/keymaps/\0"
-
-int get_keymaps(char ***l);
+int keymap_directories(char ***ret);
+int get_keymaps(char ***ret);
 bool keymap_is_valid(const char *name);
 int keymap_exists(const char *name);