]>
Commit | Line | Data |
---|---|---|
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 | ||
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 | } |