]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tree-wide: port various bits over to locale_is_installed() 15651/head
authorLennart Poettering <lennart@poettering.net>
Thu, 30 Apr 2020 16:32:44 +0000 (18:32 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 7 May 2020 15:24:22 +0000 (17:24 +0200)
src/firstboot/firstboot.c
src/home/homectl.c
src/locale/localed.c
src/login/pam_systemd.c

index 488e87beae644294904737d73be66ef1014e97d9..f9fdf7b1d7fc67c755856b81953018e37e1eb627 100644 (file)
@@ -205,6 +205,14 @@ static int prompt_loop(const char *text, char **l, unsigned percentage, bool (*i
         }
 }
 
+static bool locale_is_ok(const char *name) {
+
+        if (arg_root)
+                return locale_is_valid(name);
+
+        return locale_is_installed(name) > 0;
+}
+
 static int prompt_locale(void) {
         _cleanup_strv_free_ char **locales = NULL;
         int r;
@@ -238,7 +246,7 @@ static int prompt_locale(void) {
                 print_welcome();
 
                 r = prompt_loop("Please enter system locale name or number",
-                                locales, 60, locale_is_valid, &arg_locale);
+                                locales, 60, locale_is_ok, &arg_locale);
                 if (r < 0)
                         return r;
 
@@ -246,7 +254,7 @@ static int prompt_locale(void) {
                         return 0;
 
                 r = prompt_loop("Please enter system message locale name or number",
-                                locales, 60, locale_is_valid, &arg_locale_messages);
+                                locales, 60, locale_is_ok, &arg_locale_messages);
                 if (r < 0)
                         return r;
 
@@ -791,10 +799,6 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_LOCALE:
-                        if (!locale_is_valid(optarg))
-                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                                       "Locale %s is not valid.", optarg);
-
                         r = free_and_strdup(&arg_locale, optarg);
                         if (r < 0)
                                 return log_oom();
@@ -802,10 +806,6 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_LOCALE_MESSAGES:
-                        if (!locale_is_valid(optarg))
-                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                                       "Locale %s is not valid.", optarg);
-
                         r = free_and_strdup(&arg_locale_messages, optarg);
                         if (r < 0)
                                 return log_oom();
@@ -927,6 +927,14 @@ static int parse_argv(int argc, char *argv[]) {
                         assert_not_reached("Unhandled option");
                 }
 
+        /* We check if the specified locale strings are valid down here, so that we can take --root= into
+         * account when looking for the locale files. */
+
+        if (arg_locale && !locale_is_ok(arg_locale))
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Locale %s is not installed.", arg_locale);
+        if (arg_locale_messages && !locale_is_ok(arg_locale_messages))
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Locale %s is not installed.", arg_locale_messages);
+
         return 1;
 }
 
