Accepting request 536877 from Base:System

1

OBS-URL: https://build.opensuse.org/request/show/536877
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/systemd?expand=0&rev=264
This commit is contained in:
Dominique Leuenberger 2017-10-28 12:19:43 +00:00 committed by Git OBS Bridge
commit 5bb754e78e
6 changed files with 561 additions and 2 deletions

View File

@ -0,0 +1,525 @@
From 349fd7b2fe35d2fd6c7ba6493d2e44ae93013804 Mon Sep 17 00:00:00 2001
From: Thomas Blume <Thomas.Blume@suse.com>
Date: Wed, 18 Oct 2017 12:30:03 +0200
Subject: [PATCH 1/1] systemd-firstboot: add vconsole keymap support
yast installer needs systemd-firstboot support for setting the keymap
This is a temporary patch to be superseded when upstream commit is available,
see https://github.com/systemd/systemd/pull/7035 for the relevant PR.
[tblume: fixes bsc#1046436]
---
src/basic/locale-util.c | 95 +++++++++++++++++++++++++++++++++++
src/basic/locale-util.h | 3 ++
src/firstboot/firstboot.c | 117 ++++++++++++++++++++++++++++++++++++++++++--
src/locale/localectl.c | 65 +++---------------------
src/test/test-locale-util.c | 29 +++++++++++
5 files changed, 247 insertions(+), 62 deletions(-)
diff --git a/src/basic/locale-util.c b/src/basic/locale-util.c
index ada0a28cd..f3fa918b8 100644
--- a/src/basic/locale-util.c
+++ b/src/basic/locale-util.c
@@ -20,6 +20,7 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <ftw.h>
#include <langinfo.h>
#include <libintl.h>
#include <locale.h>
@@ -30,6 +31,7 @@
#include <sys/mman.h>
#include <sys/stat.h>
+#include "def.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "hashmap.h"
@@ -270,6 +272,99 @@ out:
return (bool) cached_answer;
}
+static thread_local Set *keymaps = NULL;
+
+static int nftw_cb(
+ const char *fpath,
+ const struct stat *sb,
+ int tflag,
+ struct FTW *ftwbuf) {
+
+ char *p, *e;
+ int r;
+
+ if (tflag != FTW_F)
+ return 0;
+
+ if (!endswith(fpath, ".map") &&
+ !endswith(fpath, ".map.gz"))
+ return 0;
+
+ p = strdup(basename(fpath));
+ if (!p)
+ return FTW_STOP;
+
+ e = endswith(p, ".map");
+ if (e)
+ *e = 0;
+
+ e = endswith(p, ".map.gz");
+ if (e)
+ *e = 0;
+
+ r = set_consume(keymaps, p);
+ if (r < 0 && r != -EEXIST)
+ return r;
+
+ return 0;
+}
+
+int get_keymaps(char ***ret) {
+ _cleanup_strv_free_ char **l = NULL;
+ const char *dir;
+ int r;
+
+ keymaps = set_new(&string_hash_ops);
+ if (!keymaps)
+ return -ENOMEM;
+
+ NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) {
+ r = nftw(dir, nftw_cb, 20, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
+
+ if (r == FTW_STOP)
+ log_debug("Directory not found %s", dir);
+ else if (r < 0)
+ log_debug_errno(r, "Can't add keymap: %m");
+ }
+
+ l = set_get_strv(keymaps);
+ if (!l) {
+ set_free_free(keymaps);
+ return -ENOMEM;
+ }
+
+ set_free(keymaps);
+
+ if (strv_isempty(l))
+ return -ENOENT;
+
+ strv_sort(l);
+
+ *ret = l;
+ l = NULL;
+
+ return 0;
+}
+
+bool keymap_is_valid(const char *name) {
+
+ if (isempty(name))
+ return false;
+
+ if (strlen(name) >= 128)
+ return false;
+
+ if (!utf8_is_valid(name))
+ return false;
+
+ if (!filename_is_valid(name))
+ return false;
+
+ if (!string_is_safe(name))
+ return false;
+
+ return true;
+}
const char *special_glyph(SpecialGlyph code) {
diff --git a/src/basic/locale-util.h b/src/basic/locale-util.h
index 0630a034a..104864501 100644
--- a/src/basic/locale-util.h
+++ b/src/basic/locale-util.h
@@ -71,3 +71,6 @@ const char *special_glyph(SpecialGlyph code) _const_;
const char* locale_variable_to_string(LocaleVariable i) _const_;
LocaleVariable locale_variable_from_string(const char *s) _pure_;
+
+int get_keymaps(char ***l);
+bool keymap_is_valid(const char *name);
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index b3578d3e1..fd60ee518 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -44,16 +44,19 @@
static char *arg_root = NULL;
static char *arg_locale = NULL; /* $LANG */
+static char *arg_keymap = NULL;
static char *arg_locale_messages = NULL; /* $LC_MESSAGES */
static char *arg_timezone = NULL;
static char *arg_hostname = NULL;
static sd_id128_t arg_machine_id = {};
static char *arg_root_password = NULL;
static bool arg_prompt_locale = false;
+static bool arg_prompt_keymap = false;
static bool arg_prompt_timezone = false;
static bool arg_prompt_hostname = false;
static bool arg_prompt_root_password = false;
static bool arg_copy_locale = false;
+static bool arg_copy_keymap = false;
static bool arg_copy_timezone = false;
static bool arg_copy_root_password = false;
@@ -285,6 +288,80 @@ static int process_locale(void) {
return 0;
}
+static int prompt_keymap(void) {
+ _cleanup_strv_free_ char **kmaps = NULL;
+ int r;
+
+ if (arg_keymap)
+ return 0;
+
+ if (!arg_prompt_keymap)
+ return 0;
+
+ r = get_keymaps(&kmaps);
+ if (r < 0)
+ return log_error_errno(r, "Cannot query keymap list: %m");
+
+ print_welcome();
+
+ printf("\nAvailable keymaps:\n\n");
+ r = show_menu(kmaps, 3, 22, 60);
+ if (r < 0)
+ return r;
+
+ putchar('\n');
+
+ r = prompt_loop("Please enter system keymap name or number", kmaps, keymap_is_valid, &arg_keymap);
+ if (r < 0)
+ return r;
+
+ if (isempty(arg_keymap))
+ return 0;
+
+ return 0;
+}
+
+static int process_keymap(void) {
+ const char *etc_vconsoleconf;
+ char **keymap;
+ int r;
+
+ etc_vconsoleconf = prefix_roota(arg_root, "/etc/vconsole.conf");
+ if (laccess(etc_vconsoleconf, F_OK) >= 0)
+ return 0;
+
+ if (arg_copy_keymap && arg_root) {
+
+ mkdir_parents(etc_vconsoleconf, 0755);
+ r = copy_file("/etc/vconsole.conf", etc_vconsoleconf, 0, 0644, 0, COPY_REFLINK);
+ if (r != -ENOENT) {
+ if (r < 0)
+ return log_error_errno(r, "Failed to copy %s: %m", etc_vconsoleconf);
+
+ log_info("%s copied.", etc_vconsoleconf);
+ return 0;
+ }
+ }
+
+ r = prompt_keymap();
+ if (r < 0)
+ return r;
+
+ if (!isempty(arg_keymap))
+ keymap = STRV_MAKE(strjoina("KEYMAP=", arg_keymap));
+
+ if (!keymap)
+ return 0;
+
+ mkdir_parents(etc_vconsoleconf, 0755);
+ r = write_env_file(etc_vconsoleconf, keymap);
+ if (r < 0)
+ return log_error_errno(r, "Failed to write %s: %m", etc_vconsoleconf);
+
+ log_info("%s written.", etc_vconsoleconf);
+ return 0;
+}
+
static int prompt_timezone(void) {
_cleanup_strv_free_ char **zones = NULL;
int r;
@@ -611,20 +688,23 @@ static void help(void) {
" --root=PATH Operate on an alternate filesystem root\n"
" --locale=LOCALE Set primary locale (LANG=)\n"
" --locale-messages=LOCALE Set message locale (LC_MESSAGES=)\n"
+ " --keymap=KEYMAP Set keymap\n"
" --timezone=TIMEZONE Set timezone\n"
" --hostname=NAME Set host name\n"
" --machine-ID=ID Set machine ID\n"
" --root-password=PASSWORD Set root password\n"
" --root-password-file=FILE Set root password from file\n"
" --prompt-locale Prompt the user for locale settings\n"
+ " --prompt-keymap Prompt the user for keymap settings\n"
" --prompt-timezone Prompt the user for timezone\n"
" --prompt-hostname Prompt the user for hostname\n"
" --prompt-root-password Prompt the user for root password\n"
" --prompt Prompt for all of the above\n"
" --copy-locale Copy locale from host\n"
+ " --copy-keymap Copy keymap from host\n"
" --copy-timezone Copy timezone from host\n"
" --copy-root-password Copy root password from host\n"
- " --copy Copy locale, timezone, root password\n"
+ " --copy Copy locale, keymap, timezone, root password\n"
" --setup-machine-id Generate a new random machine ID\n"
, program_invocation_short_name);
}
@@ -636,6 +716,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_ROOT,
ARG_LOCALE,
ARG_LOCALE_MESSAGES,
+ ARG_KEYMAP,
ARG_TIMEZONE,
ARG_HOSTNAME,
ARG_MACHINE_ID,
@@ -643,11 +724,13 @@ static int parse_argv(int argc, char *argv[]) {
ARG_ROOT_PASSWORD_FILE,
ARG_PROMPT,
ARG_PROMPT_LOCALE,
+ ARG_PROMPT_KEYMAP,
ARG_PROMPT_TIMEZONE,
ARG_PROMPT_HOSTNAME,
ARG_PROMPT_ROOT_PASSWORD,
ARG_COPY,
ARG_COPY_LOCALE,
+ ARG_COPY_KEYMAP,
ARG_COPY_TIMEZONE,
ARG_COPY_ROOT_PASSWORD,
ARG_SETUP_MACHINE_ID,
@@ -659,6 +742,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "root", required_argument, NULL, ARG_ROOT },
{ "locale", required_argument, NULL, ARG_LOCALE },
{ "locale-messages", required_argument, NULL, ARG_LOCALE_MESSAGES },
+ { "keymap", required_argument, NULL, ARG_KEYMAP },
{ "timezone", required_argument, NULL, ARG_TIMEZONE },
{ "hostname", required_argument, NULL, ARG_HOSTNAME },
{ "machine-id", required_argument, NULL, ARG_MACHINE_ID },
@@ -666,11 +750,13 @@ static int parse_argv(int argc, char *argv[]) {
{ "root-password-file", required_argument, NULL, ARG_ROOT_PASSWORD_FILE },
{ "prompt", no_argument, NULL, ARG_PROMPT },
{ "prompt-locale", no_argument, NULL, ARG_PROMPT_LOCALE },
+ { "prompt-keymap", no_argument, NULL, ARG_PROMPT_KEYMAP },
{ "prompt-timezone", no_argument, NULL, ARG_PROMPT_TIMEZONE },
{ "prompt-hostname", no_argument, NULL, ARG_PROMPT_HOSTNAME },
{ "prompt-root-password", no_argument, NULL, ARG_PROMPT_ROOT_PASSWORD },
{ "copy", no_argument, NULL, ARG_COPY },
{ "copy-locale", no_argument, NULL, ARG_COPY_LOCALE },
+ { "copy-keymap", no_argument, NULL, ARG_COPY_KEYMAP },
{ "copy-timezone", no_argument, NULL, ARG_COPY_TIMEZONE },
{ "copy-root-password", no_argument, NULL, ARG_COPY_ROOT_PASSWORD },
{ "setup-machine-id", no_argument, NULL, ARG_SETUP_MACHINE_ID },
@@ -723,6 +809,18 @@ static int parse_argv(int argc, char *argv[]) {
break;
+ case ARG_KEYMAP:
+ if (!keymap_is_valid(optarg)) {
+ log_error("Keymap %s is not valid.", optarg);
+ return -EINVAL;
+ }
+
+ r = free_and_strdup(&arg_keymap, optarg);
+ if (r < 0)
+ return log_oom();
+
+ break;
+
case ARG_TIMEZONE:
if (!timezone_is_valid(optarg)) {
log_error("Timezone %s is not valid.", optarg);
@@ -772,13 +870,17 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_PROMPT:
- arg_prompt_locale = arg_prompt_timezone = arg_prompt_hostname = arg_prompt_root_password = true;
+ arg_prompt_locale = arg_prompt_keymap = arg_prompt_timezone = arg_prompt_hostname = arg_prompt_root_password = true;
break;
case ARG_PROMPT_LOCALE:
arg_prompt_locale = true;
break;
+ case ARG_PROMPT_KEYMAP:
+ arg_prompt_keymap = true;
+ break;
+
case ARG_PROMPT_TIMEZONE:
arg_prompt_timezone = true;
break;
@@ -792,13 +894,17 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_COPY:
- arg_copy_locale = arg_copy_timezone = arg_copy_root_password = true;
+ arg_copy_locale = arg_copy_keymap = arg_copy_timezone = arg_copy_root_password = true;
break;
case ARG_COPY_LOCALE:
arg_copy_locale = true;
break;
+ case ARG_COPY_KEYMAP:
+ arg_copy_keymap = true;
+ break;
+
case ARG_COPY_TIMEZONE:
arg_copy_timezone = true;
break;
@@ -853,6 +959,10 @@ int main(int argc, char *argv[]) {
if (r < 0)
goto finish;
+ r = process_keymap();
+ if (r < 0)
+ goto finish;
+
r = process_timezone();
if (r < 0)
goto finish;
@@ -873,6 +983,7 @@ finish:
free(arg_root);
free(arg_locale);
free(arg_locale_messages);
+ free(arg_keymap);
free(arg_timezone);
free(arg_hostname);
string_erase(arg_root_password);
diff --git a/src/locale/localectl.c b/src/locale/localectl.c
index 0bd18a5c0..efdd73a8f 100644
--- a/src/locale/localectl.c
+++ b/src/locale/localectl.c
@@ -273,68 +273,15 @@ static int set_vconsole_keymap(sd_bus *bus, char **args, unsigned n) {
return r;
}
-static Set *keymaps = NULL;
-
-static int nftw_cb(
- const char *fpath,
- const struct stat *sb,
- int tflag,
- struct FTW *ftwbuf) {
-
- char *p, *e;
- int r;
-
- if (tflag != FTW_F)
- return 0;
-
- if (!endswith(fpath, ".map") &&
- !endswith(fpath, ".map.gz"))
- return 0;
-
- p = strdup(basename(fpath));
- if (!p)
- return log_oom();
-
- e = endswith(p, ".map");
- if (e)
- *e = 0;
-
- e = endswith(p, ".map.gz");
- if (e)
- *e = 0;
-
- r = set_consume(keymaps, p);
- if (r < 0 && r != -EEXIST)
- return log_error_errno(r, "Can't add keymap: %m");
-
- return 0;
-}
-
static int list_vconsole_keymaps(sd_bus *bus, char **args, unsigned n) {
- _cleanup_strv_free_ char **l = NULL;
- const char *dir;
-
- keymaps = set_new(&string_hash_ops);
- if (!keymaps)
- return log_oom();
-
- NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS)
- nftw(dir, nftw_cb, 20, FTW_MOUNT|FTW_PHYS);
-
- l = set_get_strv(keymaps);
- if (!l) {
- set_free_free(keymaps);
- return log_oom();
- }
-
- set_free(keymaps);
+ _cleanup_strv_free_ char **l = NULL;
+ int r;
- if (strv_isempty(l)) {
- log_error("Couldn't find any console keymaps.");
- return -ENOENT;
- }
+ assert(args);
- strv_sort(l);
+ r = get_keymaps(&l);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read list of keymaps: %m");
pager_open(arg_no_pager, false);
diff --git a/src/test/test-locale-util.c b/src/test/test-locale-util.c
index 427c698d1..e6876c82e 100644
--- a/src/test/test-locale-util.c
+++ b/src/test/test-locale-util.c
@@ -50,9 +50,38 @@ static void test_locale_is_valid(void) {
assert_se(!locale_is_valid("\x01gar\x02 bage\x03"));
}
+static void test_get_keymaps(void) {
+ _cleanup_strv_free_ char **kmaps = NULL;
+ char **p;
+ int r;
+
+ r = get_keymaps(&kmaps);
+ assert_se(r >= 0);
+ assert_se(kmaps);
+
+ STRV_FOREACH(p, kmaps) {
+ puts(*p);
+ assert_se(keymap_is_valid(*p));
+ }
+}
+
+static void test_keymap_is_valid(void) {
+ assert_se(keymap_is_valid("uk"));
+ assert_se(keymap_is_valid("de-nodeadkeys"));
+ assert_se(keymap_is_valid("ANSI-dvorak"));
+ assert_se(keymap_is_valid("unicode"));
+
+ assert_se(!keymap_is_valid(""));
+ assert_se(!keymap_is_valid("/usr/bin/foo"));
+ assert_se(!keymap_is_valid("\x01gar\x02 bage\x03"));
+}
+
int main(int argc, char *argv[]) {
test_get_locales();
test_locale_is_valid();
+ test_get_keymaps();
+ test_keymap_is_valid();
+
return 0;
}
--
2.14.2

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6fd8f4674008055ae6b3fb870e84fbd64f53c1edaf43c84d95d7a9b6b7bec00b
size 3351212
oid sha256:42bf64dac8b5fa739b53c12c5cba492340b09ebdc78890cd429088158f95e285
size 3352176

View File

@ -1,3 +1,19 @@
-------------------------------------------------------------------
Thu Oct 26 12:29:29 UTC 2017 - fbui@suse.com
- Import commit e44237e76f6e133e62ff6c681d3fd06ebf12f66d
a4e02c099 udev-rules: all values can contain escaped double quotes now (#6890)
d2b767a76 tmpfiles: remove old ICE and X11 sockets at boot (#6979)
-------------------------------------------------------------------
Thu Oct 19 07:47:16 UTC 2017 - fbui@suse.com
- Add 0001-systemd-firstboot-add-vconsole-keymap-support.patch (bsc#1046436)
Temporary patch until it's been merged by upstream, see
https://github.com/systemd/systemd/pull/7035
-------------------------------------------------------------------
Fri Oct 6 07:44:38 UTC 2017 - fbui@suse.com

View File

@ -163,6 +163,7 @@ Source1065: udev-remount-tmpfs
# patches are temporary and should be removed as soon as a fix is
# merged by upstream.
Patch1: 0001-core-disable-session-keyring-per-system-sevice-entir.patch
Patch2: 0001-systemd-firstboot-add-vconsole-keymap-support.patch
%description
Systemd is a system and service manager, compatible with SysV and LSB

View File

@ -1,3 +1,19 @@
-------------------------------------------------------------------
Thu Oct 26 12:29:29 UTC 2017 - fbui@suse.com
- Import commit e44237e76f6e133e62ff6c681d3fd06ebf12f66d
a4e02c099 udev-rules: all values can contain escaped double quotes now (#6890)
d2b767a76 tmpfiles: remove old ICE and X11 sockets at boot (#6979)
-------------------------------------------------------------------
Thu Oct 19 07:47:16 UTC 2017 - fbui@suse.com
- Add 0001-systemd-firstboot-add-vconsole-keymap-support.patch (bsc#1046436)
Temporary patch until it's been merged by upstream, see
https://github.com/systemd/systemd/pull/7035
-------------------------------------------------------------------
Fri Oct 6 07:44:38 UTC 2017 - fbui@suse.com

View File

@ -161,6 +161,7 @@ Source1065: udev-remount-tmpfs
# patches are temporary and should be removed as soon as a fix is
# merged by upstream.
Patch1: 0001-core-disable-session-keyring-per-system-sevice-entir.patch
Patch2: 0001-systemd-firstboot-add-vconsole-keymap-support.patch
%description
Systemd is a system and service manager, compatible with SysV and LSB