Skip to content

Commit e260393

Browse files
authored
locale-util,kbd-util: several cleanups (systemd#37090)
2 parents 7065494 + 002ff90 commit e260393

File tree

7 files changed

+71
-39
lines changed

7 files changed

+71
-39
lines changed

src/basic/hashmap.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1805,6 +1805,23 @@ char** _hashmap_get_strv(HashmapBase *h) {
18051805
return sv;
18061806
}
18071807

1808+
char** set_to_strv(Set **s) {
1809+
assert(s);
1810+
1811+
/* This is similar to set_get_strv(), but invalidates the set on success. */
1812+
1813+
char **v = new(char*, set_size(*s) + 1);
1814+
if (!v)
1815+
return NULL;
1816+
1817+
for (char **p = v; (*p = set_steal_first(*s)); p++)
1818+
;
1819+
1820+
assert(set_isempty(*s));
1821+
*s = set_free(*s);
1822+
return v;
1823+
}
1824+
18081825
void* ordered_hashmap_next(OrderedHashmap *h, const void *key) {
18091826
struct ordered_hashmap_entry *e;
18101827
unsigned hash, idx;

src/basic/locale-util.c

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#include "strv.h"
2626
#include "utf8.h"
2727

28-
static char *normalize_locale(const char *name) {
28+
static char* normalize_locale(const char *name) {
2929
const char *e;
3030

3131
/* Locale names are weird: glibc has some magic rules when looking for the charset name on disk: it
@@ -93,18 +93,15 @@ static int add_locales_from_archive(Set *locales) {
9393
uint32_t locrec_offset;
9494
};
9595

96-
const struct locarhead *h;
97-
const struct namehashent *e;
98-
const void *p = MAP_FAILED;
99-
_cleanup_close_ int fd = -EBADF;
100-
size_t sz = 0;
101-
struct stat st;
10296
int r;
10397

104-
fd = open("/usr/lib/locale/locale-archive", O_RDONLY|O_NOCTTY|O_CLOEXEC);
98+
assert(locales);
99+
100+
_cleanup_close_ int fd = open("/usr/lib/locale/locale-archive", O_RDONLY|O_NOCTTY|O_CLOEXEC);
105101
if (fd < 0)
106102
return errno == ENOENT ? 0 : -errno;
107103

104+
struct stat st;
108105
if (fstat(fd, &st) < 0)
109106
return -errno;
110107

@@ -117,11 +114,12 @@ static int add_locales_from_archive(Set *locales) {
117114
if (file_offset_beyond_memory_size(st.st_size))
118115
return -EFBIG;
119116

120-
p = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
117+
void *p = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
121118
if (p == MAP_FAILED)
122119
return -errno;
123120

124-
h = (const struct locarhead *) p;
121+
const struct namehashent *e;
122+
const struct locarhead *h = p;
125123
if (h->magic != 0xde020109 ||
126124
h->namehash_offset + h->namehash_size > st.st_size ||
127125
h->string_offset + h->string_size > st.st_size ||
@@ -154,9 +152,9 @@ static int add_locales_from_archive(Set *locales) {
154152

155153
r = 0;
156154

157-
finish:
155+
finish:
158156
if (p != MAP_FAILED)
159-
munmap((void*) p, sz);
157+
munmap((void*) p, st.st_size);
160158

161159
return r;
162160
}
@@ -165,6 +163,8 @@ static int add_locales_from_libdir(Set *locales) {
165163
_cleanup_closedir_ DIR *dir = NULL;
166164
int r;
167165

166+
assert(locales);
167+
168168
dir = opendir("/usr/lib/locale");
169169
if (!dir)
170170
return errno == ENOENT ? 0 : -errno;
@@ -180,19 +180,18 @@ static int add_locales_from_libdir(Set *locales) {
180180
return -ENOMEM;
181181

182182
r = set_consume(locales, z);
183-
if (r < 0 && r != -EEXIST)
183+
if (r < 0)
184184
return r;
185185
}
186186

187187
return 0;
188188
}
189189

190190
int get_locales(char ***ret) {
191-
_cleanup_set_free_free_ Set *locales = NULL;
192-
_cleanup_strv_free_ char **l = NULL;
191+
_cleanup_set_free_ Set *locales = NULL;
193192
int r;
194193

195-
locales = set_new(&string_hash_ops);
194+
locales = set_new(&string_hash_ops_free);
196195
if (!locales)
197196
return -ENOMEM;
198197

@@ -213,31 +212,25 @@ int get_locales(char ***ret) {
213212
free(set_remove(locales, locale));
214213
}
215214

216-
l = set_get_strv(locales);
215+
_cleanup_strv_free_ char **l = set_to_strv(&locales);
217216
if (!l)
218217
return -ENOMEM;
219218

220-
/* Now, all elements are owned by strv 'l'. Hence, do not call set_free_free(). */
221-
locales = set_free(locales);
222-
223219
r = getenv_bool("SYSTEMD_LIST_NON_UTF8_LOCALES");
224-
if (IN_SET(r, -ENXIO, 0)) {
225-
char **a, **b;
220+
if (r <= 0) {
221+
if (!IN_SET(r, -ENXIO, 0))
222+
log_debug_errno(r, "Failed to parse $SYSTEMD_LIST_NON_UTF8_LOCALES as boolean, ignoring: %m");
226223

227224
/* Filter out non-UTF-8 locales, because it's 2019, by default */
228-
for (a = b = l; *a; a++) {
229-
230-
if (endswith(*a, "UTF-8") ||
231-
strstr(*a, ".UTF-8@"))
225+
char **b = l;
226+
STRV_FOREACH(a, l)
227+
if (endswith(*a, "UTF-8") || strstr(*a, ".UTF-8@"))
232228
*(b++) = *a;
233229
else
234230
free(*a);
235-
}
236231

237232
*b = NULL;
238-
239-
} else if (r < 0)
240-
log_debug_errno(r, "Failed to parse $SYSTEMD_LIST_NON_UTF8_LOCALES as boolean");
233+
}
241234

242235
strv_sort(l);
243236

src/basic/set.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ static inline char **set_get_strv(Set *s) {
114114
return _hashmap_get_strv(HASHMAP_BASE(s));
115115
}
116116

117+
char** set_to_strv(Set **s);
118+
117119
int _set_ensure_put(Set **s, const struct hash_ops *hash_ops, const void *key HASHMAP_DEBUG_PARAMS);
118120
#define set_ensure_put(s, hash_ops, key) _set_ensure_put(s, hash_ops, key HASHMAP_DEBUG_SRC_ARGS)
119121

src/basic/strv.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -861,7 +861,7 @@ int strv_compare(char * const *a, char * const *b) {
861861
return 0;
862862
}
863863

864-
bool strv_equal_ignore_order(char **a, char **b) {
864+
bool strv_equal_ignore_order(char * const *a, char * const *b) {
865865

866866
/* Just like strv_equal(), but doesn't care about the order of elements or about redundant entries
867867
* (i.e. it's even ok if the number of entries in the array differ, as long as the difference just

src/basic/strv.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ static inline bool strv_equal(char * const *a, char * const *b) {
9696
return strv_compare(a, b) == 0;
9797
}
9898

99-
bool strv_equal_ignore_order(char **a, char **b);
99+
bool strv_equal_ignore_order(char * const *a, char * const *b);
100100

101101
char** strv_new_internal(const char *x, ...) _sentinel_;
102102
char** strv_new_ap(const char *x, va_list ap);

src/shared/kbd-util.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,15 @@ static int keymap_recurse_dir_callback(
8383
}
8484

8585
int get_keymaps(char ***ret) {
86-
_cleanup_set_free_free_ Set *keymaps = NULL;
86+
_cleanup_set_free_ Set *keymaps = NULL;
8787
_cleanup_strv_free_ char **keymap_dirs = NULL;
8888
int r;
8989

9090
r = keymap_directories(&keymap_dirs);
9191
if (r < 0)
9292
return r;
9393

94-
keymaps = set_new(&string_hash_ops);
94+
keymaps = set_new(&string_hash_ops_free);
9595
if (!keymaps)
9696
return -ENOMEM;
9797

@@ -114,14 +114,10 @@ int get_keymaps(char ***ret) {
114114
log_debug_errno(r, "Failed to read keymap list from %s, ignoring: %m", *dir);
115115
}
116116

117-
_cleanup_strv_free_ char **l = set_get_strv(keymaps);
117+
_cleanup_strv_free_ char **l = set_to_strv(&keymaps);
118118
if (!l)
119119
return -ENOMEM;
120120

121-
keymaps = set_free(keymaps); /* If we got the strv above, then do a set_free() rather than
122-
* set_free_free() since the entries of the set are now owned by the
123-
* strv */
124-
125121
if (strv_isempty(l))
126122
return -ENOENT;
127123

src/test/test-set.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,4 +400,28 @@ TEST(set_fnmatch) {
400400
assert_se(!set_fnmatch(match, nomatch, "cccXX"));
401401
}
402402

403+
TEST(set_to_strv) {
404+
_cleanup_set_free_ Set *set = NULL;
405+
_cleanup_strv_free_ char **a = NULL;
406+
_cleanup_free_ char **b = NULL;
407+
char **v = STRV_MAKE("aaa", "bbb", "ccc");
408+
409+
ASSERT_NOT_NULL(a = set_to_strv(&set));
410+
ASSERT_TRUE(strv_isempty(a));
411+
ASSERT_NULL(set);
412+
a = strv_free(a);
413+
414+
ASSERT_OK(set_put_strdupv(&set, v));
415+
ASSERT_EQ(set_size(set), strv_length(v));
416+
417+
ASSERT_NOT_NULL(b = set_get_strv(set));
418+
ASSERT_EQ(strv_length(b), strv_length(v));
419+
ASSERT_TRUE(strv_equal_ignore_order(b, v));
420+
421+
ASSERT_NOT_NULL(a = set_to_strv(&set));
422+
ASSERT_EQ(strv_length(a), strv_length(v));
423+
ASSERT_TRUE(strv_equal_ignore_order(a, v));
424+
ASSERT_NULL(set);
425+
}
426+
403427
DEFINE_TEST_MAIN(LOG_INFO);

0 commit comments

Comments
 (0)