index c98bf8b5408f6d3571b7749144408f670f8f14f2..e1857b6923436dfa6e8738d5c1f7f0eb61bf6798 100644 (file)
@@ -2807,6 +2807,9 @@ static int parse_argv(int argc, char *argv[]) {
                         if (!locale_is_valid(optarg))
                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Locale '%s' is not valid.", optarg);
 
+                        if (locale_is_installed(optarg) <= 0)
+                                log_warning("Locale '%s' is not installed, accepting anyway.", optarg);
+
                         r = json_variant_set_field_string(&arg_identity_extra, "preferredLanguage", optarg);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to set preferredLanguage field: %m");
index acdf79fa6b3d1d0f18ad4111e74ba30509fed1dd..a6aa3bae8c86c418d154a8448b1a8bd0f0c67d19 100644 (file)
@@ -258,18 +258,57 @@ static int property_get_xkb(
         return -EINVAL;
 }
 
+static int process_locale_list_item(
+                const char *assignment,
+                char *new_locale[static _VARIABLE_LC_MAX],
+                sd_bus_error *error) {
+
+        assert(assignment);
+        assert(new_locale);
+
+        for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++) {
+                const char *name, *e;
+
+                assert_se(name = locale_variable_to_string(p));
+
+                e = startswith(assignment, name);
+                if (!e)
+                        continue;
+
+                if (*e != '=')
+                        continue;
+
+                e++;
+
+                if (!locale_is_valid(e))
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Locale %s is not valid, refusing.", e);
+                if (locale_is_installed(e) <= 0)
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Locale %s not installed, refusing.", e);
+                if (new_locale[p])
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Locale variable %s set twice, refusing.", name);
+
+                new_locale[p] = strdup(e);
+                if (!new_locale[p])
+                        return -ENOMEM;
+
+                return 0;
+        }
+
+        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Locale assignment %s not valid, refusing.", assignment);
+}
+
 static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *error) {
         _cleanup_(locale_variables_freep) char *new_locale[_VARIABLE_LC_MAX] = {};
         _cleanup_strv_free_ char **settings = NULL, **l = NULL;
         Context *c = userdata;
         bool modified = false;
-        int interactive, p, r;
+        int interactive, r;
         char **i;
 
         assert(m);
         assert(c);
 
-        r = bus_message_read_strv_extend(m, &l);
+        r = sd_bus_message_read_strv(m, &l);
         if (r < 0)
                 return r;
 
@@ -278,11 +317,13 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
                 return r;
 
         /* If single locale without variable name is provided, then we assume it is LANG=. */
-        if (strv_length(l) == 1 && !strchr(*l, '=')) {
-                if (!locale_is_valid(*l))
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Locale data.");
+        if (strv_length(l) == 1 && !strchr(l[0], '=')) {
+                if (!locale_is_valid(l[0]))
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid locale specification: %s", l[0]);
+                if (locale_is_installed(l[0]) <= 0)
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified locale is not installed: %s", l[0]);
 
-                new_locale[VARIABLE_LANG] = strdup(*l);
+                new_locale[VARIABLE_LANG] = strdup(l[0]);
                 if (!new_locale[VARIABLE_LANG])
                         return -ENOMEM;
 
@@ -291,31 +332,9 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
 
         /* Check whether a variable is valid */
         STRV_FOREACH(i, l) {
-                bool valid = false;
-
-                for (p = 0; p < _VARIABLE_LC_MAX; p++) {
-                        size_t k;
-                        const char *name;
-
-                        name = locale_variable_to_string(p);
-                        assert(name);
-
-                        k = strlen(name);
-                        if (startswith(*i, name) &&
-                            (*i)[k] == '=' &&
-                            locale_is_valid((*i) + k + 1)) {
-                                valid = true;
-
-                                new_locale[p] = strdup((*i) + k + 1);
-                                if (!new_locale[p])
-                                        return -ENOMEM;
-
-                                break;
-                        }
-                }
-
-                if (!valid)
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Locale data.");
+                r = process_locale_list_item(*i, new_locale, error);
+                if (r < 0)
+                        return r;
         }
 
         /* If LANG was specified, but not LANGUAGE, check if we should
@@ -338,7 +357,7 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
         }
 
         /* Merge with the current settings */
-        for (p = 0; p < _VARIABLE_LC_MAX; p++)
+        for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
                 if (!isempty(c->locale[p]) && isempty(new_locale[p])) {
                         new_locale[p] = strdup(c->locale[p]);
                         if (!new_locale[p])
@@ -347,7 +366,7 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
 
         locale_simplify(new_locale);
 
-        for (p = 0; p < _VARIABLE_LC_MAX; p++)
+        for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
                 if (!streq_ptr(c->locale[p], new_locale[p])) {
                         modified = true;
                         break;
@@ -372,7 +391,7 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
         if (r == 0)
                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
 
-        for (p = 0; p < _VARIABLE_LC_MAX; p++)
+        for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
                 free_and_replace(c->locale[p], new_locale[p]);
 
         r = locale_write_data(c, &settings);
index 84bea21ab7be0777899a2d35c5b56cecaab00471..b07773088e2b3fbb8fd003e86fdf49a384b7ad42 100644 (file)
@@ -580,9 +580,9 @@ static int apply_user_record_settings(pam_handle_t *handle, UserRecord *ur, bool
                 if (pam_getenv(handle, "LANG")) {
                         if (debug)
                                 pam_syslog(handle, LOG_DEBUG, "PAM environment variable $LANG already set, not changing based on user record.");
-                } else if (!locale_is_valid(ur->preferred_language)) {
+                } else if (locale_is_installed(ur->preferred_language) <= 0) {
                         if (debug)
-                                pam_syslog(handle, LOG_DEBUG, "Preferred language specified in user record is not valid locally, not setting $LANG.");
+                                pam_syslog(handle, LOG_DEBUG, "Preferred language specified in user record is not valid or not installed, not setting $LANG.");
                 } else {
                         _cleanup_free_ char *joined = NULL;