Line data Source code
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 610 : static int nftw_cb( 17 : const char *fpath, 18 : const struct stat *sb, 19 : int tflag, 20 : struct FTW *ftwbuf) { 21 : 22 610 : _cleanup_free_ char *p = NULL; 23 : char *e; 24 : int r; 25 : 26 610 : if (tflag != FTW_F) 27 24 : return 0; 28 : 29 586 : if (!endswith(fpath, ".map") && 30 586 : !endswith(fpath, ".map.gz")) 31 25 : return 0; 32 : 33 561 : p = strdup(basename(fpath)); 34 561 : if (!p) 35 0 : return FTW_STOP; 36 : 37 561 : e = endswith(p, ".map"); 38 561 : if (e) 39 0 : *e = 0; 40 : 41 561 : e = endswith(p, ".map.gz"); 42 561 : if (e) 43 561 : *e = 0; 44 : 45 561 : if (!keymap_is_valid(p)) 46 0 : return 0; 47 : 48 561 : r = set_consume(keymaps, TAKE_PTR(p)); 49 561 : if (r < 0 && r != -EEXIST) 50 0 : return r; 51 : 52 561 : return 0; 53 : } 54 : 55 1 : int get_keymaps(char ***ret) { 56 1 : _cleanup_strv_free_ char **l = NULL; 57 : const char *dir; 58 : int r; 59 : 60 1 : keymaps = set_new(&string_hash_ops); 61 1 : if (!keymaps) 62 0 : return -ENOMEM; 63 : 64 4 : NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) { 65 3 : r = nftw(dir, nftw_cb, 20, FTW_PHYS|FTW_ACTIONRETVAL); 66 : 67 3 : if (r == FTW_STOP) 68 0 : log_debug("Directory not found %s", dir); 69 3 : else if (r < 0) 70 2 : log_debug_errno(r, "Can't add keymap: %m"); 71 : } 72 : 73 1 : l = set_get_strv(keymaps); 74 1 : if (!l) { 75 0 : set_free_free(keymaps); 76 0 : return -ENOMEM; 77 : } 78 : 79 1 : set_free(keymaps); 80 : 81 1 : if (strv_isempty(l)) 82 0 : return -ENOENT; 83 : 84 1 : strv_sort(l); 85 : 86 1 : *ret = TAKE_PTR(l); 87 : 88 1 : return 0; 89 : } 90 : 91 1106 : bool keymap_is_valid(const char *name) { 92 : 93 1106 : if (isempty(name)) 94 1 : return false; 95 : 96 1105 : if (strlen(name) >= 128) 97 0 : return false; 98 : 99 1105 : if (!utf8_is_valid(name)) 100 0 : return false; 101 : 102 1105 : if (!filename_is_valid(name)) 103 1 : return false; 104 : 105 1104 : if (!string_is_safe(name)) 106 1 : return false; 107 : 108 1103 : return true; 109 : }