]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/kbd-util.c
license: LGPL-2.1+ -> LGPL-2.1-or-later
[thirdparty/systemd.git] / src / basic / kbd-util.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
f05e1d0d
LP
2
3#include <ftw.h>
4
5#include "kbd-util.h"
6#include "log.h"
d8b4d14d 7#include "nulstr-util.h"
f05e1d0d
LP
8#include "path-util.h"
9#include "set.h"
10#include "string-util.h"
11#include "strv.h"
12#include "utf8.h"
13
14static thread_local Set *keymaps = NULL;
15
16static int nftw_cb(
17 const char *fpath,
18 const struct stat *sb,
19 int tflag,
20 struct FTW *ftwbuf) {
21
22 _cleanup_free_ char *p = NULL;
23 char *e;
24 int r;
25
26 if (tflag != FTW_F)
27 return 0;
28
29 if (!endswith(fpath, ".map") &&
30 !endswith(fpath, ".map.gz"))
31 return 0;
32
33 p = strdup(basename(fpath));
34 if (!p)
35 return FTW_STOP;
36
37 e = endswith(p, ".map");
38 if (e)
39 *e = 0;
40
41 e = endswith(p, ".map.gz");
42 if (e)
43 *e = 0;
44
45 if (!keymap_is_valid(p))
46 return 0;
47
48 r = set_consume(keymaps, TAKE_PTR(p));
49 if (r < 0 && r != -EEXIST)
50 return r;
51
52 return 0;
53}
54
55int get_keymaps(char ***ret) {
56 _cleanup_strv_free_ char **l = NULL;
57 const char *dir;
58 int r;
59
60 keymaps = set_new(&string_hash_ops);
61 if (!keymaps)
62 return -ENOMEM;
63
64 NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) {
65 r = nftw(dir, nftw_cb, 20, FTW_PHYS|FTW_ACTIONRETVAL);
66
67 if (r == FTW_STOP)
68 log_debug("Directory not found %s", dir);
69 else if (r < 0)
70 log_debug_errno(r, "Can't add keymap: %m");
71 }
72
73 l = set_get_strv(keymaps);
74 if (!l) {
75 set_free_free(keymaps);
76 return -ENOMEM;
77 }
78
79 set_free(keymaps);
80
81 if (strv_isempty(l))
82 return -ENOENT;
83
84 strv_sort(l);
85
86 *ret = TAKE_PTR(l);
87
88 return 0;
89}
90
91bool keymap_is_valid(const char *name) {
92
93 if (isempty(name))
94 return false;
95
96 if (strlen(name) >= 128)
97 return false;
98
99 if (!utf8_is_valid(name))
100 return false;
101
102 if (!filename_is_valid(name))
103 return false;
104
105 if (!string_is_safe(name))
106 return false;
107
108 return true;
109}