File kbd-setfont-check.patch of Package kbd

From f5695d3e69ddc9670dc7dd28107327aceda1ec70 Mon Sep 17 00:00:00 2001
From: Alexey Gladkov <legion@kernel.org>
Date: Fri, 13 Mar 2026 10:38:38 +0100
Subject: [PATCH] setfont: check whether console is suitable for font
 operations

Signed-off-by: Alexey Gladkov <legion@kernel.org>
---
 src/include/kbd/kfont.h   |  8 ++++++++
 src/libkfont/kdfontop.c   | 35 ++++++++++++++++++++++++++++++++---
 src/libkfont/libkfont.map |  9 +++++++++
 src/setfont.c             | 15 +++++++++++----
 4 files changed, 60 insertions(+), 7 deletions(-)

diff --git a/src/include/kbd/kfont.h b/src/include/kbd/kfont.h
index 67ad917..11bc97c 100644
--- a/src/include/kbd/kfont.h
+++ b/src/include/kbd/kfont.h
@@ -188,6 +188,14 @@ int kfont_put_font(struct kfont_context *ctx, int consolefd, unsigned char *buf,
 unsigned int kfont_get_fontsize(struct kfont_context *ctx, int consolefd)
 	KBD_ATTR_NONNULL(1);
 
+/*
+ * Check whether CONSOLEFD refers to a text-mode console suitable for
+ * font operations through KDFONTOP. The check is silent and returns 1
+ * if the console can be used, 0 otherwise.
+ */
+int kfont_is_font_console(struct kfont_context *ctx, int consolefd)
+	KBD_ATTR_NONNULL(1);
+
 /*
  * Restore font (doesn't work).
  */
diff --git a/src/libkfont/kdfontop.c b/src/libkfont/kdfontop.c
index 4f1f0d2..64d78ad 100644
--- a/src/libkfont/kdfontop.c
+++ b/src/libkfont/kdfontop.c
@@ -21,22 +21,30 @@
 #endif
 
 static int
-is_kd_text(struct kfont_context *ctx, int fd)
+is_kd_text_mode(struct kfont_context *ctx, int fd, int report_errors)
 {
 	unsigned int kd_mode;
 
 	if (ioctl(fd, KDGETMODE, &kd_mode)) {
-		KFONT_ERR(ctx, "ioctl(KDGETMODE): %m");
+		if (report_errors)
+			KFONT_ERR(ctx, "ioctl(KDGETMODE): %m");
 		return 0;
 	}
 
 	if (kd_mode == KD_TEXT)
 		return 1;
 
-	KFONT_ERR(ctx, _("Console is not in text mode"));
+	if (report_errors)
+		KFONT_ERR(ctx, _("Console is not in text mode"));
 	return 0;
 }
 
+static inline int
+is_kd_text(struct kfont_context *ctx, int fd)
+{
+	return is_kd_text_mode(ctx, fd, 1);
+}
+
 int
 kfont_restore_font(struct kfont_context *ctx, int fd)
 {
@@ -176,6 +184,27 @@ kfont_get_fontsize(struct kfont_context *ctx, int fd)
 	return 256;
 }
 
+int
+kfont_is_font_console(struct kfont_context *ctx, int fd)
+{
+	if (!is_kd_text_mode(ctx, fd, 0))
+		return 0;
+
+	struct console_font_op cfo = {
+		.op        = KD_FONT_OP_GET,
+		.flags     = 0,
+		.width     = 32,
+		.height    = 32,
+		.charcount = (sizeof(unsigned char) * MAXFONTSIZE) / (64 * 128 / 8),
+		.data      = NULL,
+	};
+
+	errno = 0;
+	ioctl(fd, KDFONTOP, &cfo);
+
+	return (errno != ENOSYS && errno != ENOTTY);
+}
+
 static int
 put_font_kdfontop(struct kfont_context *ctx, int consolefd, unsigned char *buf,
 		unsigned int count,
diff --git a/src/libkfont/libkfont.map b/src/libkfont/libkfont.map
index 0ea76d2..e89cd86 100644
--- a/src/libkfont/libkfont.map
+++ b/src/libkfont/libkfont.map
@@ -36,3 +36,12 @@ KFONT_1.0 {
   local:
     *;
 };
+
+/*
+ * symbols since kbd 2.9.0
+ */
+KFONT_2.9 {
+  global:
+    kfont_is_font_console;
+
+} KFONT_1.0;
diff --git a/src/setfont.c b/src/setfont.c
index dc336c1..8a80431 100644
--- a/src/setfont.c
+++ b/src/setfont.c
@@ -166,10 +166,8 @@ int main(int argc, char *argv[])
 {
 	const char *ifiles[MAXIFILES];
 	char *mfil, *ufil, *Ofil, *ofil, *omfil, *oufil, *console;
-	int ifilct = 0, fd, no_m, no_u;
+	int ifilct, fd, no_m, no_u, restore, check_console, ret, c;
 	unsigned int iunit, hwunit;
-	int restore = 0;
-	int ret, c;
 
 	struct kfont_context *kfont;
 
@@ -183,6 +181,7 @@ int main(int argc, char *argv[])
 		{ "-m, --consolemap <FILE>",         _("load console screen map ('none' means don't load it).") },
 		{ "-u, --unicodemap <FILE>",         _("load font unicode map ('none' means don't load it).") },
 		{ "-C, --console <DEV>",             _("the console device to be used.") },
+		{ "-c, --check",                     _("check whether console is suitable for font operations.") },
 		{ "-d, --double",                    _("double size of font horizontally and vertically.") },
 		{ "-f, --force",                     _("force load unicode map.") },
 		{ "-R, --reset",                     _("reset the screen font, size, and unicode map to the bootup defaults.") },
@@ -193,6 +192,7 @@ int main(int argc, char *argv[])
 	};
 
 	const struct kbd_option opts[] = {
+		{ "=c",  "check",             kbd_no_argument,       'c' },
 		{ "=d",  "double",            kbd_no_argument,       'd' },
 		{ "=f",  "force",             kbd_no_argument,       'f' },
 		{ "=R",  "reset",             kbd_no_argument,       'R' },
@@ -218,7 +218,8 @@ int main(int argc, char *argv[])
 
 	ifiles[0] = mfil = ufil = Ofil = ofil = omfil = oufil = NULL;
 	iunit = hwunit = 0;
-	no_m = no_u = 0;
+	ifilct = no_m = no_u = 0;
+	restore = check_console = 0;
 	console = NULL;
 
 	while ((c = kbd_getopt(argc, argv, opts)) != -1) {
@@ -271,6 +272,9 @@ int main(int argc, char *argv[])
 			case 'R':
 				restore = 1;
 				break;
+			case 'c':
+				check_console = 1;
+				break;
 			case 'd':
 				kfont_set_option(kfont, kfont_double_size);
 				break;
@@ -316,6 +320,9 @@ int main(int argc, char *argv[])
 	if ((fd = getfd(console)) < 0)
 		kbd_error(EX_OSERR, 0, _("Couldn't get a file descriptor referring to the console."));
 
+	if (check_console)
+		return kfont_is_font_console(kfont, fd) ? EX_OK : EXIT_FAILURE;
+
 	int kd_mode = -1;
 	if (!ioctl(fd, KDGETMODE, &kd_mode) && (kd_mode == KD_GRAPHICS)) {
 		/*
-- 
2.51.0

openSUSE Build Service is sponsored by