]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/kbd-util.c
17d4022dbe74c24a3ea53003bc6babd8fc8579b8
[thirdparty/systemd.git] / src / basic / kbd-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <ftw.h>
4
5 #include "kbd-util.h"
6 #include "log.h"
7 #include "nulstr-util.h"
8 #include "path-util.h"
9 #include "set.h"
10 #include "string-util.h"
11 #include "strv.h"
12 #include "utf8.h"
13
14 static thread_local Set *keymaps = NULL;
15
16 static 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
55 int 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
91 bool 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 }