]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
locale: introduce VCContext and several helper functions for the struct
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 25 Jan 2023 03:11:40 +0000 (12:11 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 28 Jan 2023 05:47:36 +0000 (14:47 +0900)
No functional changes, preparation for later commits.

src/locale/localed-util.c
src/locale/localed-util.h
src/locale/localed.c
src/locale/test-localed-util.c

index e742a8d0b156e79260e739fd69a904ae7c68441e..9dccaf9d2b47f0134f872d0b18560fb07d3e8973 100644 (file)
@@ -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.");
 
index a3e763f8505a6e44899fc9762ccac6082c895368..6e4f270f4621e5ca6443c09479ec2c829cc70cc6 100644 (file)
@@ -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);
index 5b2dcb790453671e3cf527b14420339bf80fe021..4ba7dc1f7c71710e897f9a5e976c8ba979e825bc 100644 (file)
@@ -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));
 
index 3d96b3aa85bd3b1cc93ace5b7462bd8ed15fd6cf..d7089fa6c35ed5aca528a1fae83524871b360d61 100644 (file)
@@ -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) {