kbd-util: allow to override the default keymap directories

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.
This commit is contained in:
Yu Watanabe 2024-03-14 18:40:14 +09:00
parent 361c5b4beb
commit e852f10cb4
4 changed files with 55 additions and 19 deletions

View 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`

View 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;
}

View 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"
@ -11,6 +11,25 @@
#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;

View 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);