From ba4a886f2d0d4c5409fb0bd7ec7faaa080a2ac0b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 25 Jan 2023 12:11:40 +0900 Subject: locale: introduce VCContext and several helper functions for the struct No functional changes, preparation for later commits. --- src/locale/localed-util.c | 97 ++++++++++++++++++++++++++++++++---------- src/locale/localed-util.h | 12 +++++- src/locale/localed.c | 24 +++++------ src/locale/test-localed-util.c | 30 ++++++------- 4 files changed, 110 insertions(+), 53 deletions(-) (limited to 'src/locale') diff --git a/src/locale/localed-util.c b/src/locale/localed-util.c index e742a8d0b1..9dccaf9d2b 100644 --- a/src/locale/localed-util.c +++ b/src/locale/localed-util.c @@ -152,11 +152,65 @@ static void context_clear_x11(Context *c) { x11_context_clear(&c->x11_from_vc); } -static void context_clear_vconsole(Context *c) { - assert(c); +static void vc_context_clear(VCContext *vc) { + assert(vc); + + vc->keymap = mfree(vc->keymap); + vc->toggle = mfree(vc->toggle); +} + +static bool vc_context_isempty(const VCContext *vc) { + assert(vc); + + return + isempty(vc->keymap) && + isempty(vc->toggle); +} + +void vc_context_empty_to_null(VCContext *vc) { + assert(vc); + + /* Do not call vc_context_clear() for the passed object. */ + + vc->keymap = empty_to_null(vc->keymap); + vc->toggle = empty_to_null(vc->toggle); +} - c->vc_keymap = mfree(c->vc_keymap); - c->vc_keymap_toggle = mfree(c->vc_keymap_toggle); +bool vc_context_equal(const VCContext *a, const VCContext *b) { + assert(a); + assert(b); + + return + streq_ptr(a->keymap, b->keymap) && + streq_ptr(a->toggle, b->toggle); +} + +int vc_context_copy(VCContext *dest, const VCContext *src) { + bool modified; + int r; + + assert(dest); + + if (dest == src) + return 0; + + if (!src) { + modified = !vc_context_isempty(dest); + vc_context_clear(dest); + return modified; + } + + r = free_and_strdup(&dest->keymap, src->keymap); + if (r < 0) + return r; + modified = r > 0; + + r = free_and_strdup(&dest->toggle, src->toggle); + if (r < 0) + return r; + modified = modified || r > 0; + + return modified; } void context_clear(Context *c) { @@ -164,7 +218,7 @@ void context_clear(Context *c) { locale_context_clear(&c->locale_context); context_clear_x11(c); - context_clear_vconsole(c); + vc_context_clear(&c->vc); c->locale_cache = sd_bus_message_unref(c->locale_cache); c->x11_cache = sd_bus_message_unref(c->x11_cache); @@ -223,7 +277,7 @@ int vconsole_read_data(Context *c, sd_bus_message *m) { fd = RET_NERRNO(open("/etc/vconsole.conf", O_CLOEXEC | O_PATH)); if (fd == -ENOENT) { c->vc_stat = (struct stat) {}; - context_clear_vconsole(c); + vc_context_clear(&c->vc); return 0; } if (fd < 0) @@ -237,12 +291,12 @@ int vconsole_read_data(Context *c, sd_bus_message *m) { return 0; c->vc_stat = st; - context_clear_vconsole(c); + vc_context_clear(&c->vc); x11_context_clear(&c->x11_from_vc); return parse_env_file_fd(fd, "/etc/vconsole.conf", - "KEYMAP", &c->vc_keymap, - "KEYMAP_TOGGLE", &c->vc_keymap_toggle, + "KEYMAP", &c->vc.keymap, + "KEYMAP_TOGGLE", &c->vc.toggle, "XKBLAYOUT", &c->x11_from_vc.layout, "XKBMODEL", &c->x11_from_vc.model, "XKBVARIANT", &c->x11_from_vc.variant, @@ -380,11 +434,11 @@ int vconsole_write_data(Context *c) { if (r < 0 && r != -ENOENT) return r; - r = strv_env_assign(&l, "KEYMAP", empty_to_null(c->vc_keymap)); + r = strv_env_assign(&l, "KEYMAP", empty_to_null(c->vc.keymap)); if (r < 0) return r; - r = strv_env_assign(&l, "KEYMAP_TOGGLE", empty_to_null(c->vc_keymap_toggle)); + r = strv_env_assign(&l, "KEYMAP_TOGGLE", empty_to_null(c->vc.toggle)); if (r < 0) return r; @@ -542,7 +596,7 @@ int vconsole_convert_to_x11(Context *c) { * vconsole_write_data() if necessary. */ xc = context_get_x11_context_safe(c); - if (isempty(c->vc_keymap)) { + if (isempty(c->vc.keymap)) { modified = !x11_context_isempty(xc); context_clear_x11(c); } else { @@ -563,7 +617,7 @@ int vconsole_convert_to_x11(Context *c) { if (r == 0) break; - if (!streq(c->vc_keymap, a[0])) + if (!streq(c->vc.keymap, a[0])) continue; r = x11_context_copy(xc, @@ -589,7 +643,7 @@ int vconsole_convert_to_x11(Context *c) { strempty(xc->options)); else if (modified < 0) log_notice("X11 keyboard layout was not modified: no conversion found for \"%s\".", - c->vc_keymap); + c->vc.keymap); else log_debug("X11 keyboard layout did not need to be modified."); @@ -778,11 +832,8 @@ int x11_convert_to_vconsole(Context *c) { xc = context_get_x11_context_safe(c); if (isempty(xc->layout)) { - modified = - !isempty(c->vc_keymap) || - !isempty(c->vc_keymap_toggle); - - context_clear_vconsole(c); + modified = !vc_context_isempty(&c->vc); + vc_context_clear(&c->vc); } else { _cleanup_free_ char *new_keymap = NULL; int r; @@ -798,16 +849,16 @@ int x11_convert_to_vconsole(Context *c) { * that we couldn't find anything which matches the layout. */ log_notice("No conversion to virtual console map found for \"%s\".", xc->layout); - if (!streq_ptr(c->vc_keymap, new_keymap)) { - context_clear_vconsole(c); - c->vc_keymap = TAKE_PTR(new_keymap); + if (!streq_ptr(c->vc.keymap, new_keymap)) { + vc_context_clear(&c->vc); + c->vc.keymap = TAKE_PTR(new_keymap); modified = true; } } if (modified) log_info("Changing virtual console keymap to '%s' toggle '%s'", - strempty(c->vc_keymap), strempty(c->vc_keymap_toggle)); + strempty(c->vc.keymap), strempty(c->vc.toggle)); else log_debug("Virtual console keymap was not modified."); diff --git a/src/locale/localed-util.h b/src/locale/localed-util.h index a3e763f850..6e4f270f46 100644 --- a/src/locale/localed-util.h +++ b/src/locale/localed-util.h @@ -15,6 +15,11 @@ typedef struct X11Context { char *options; } X11Context; +typedef struct VCContext { + char *keymap; + char *toggle; +} VCContext; + typedef struct Context { sd_bus_message *locale_cache; LocaleContext locale_context; @@ -26,8 +31,7 @@ typedef struct Context { sd_bus_message *vc_cache; struct stat vc_stat; - char *vc_keymap; - char *vc_keymap_toggle; + VCContext vc; Hashmap *polkit_registry; } Context; @@ -39,6 +43,10 @@ int x11_context_copy(X11Context *dest, const X11Context *src); X11Context *context_get_x11_context_safe(Context *c); +void vc_context_empty_to_null(VCContext *vc); +bool vc_context_equal(const VCContext *a, const VCContext *b); +int vc_context_copy(VCContext *dest, const VCContext *src); + int find_converted_keymap(const X11Context *xc, char **ret); int find_legacy_keymap(const X11Context *xc, char **ret); int find_language_fallback(const char *lang, char **ret); diff --git a/src/locale/localed.c b/src/locale/localed.c index 5b2dcb7904..4ba7dc1f7c 100644 --- a/src/locale/localed.c +++ b/src/locale/localed.c @@ -118,9 +118,9 @@ static int property_get_vconsole( return r; if (streq(property, "VConsoleKeymap")) - return sd_bus_message_append_basic(reply, 's', c->vc_keymap); + return sd_bus_message_append_basic(reply, 's', c->vc.keymap); if (streq(property, "VConsoleKeymapToggle")) - return sd_bus_message_append_basic(reply, 's', c->vc_keymap_toggle); + return sd_bus_message_append_basic(reply, 's', c->vc.toggle); return -EINVAL; } @@ -367,17 +367,16 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er static int method_set_vc_keyboard(sd_bus_message *m, void *userdata, sd_bus_error *error) { Context *c = ASSERT_PTR(userdata); - const char *keymap, *keymap_toggle; int convert, interactive, r; + VCContext in; assert(m); - r = sd_bus_message_read(m, "ssbb", &keymap, &keymap_toggle, &convert, &interactive); + r = sd_bus_message_read(m, "ssbb", &in.keymap, &in.toggle, &convert, &interactive); if (r < 0) return bus_log_parse_error(r); - keymap = empty_to_null(keymap); - keymap_toggle = empty_to_null(keymap_toggle); + vc_context_empty_to_null(&in); r = vconsole_read_data(c, m); if (r < 0) { @@ -385,7 +384,7 @@ static int method_set_vc_keyboard(sd_bus_message *m, void *userdata, sd_bus_erro return sd_bus_error_set_errnof(error, r, "Failed to read virtual console keymap data: %m"); } - FOREACH_STRING(name, keymap ?: keymap_toggle, keymap ? keymap_toggle : NULL) { + FOREACH_STRING(name, in.keymap ?: in.toggle, in.keymap ? in.toggle : NULL) { r = keymap_exists(name); /* This also verifies that the keymap name is kosher. */ if (r < 0) { log_error_errno(r, "Failed to check keymap %s: %m", name); @@ -395,8 +394,7 @@ static int method_set_vc_keyboard(sd_bus_message *m, void *userdata, sd_bus_erro return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Keymap %s is not installed.", name); } - if (streq_ptr(keymap, c->vc_keymap) && - streq_ptr(keymap_toggle, c->vc_keymap_toggle)) + if (vc_context_equal(&c->vc, &in)) return sd_bus_reply_method_return(m, NULL); r = bus_verify_polkit_async( @@ -413,9 +411,9 @@ static int method_set_vc_keyboard(sd_bus_message *m, void *userdata, sd_bus_erro if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ - if (free_and_strdup(&c->vc_keymap, keymap) < 0 || - free_and_strdup(&c->vc_keymap_toggle, keymap_toggle) < 0) - return -ENOMEM; + r = vc_context_copy(&c->vc, &in); + if (r < 0) + return log_oom(); if (convert) { r = x11_read_data(c, m); @@ -445,7 +443,7 @@ static int method_set_vc_keyboard(sd_bus_message *m, void *userdata, sd_bus_erro } log_info("Changed virtual console keymap to '%s' toggle '%s'", - strempty(c->vc_keymap), strempty(c->vc_keymap_toggle)); + strempty(c->vc.keymap), strempty(c->vc.toggle)); (void) vconsole_reload(sd_bus_message_get_bus(m)); diff --git a/src/locale/test-localed-util.c b/src/locale/test-localed-util.c index 3d96b3aa85..d7089fa6c3 100644 --- a/src/locale/test-localed-util.c +++ b/src/locale/test-localed-util.c @@ -88,35 +88,35 @@ TEST(vconsole_convert_to_x11) { assert_se(xc->variant == NULL); log_info("/* test without variant, new mapping (es:) */"); - assert_se(free_and_strdup(&c.vc_keymap, "es") >= 0); + assert_se(free_and_strdup(&c.vc.keymap, "es") >= 0); assert_se(vconsole_convert_to_x11(&c) == 1); assert_se(streq(xc->layout, "es")); assert_se(xc->variant == NULL); log_info("/* test with known variant, new mapping (es:dvorak) */"); - assert_se(free_and_strdup(&c.vc_keymap, "es-dvorak") >= 0); + assert_se(free_and_strdup(&c.vc.keymap, "es-dvorak") >= 0); assert_se(vconsole_convert_to_x11(&c) == 1); assert_se(streq(xc->layout, "es")); assert_se(streq(xc->variant, "dvorak")); log_info("/* test with old mapping (fr:latin9) */"); - assert_se(free_and_strdup(&c.vc_keymap, "fr-latin9") >= 0); + assert_se(free_and_strdup(&c.vc.keymap, "fr-latin9") >= 0); assert_se(vconsole_convert_to_x11(&c) == 1); assert_se(streq(xc->layout, "fr")); assert_se(streq(xc->variant, "latin9")); log_info("/* test with a compound mapping (ru,us) */"); - assert_se(free_and_strdup(&c.vc_keymap, "ru") >= 0); + assert_se(free_and_strdup(&c.vc.keymap, "ru") >= 0); assert_se(vconsole_convert_to_x11(&c) == 1); assert_se(streq(xc->layout, "ru,us")); assert_se(xc->variant == NULL); log_info("/* test with a simple mapping (us) */"); - assert_se(free_and_strdup(&c.vc_keymap, "us") >= 0); + assert_se(free_and_strdup(&c.vc.keymap, "us") >= 0); assert_se(vconsole_convert_to_x11(&c) == 1); assert_se(streq(xc->layout, "us")); @@ -129,26 +129,26 @@ TEST(x11_convert_to_vconsole) { int r; log_info("/* test emptying first (:) */"); - assert_se(free_and_strdup(&c.vc_keymap, "foobar") >= 0); + assert_se(free_and_strdup(&c.vc.keymap, "foobar") >= 0); assert_se(x11_convert_to_vconsole(&c) == 1); - assert_se(c.vc_keymap == NULL); + assert_se(c.vc.keymap == NULL); log_info("/* test emptying second (:) */"); assert_se(x11_convert_to_vconsole(&c) == 0); - assert_se(c.vc_keymap == NULL); + assert_se(c.vc.keymap == NULL); log_info("/* test without variant, new mapping (es:) */"); assert_se(free_and_strdup(&xc->layout, "es") >= 0); assert_se(x11_convert_to_vconsole(&c) == 1); - assert_se(streq(c.vc_keymap, "es")); + assert_se(streq(c.vc.keymap, "es")); log_info("/* test with unknown variant, new mapping (es:foobar) */"); assert_se(free_and_strdup(&xc->variant, "foobar") >= 0); assert_se(x11_convert_to_vconsole(&c) == 0); - assert_se(streq(c.vc_keymap, "es")); + assert_se(streq(c.vc.keymap, "es")); log_info("/* test with known variant, new mapping (es:dvorak) */"); assert_se(free_and_strdup(&xc->variant, "dvorak") >= 0); @@ -160,28 +160,28 @@ TEST(x11_convert_to_vconsole) { } assert_se(r == 1); - assert_se(streq(c.vc_keymap, "es-dvorak")); + assert_se(streq(c.vc.keymap, "es-dvorak")); log_info("/* test with old mapping (fr:latin9) */"); assert_se(free_and_strdup(&xc->layout, "fr") >= 0); assert_se(free_and_strdup(&xc->variant, "latin9") >= 0); assert_se(x11_convert_to_vconsole(&c) == 1); - assert_se(streq(c.vc_keymap, "fr-latin9")); + assert_se(streq(c.vc.keymap, "fr-latin9")); log_info("/* test with a compound mapping (us,ru:) */"); assert_se(free_and_strdup(&xc->layout, "us,ru") >= 0); assert_se(free_and_strdup(&xc->variant, NULL) >= 0); assert_se(x11_convert_to_vconsole(&c) == 1); - assert_se(streq(c.vc_keymap, "us")); + assert_se(streq(c.vc.keymap, "us")); log_info("/* test with a compound mapping (ru,us:) */"); assert_se(free_and_strdup(&xc->layout, "ru,us") >= 0); assert_se(free_and_strdup(&xc->variant, NULL) >= 0); assert_se(x11_convert_to_vconsole(&c) == 1); - assert_se(streq(c.vc_keymap, "ru")); + assert_se(streq(c.vc.keymap, "ru")); /* https://bugzilla.redhat.com/show_bug.cgi?id=1333998 */ log_info("/* test with a simple new mapping (ru:) */"); @@ -189,7 +189,7 @@ TEST(x11_convert_to_vconsole) { assert_se(free_and_strdup(&xc->variant, NULL) >= 0); assert_se(x11_convert_to_vconsole(&c) == 0); - assert_se(streq(c.vc_keymap, "ru")); + assert_se(streq(c.vc.keymap, "ru")); } static int intro(void) { -- cgit v1.2.1