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