Skip to content

Commit 4f63208

Browse files
committed
DLPX-95602 X11 console Keymaps broken
1 parent cdd6630 commit 4f63208

File tree

1 file changed

+58
-4
lines changed

1 file changed

+58
-4
lines changed

files/common/usr/bin/delphix-startup-screen

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import curses.textpad
2525
import sys
2626
import signal
2727
import os
28+
import shutil
29+
import tempfile
2830
import logging
2931
import subprocess
3032
from typing import List, Any, Tuple, Generator
@@ -102,11 +104,63 @@ def get_keyboard_layout() -> str:
102104

103105
def set_keyboard_layout(layout: str) -> subprocess.CompletedProcess:
104106
"""
105-
Set the keyboard layout based on the user selection.
107+
Set the keyboard layout by editing /etc/default/keyboard and applying it with setupcon.
108+
This avoids localectl (which is disabled on Debian/Ubuntu builds).
109+
110+
Notes:
111+
- Does NOT trigger update-initramfs; only applies to the running system's console.
106112
"""
107-
cmd: List[str] = ['localectl', 'set-x11-keymap', layout, 'pc105']
108-
subprocess.run(cmd, shell=False, check=True)
109-
return subprocess.run('setupcon', shell=False, check=True)
113+
kb_path = "/etc/default/keyboard"
114+
kb_backup = kb_path + ".bak"
115+
116+
# Read current content (if file doesn't exist, start with a minimal stub)
117+
try:
118+
with open(kb_path, "r", encoding="utf-8") as f:
119+
lines = f.readlines()
120+
except FileNotFoundError:
121+
lines = [
122+
'XKBMODEL="pc105"\n',
123+
f'XKBLAYOUT="{layout}"\n',
124+
'XKBVARIANT=""\n',
125+
'XKBOPTIONS=""\n',
126+
'BACKSPACE="guess"\n',
127+
]
128+
else:
129+
# Update or append XKBLAYOUT line
130+
updated = False
131+
pattern = re.compile(r'^\s*XKBLAYOUT\s*=')
132+
for i, line in enumerate(lines):
133+
if pattern.match(line):
134+
lines[i] = f'XKBLAYOUT="{layout}"\n'
135+
updated = True
136+
break
137+
if not updated:
138+
# Append if not present
139+
lines.append(f'XKBLAYOUT="{layout}"\n')
140+
141+
# Atomic write with backup
142+
os.makedirs(os.path.dirname(kb_path), exist_ok=True)
143+
if os.path.exists(kb_path):
144+
shutil.copy2(kb_path, kb_backup)
145+
146+
fd, tmp = tempfile.mkstemp(prefix=".keyboard.", dir=os.path.dirname(kb_path))
147+
try:
148+
with os.fdopen(fd, "w", encoding="utf-8") as f:
149+
f.writelines(lines)
150+
os.replace(tmp, kb_path)
151+
except Exception:
152+
# Clean temp file and restore from backup if we wrote a partial file
153+
try:
154+
os.remove(tmp)
155+
except OSError:
156+
pass
157+
if os.path.exists(kb_backup):
158+
shutil.copy2(kb_backup, kb_path)
159+
raise
160+
161+
# Apply to current console immediately (does not affect serial consoles)
162+
# Use --force so it rebuilds/loads even if it thinks nothing changed.
163+
return subprocess.run(["setupcon", "--force"], shell=False, check=True)
110164

111165

112166
def get_valid_keyboard_layouts() -> List[str]:

0 commit comments

Comments
 (0)